diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 8b990e9..18753e1 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -2,7 +2,7 @@ ## Overview -This repository contains the Python SDK for Azure Connectors. Code must follow Python best practices (PEP 8, PEP 484) and the team's conventions for async/await patterns, type safety, and API design. +This repository contains the Python SDK for Azure Connectors. Code must follow Python best practices (PEP 8, PEP 484) and the team's conventions for synchronous and asynchronous APIs, type safety, and API design. ## Client Refresh and Review @@ -13,6 +13,9 @@ This repository contains the Python SDK for Azure Connectors. Code must follow P - Capture known response data directly in semantic variables, without redundant `result` aliases or duplicated conditions. Check the actual returned shape after regeneration; an item list is not a response dictionary. - Preserve nullable-response guards such as `response and response.get(...)`; they are not duplicate conditions. Test non-pageable consumers with `None`, empty dictionaries, and populated responses separately. Do not simplify conditions by matching text prefixes. - Execute changed samples with empty and nonempty mocked results and assert their output, including absence of caught-and-printed errors. Pagination tests must exercise continuation requests, later-page items, and termination, including an empty initial page with a next link. +- Generate clients as atomic pairs: synchronous clients and shared declarations in `azure.connectors.`, and asynchronous clients in `azure.connectors.aio.`. +- Keep operation names and signatures aligned across modes without `_async` suffixes. Pageable operations return `ItemPaged` or `AsyncItemPaged`; long-running operation support remains deferred. +- Import generated clients from their connector modules. Do not add generated-client barrel exports to package `__init__.py` files. ## Quick Reference: Coding Style Rules @@ -397,31 +400,30 @@ When adding a new connector client to the SDK, use the **add-connector** skill ( ### Steps -1. **Create the connector module** in `src/azure/connectors/`: - - File name should match the connector API name (e.g., `office365.py`, `sharepointonline.py`) +1. **Generate the connector pair**: + - Root: `src/azure/connectors/.py` + - Async: `src/azure/connectors/aio/.py` -2. **Implement the client class** following existing patterns: - ```python - from azure.connectors.sdk import ConnectorClient - - class Office365Client(ConnectorClient): - """Client for Office 365 connector operations.""" - - async def send_email(self, ...) -> EmailResponse: - ... - ``` +2. **Verify matching client classes** following existing patterns: -3. **Export from `__init__.py`** — add the new client to `src/azure/connectors/__init__.py` + ```python + from azure.connectors.office365 import Office365Client, SendEmailInput + + from azure.connectors.aio.office365 import Office365Client as AsyncOffice365Client + ``` + +3. **Keep package initializers minimal** — do not add generated-client barrel exports 4. **Update `README.md`** — add the connector to the "Validated Connectors" table with status (`✅ E2E Validated` or `🔄 SDK Generated`) and test count -5. **Add unit tests** — create `test_.py` in `tests/` following the pattern of existing tests: - - Constructor tests - - Method tests with mocked responses - - Error handling tests - - Type serialization round-trips +5. **Add unit tests** — create `test_.py` in `tests/` following existing paired tests: + - Sync and aio constructors and lifecycle + - Matching operation names and signatures + - Mocked success and error behavior in both modes + - Shared model identity and serialization round-trips + - `ItemPaged` and `AsyncItemPaged` behavior when applicable -6. **Create sample usage file** — create `sample_connector_usage_.py` in `samples/sample_connector_usage/` following the pattern of existing samples (port from .NET if available) +6. **Create paired samples** — add the sync file under `samples/sample_connector_usage/` and the aio file under `samples/sample_connector_usage/aio/` 7. **Update `samples/sample_connector_usage/README.md`** — add the new sample to the samples table @@ -440,9 +442,10 @@ When adding a new connector client to the SDK, use the **add-connector** skill ( - [ ] Docstrings present on class and all public methods - [ ] Existing connector tests still pass (no regressions) - [ ] New connector tests cover: constructor, mocked success, mocked error, exception handling -- [ ] Module exported in `__init__.py` +- [ ] Root and aio modules expose matching unsuffixed operations +- [ ] Models and trigger metadata are root-owned and shared with aio - [ ] README.md connector table updated -- [ ] Sample file created and compiles without errors +- [ ] Sync and aio sample files compile without errors - [ ] Samples README updated - [ ] CHANGELOG.md updated - [ ] Connection setup skill updated diff --git a/.github/skills/add-connector/SKILL.md b/.github/skills/add-connector/SKILL.md index ab9e9e2..3bce111 100644 --- a/.github/skills/add-connector/SKILL.md +++ b/.github/skills/add-connector/SKILL.md @@ -1,6 +1,6 @@ --- name: add-connector -description: 'Add a new connector to the Azure Connectors Python SDK. USE WHEN: adding a new connector client, scaffolding connector files, creating unit tests, updating __init__.py exports, updating README status table, creating sample usage files. Covers the full workflow from connector file creation through test validation. NOT FOR: modifying existing connectors, connection setup, or trigger registration.' +description: 'Add a new connector to the Azure Connectors Python SDK. USE WHEN: adding a generated root/aio connector pair, creating paired unit tests and samples, or updating connector documentation. Covers the full workflow from generation through validation. NOT FOR: modifying existing connectors, connection setup, or trigger registration.' argument-hint: 'Provide the connector name (e.g., "dynamics365", "servicenow")' --- @@ -17,8 +17,8 @@ Automates the complete workflow for adding a new connector to the Azure Connecto ## Prerequisites -- The connector module file (e.g., `dynamics365.py`) is provided or needs to be created -- The connector follows the `ConnectorClientBase` pattern +- The connector can be generated as root and aio modules from one contract +- Both clients follow the matching `ConnectorClientBase` runtime patterns - A .NET sample exists to port to Python (optional) ## Procedure @@ -39,9 +39,12 @@ Collect the following details from the user: ### Step 2: Create/Verify Connector Module -Ensure the connector file exists at `src/azure/connectors/{connector_name}.py`. +Generate both files from one CodefulSdkGenerator invocation: -The connector must follow this structure: +- `src/azure/connectors/{connector_name}.py` +- `src/azure/connectors/aio/{connector_name}.py` + +The root connector owns shared declarations and the synchronous client: ```python # Copyright (c) Microsoft Corporation. All rights reserved. @@ -56,9 +59,8 @@ from typing import Optional, Any, Dict, List from urllib.parse import quote import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ConnectorClientBase, ConnectorException @@ -74,21 +76,18 @@ class {ClientClassName}(ConnectorClientBase): def connector_name(self) -> str: return "{connector_name}" - # ... async methods ... + # ... synchronous unsuffixed methods ... ``` -### Step 3: Update `__init__.py` Exports - -Add the connector import to `src/azure/connectors/__init__.py`: +The aio module imports and re-exports root models, aliases, enums, and +`TRIGGER_OPERATIONS`. Its client uses `AsyncTokenCredential`, +`AsyncHttpTransport`, and the same unsuffixed operations. Pageable operations +return `ItemPaged` from root and `AsyncItemPaged` from aio. -```python -try: - from .{connector_name} import {ClientClassName} -except (ImportError, NameError): - {ClientClassName} = None # type: ignore[assignment,misc] -``` +### Step 3: Keep Package Initializers Minimal -Also add to the `__all__` list if present. +Do not add generated clients to `azure.connectors` or `azure.connectors.aio` +package exports. Consumers import clients from each connector module. ### Step 4: Update README Connector Table @@ -113,9 +112,9 @@ from unittest.mock import AsyncMock, patch import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.{connector_name} import {ClientClassName} from azure.connectors.{connector_name} import ( - {ClientClassName}, - # Import all public dataclasses from the connector + {RequestModelName}, ) from azure.connectors.sdk import ConnectorException from tests.conftest import MockResponse @@ -216,7 +215,7 @@ class Test{ClientClassName}Lifecycle: # Follow the pattern: # # class Test{MethodName}: -# """Tests for {method_name}_async method.""" +# """Tests for {method_name} on the aio client.""" # # @pytest.mark.asyncio # async def test_success(self, mock_credential): @@ -230,16 +229,26 @@ class Test{ClientClassName}Lifecycle: ``` **Required test categories:** + 1. **Initialization tests** — constructor, URL handling, options, error cases 2. **Lifecycle tests** — close(), context manager -3. **Method tests** — one class per public async method with: - - Success case with mocked response - - Parameter handling tests - - Error response handling +3. **Method tests** — exercise matching root and aio operations with: + - Success cases with synchronous and asynchronous mocked responses + - Matching parameter and request-control signatures + - Error response handling in both modes + - Shared declaration identity + - Paging behavior for `ItemPaged` and `AsyncItemPaged`, when applicable ### Step 6: Create Sample Usage File -Create `samples/sample_connector_usage/sample_connector_usage_{connector_name}.py`: +Create both sample files: + +- `samples/sample_connector_usage/sample_connector_usage_{connector_name}.py` +- `samples/sample_connector_usage/aio/sample_connector_usage_{connector_name}.py` + +The following template shows the aio variant. The root variant uses +`azure.identity.DefaultAzureCredential`, imports its client from the root +connector module, uses `with`, and calls the same operations without `await`. ```python # Copyright (c) Microsoft Corporation. All rights reserved. @@ -268,9 +277,9 @@ import asyncio import os from azure.identity.aio import DefaultAzureCredential from azure.connectors import ConnectorException +from azure.connectors.aio.{connector_name} import {ClientClassName} from azure.connectors.{connector_name} import ( - {ClientClassName}, - # Import relevant dataclasses for the examples + {RequestModelName}, ) # Connection runtime URL format: @@ -290,7 +299,7 @@ async def example_1_basic_operation(): async with {ClientClassName}(CONNECTION_RUNTIME_URL, credential) as client: try: # Call a basic read operation - result = await client.{example_method}_async() + result = await client.{example_method}() print(f"Result: {{result}}") @@ -309,7 +318,7 @@ async def example_2_advanced_operation(): async with {ClientClassName}(CONNECTION_RUNTIME_URL, credential) as client: try: # Call a write or complex operation - # result = await client.{another_method}_async(...) + # result = await client.{another_method}(...) print("Advanced operation completed") except ConnectorException as ex: @@ -338,10 +347,11 @@ if __name__ == "__main__": ``` **When porting from .NET:** + 1. Find the corresponding .NET sample -2. Translate each example method to Python async/await syntax +2. Create matching synchronous and asynchronous examples 3. Convert C# types to Python dataclasses -4. Use `async with` for client lifecycle +4. Use `with` for root and `async with` for aio client lifecycle 5. Handle exceptions with `ConnectorException` ### Step 7: Update Samples README @@ -392,6 +402,7 @@ Execute the full test suite to validate: ``` **Required checks:** + - [ ] All tests pass - [ ] No import errors - [ ] Code quality tests pass (imports, structure) diff --git a/.github/skills/connection-setup/SKILL.md b/.github/skills/connection-setup/SKILL.md index eb3102d..3df3d91 100644 --- a/.github/skills/connection-setup/SKILL.md +++ b/.github/skills/connection-setup/SKILL.md @@ -178,21 +178,30 @@ az rest --method GET --uri "$runtimeUrl/v2/datasets" --resource "https://apihub. ## Next Steps -- **SDK usage:** Use the connection runtime URL with a caller-owned async Azure credential: - ```python - from azure.identity.aio import DefaultAzureCredential - - from azure.connectors.office365 import Office365Client, SendEmailInput - - async with DefaultAzureCredential() as credential: - async with Office365Client(runtime_url, credential) as client: - await client.send_email_async( - input=SendEmailInput( - to="recipient@example.com", - subject="Hello", - body="Sent with Azure Connectors.", - ) - ) - ``` +### SDK Usage + +Use the connection runtime URL with a caller-owned Azure credential. Root +clients are synchronous: + +```python +from azure.identity import DefaultAzureCredential + +from azure.connectors.office365 import Office365Client, SendEmailInput + +with DefaultAzureCredential() as credential: + with Office365Client(runtime_url, credential) as client: + client.send_email( + input=SendEmailInput( + to="recipient@example.com", + subject="Hello", + body="Sent with Azure Connectors.", + ) + ) +``` + +Asynchronous applications import the client from +`azure.connectors.aio.office365`, use `azure.identity.aio`, and await the same +unsuffixed `send_email` operation. Models remain in the root module. + - **Azure Functions triggers:** To register connector triggers (e.g., OnNewEmail, OnNewFile) for Azure Functions, use the [trigger-registration skill](../trigger-registration/SKILL.md). - **Azure Functions signatures:** For a complete mapping of trigger operations to Azure Functions signatures, see [Operations to Functions Signature Match](https://github.com/Azure/azure-functions-connector-extension/blob/main/docs/operations-functions-match.md). diff --git a/.github/skills/trigger-registration/SKILL.md b/.github/skills/trigger-registration/SKILL.md index 99b432d..87586f0 100644 --- a/.github/skills/trigger-registration/SKILL.md +++ b/.github/skills/trigger-registration/SKILL.md @@ -295,20 +295,21 @@ az functionapp log tail -g $resourceGroup -n $functionAppName ## Using the SDK for Actions (Beyond Triggers) -The `azure-connectors` package provides typed async clients for calling connector actions directly from Python applications. Generated clients require a caller-owned asynchronous Azure Identity credential or an `AzureKeyCredential`. +The `azure-connectors` package provides matching synchronous and asynchronous clients for calling connector actions directly from Python applications. Root clients use synchronous Azure Identity credentials; aio clients use asynchronous credentials. Both modes also accept `AzureKeyCredential`. ### Example: Send an email ```python from azure.identity.aio import DefaultAzureCredential -from azure.connectors.office365 import Office365Client, SendEmailInput +from azure.connectors.aio.office365 import Office365Client +from azure.connectors.office365 import SendEmailInput async def main(connection_url: str): async with DefaultAzureCredential() as credential: async with Office365Client(connection_url, credential) as client: - await client.send_email_async( + await client.send_email( input=SendEmailInput( to="recipient@example.com", subject="Hello from Python SDK", @@ -322,7 +323,7 @@ async def main(connection_url: str): ```python from azure.identity.aio import DefaultAzureCredential -from azure.connectors.sharepointonline import SharepointonlineClient +from azure.connectors.aio.sharepointonline import SharepointonlineClient async def list_items(connection_url: str): @@ -330,7 +331,7 @@ async def list_items(connection_url: str): async with SharepointonlineClient(connection_url, credential) as client: items = [ item - async for item in client.get_items_async( + async for item in client.get_items( dataset="https://contoso.sharepoint.com/sites/MySite", table="MyList", ) @@ -342,7 +343,8 @@ async def list_items(connection_url: str): ### Authentication Options -Use `DefaultAzureCredential` or `ManagedIdentityCredential` from `azure.identity.aio` for token authentication. Use `AzureKeyCredential` from `azure.core.credentials` when the connection runtime expects an API key. The caller owns asynchronous credentials and must close them. +Use credentials from `azure.identity` for root clients and `azure.identity.aio` for aio clients. Use `AzureKeyCredential` from `azure.core.credentials` when the connection runtime expects an API key. The caller owns credentials and must close them through the matching lifecycle. + ### E2E Validated Connectors | Connector | Package | Status | diff --git a/CHANGELOG.md b/CHANGELOG.md index f1c823e..3838727 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,25 +9,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- **Mapping-compatible model inputs** — generated request bodies and nested model fields now accept either generated dataclasses or arbitrary `Mapping` implementations. +- **Azure Core long-running operations** — generated Kusto and Plumsail operations with an HTTP 202 `Location` polling contract now use paired `begin_*` methods returning `LROPoller` or `AsyncLROPoller`. Polling honors `Retry-After` and forwards operation request controls. - **Generated API documentation site** — adds a MkDocs Material reference for the core SDK and every shipped connector module, strict source-to-site coverage validation, and a GitHub Pages deployment workflow for `main`. - **Zoho ZeptoMail generated client** — adds five public mail-agent, send-mail, template-mail, and analytics actions. `SendTemplateMailInput.merge_key_detail` remains `List[Dict[str, Any]]` so fixed string fields and arbitrary non-string merge values stay representable. The malformed Swagger type `ReplyToAddresss` is exposed as `ReplyToAddress` without changing the `reply_to` wire field. ### Breaking Changes -- **Generated clients now use the asynchronous Azure Core pipeline** — every client requires a caller-owned `AsyncTokenCredential` or `AzureKeyCredential`. The legacy token-provider classes and `ConnectorClientOptions` have been removed; retry, timeout, transport, and policy settings are passed directly to the client. Operations also expose keyword-only `timeout`, `headers`, `client_request_id`, and `response_hook` controls. +- **Swagger-required model fields are now required constructor arguments** — generated dataclasses no longer default required properties to `None`. +- **Read collection operations now return Azure Core pagers** — bounded read collections without continuation metadata use `ItemPaged` or `AsyncItemPaged`; mutation and action arrays remain eager operation payloads. +- **Client timeout configuration now uses `timeout`** — generated sync and aio + client constructors use the same keyword as per-operation request controls. +- **Location-backed operations now return pollers** — 44 Kusto and Plumsail operations move from immediate operation names to `begin_*`. Call `poller.result()` for root clients or await `poller.result()` for aio clients while the connector client remains open. +- **Generated clients now follow the Azure SDK sync/aio namespace convention** — synchronous clients live in `azure.connectors.` and asynchronous clients live in `azure.connectors.aio.`. Both surfaces use the same unsuffixed operation names. The previous root asynchronous clients and `_async` operation aliases are removed without compatibility shims. +- **Pageable operations now return Azure Core pagers** — root clients return `ItemPaged` and aio clients return `AsyncItemPaged`. Pager construction is not awaited; iterate normally or asynchronously, or use `by_page(continuation_token=...)` for page boundaries. +- **Generated models have one owner** — dataclasses, aliases, enums, and `TRIGGER_OPERATIONS` are defined in root connector modules and shared by aio modules. Import models from `azure.connectors.` in both modes. +- **Generated clients now use Azure Core pipelines** — root clients require a caller-owned `TokenCredential` or `AzureKeyCredential`, while aio clients require an `AsyncTokenCredential` or `AzureKeyCredential`. The legacy token-provider classes and `ConnectorClientOptions` have been removed; retry, timeout, transport, and policy settings are passed directly to the client. Operations also expose keyword-only `timeout`, `headers`, `client_request_id`, and `response_hook` controls. - **Automatic retries are now method-safe by default** — `GET`, `HEAD`, `OPTIONS`, and `TRACE` retain configured retries. `POST`, `PUT`, `PATCH`, `DELETE`, and unknown methods make one attempt for transient responses and transport errors. Set `retry_unsafe_http_methods=True` directly on a generated client only when replay is acceptable; retry count, timeout, and backoff settings are also direct client keyword arguments. ([#85](https://github.com/Azure/connectors-python-sdk/issues/85)) -- Jira `list_issues_async` now exposes the live optional `fields` query parameter +- Jira `list_issues` now exposes the live optional `fields` query parameter instead of sending an internal `fields=*all` default. Pass `fields` and `next_page_token` by keyword; `fields` precedes the token in the generated signature. -- This regeneration propagates the async-iterator paging contract to 32 additional +- This regeneration propagates the Azure Core paging contract to 32 additional connectors, extending [Fix Dataverse list pagination (#84)](https://github.com/Azure/connectors-python-sdk/pull/84). - Pageable operations return items rather than response dictionaries. Consume them - with `async for`, or collect them with - `[item async for item in client.get_items_async(...)]`; samples use this contract. + Pageable operations return items rather than response dictionaries. Iterate root + pagers with `for` and aio pagers with `async for`; samples use this contract. - Seismic Planner `CustomPropertyValues.localizations` now exposes `Dict[str, CustomPropertyDataDisplay]` instead of `Dict[str, Any]`. Callers can access typed values directly, such as `localizations["en-US"].name`. ([Azure/Connectors-NET-SDK#262](https://github.com/Azure/Connectors-NET-SDK/issues/262), AzureUX-BPM PR 17131877) -- Microsoft Dataverse `get_items_async` now returns an `AsyncIterator[dict[str, Any]]`. Callers must use `async for` instead of awaiting a single response dictionary; iteration preserves and follows `@odata.nextLink` until all rows are returned. ([Azure/Connectors-NET-SDK#208](https://github.com/Azure/Connectors-NET-SDK/issues/208), AzureUX-BPM PR 17086991) +- Microsoft Dataverse `get_items` now returns `ItemPaged[dict[str, Any]]` from root clients and `AsyncItemPaged[dict[str, Any]]` from aio clients. Iterate instead of awaiting a single response dictionary; paging preserves and follows `@odata.nextLink` until all rows are returned. ([Azure/Connectors-NET-SDK#208](https://github.com/Azure/Connectors-NET-SDK/issues/208), AzureUX-BPM PR 17086991) - Regenerated all 99 supported connector clients from current live managed connector metadata using the Azure Core contract generator. - Corrected generated parameter types across connector operations, including pagination values, numeric identifiers, and Boolean options. Callers must now pass the annotated `int` and `bool` values instead of string representations. @@ -35,6 +44,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Generated sync and aio operations now document their arguments, return types, + connector operation IDs, and `ConnectorException` failure contract. +- Generated connector clients are available as lazy exports from `azure.connectors` and `azure.connectors.aio`, with matching package type stubs for static analysis. +- Added a synchronous Azure Core runtime alongside the asynchronous runtime and generated 99 matching connector modules for each mode. +- Replaced the single asynchronous sample catalog with 99 synchronous root samples and 99 asynchronous `aio` samples using identical unsuffixed operation names. +- Expanded the generated API reference to publish separate sync and aio client and runtime sections. - Made `azure-identity` a required runtime dependency so Azure Identity credentials and the shipped samples work with the default package installation. - Updated all connector samples to match generated method signatures and added literal-type validation to the sample contract checks. - Added focused success, route, request-body, response, and error coverage for newly generated operations. @@ -42,14 +57,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- **Request timeout enforcement**: `timeout_seconds` and per-operation `timeout` - now bound the complete network operation, including retries, response loading, - and body reads across Azure Core async transports. Zero and negative values - disable SDK and transport deadlines. +- **Collection response contracts**: Mutation and action arrays execute eagerly and preserve their response envelopes instead of delaying the request behind a pager. Primitive read collections now expose `ItemPaged[str]` and `AsyncItemPaged[str]` rather than dictionary item types. +- **Finite polling delays**: Non-finite `Retry-After` values such as `Infinity`, `NaN`, and numeric overflow now use the finite default polling interval. +- **Collection paging classification**: Explicit pageable responses now infer omitted item properties and follow continuation fields present in the response schema. Bounded read envelopes select their primary array over auxiliary array metadata and expose Azure-guideline `list_*` operations returning `ItemPaged` or `AsyncItemPaged`; mutation and action arrays execute eagerly under their action names. +- **Caller continuation isolation**: Caller-provided `by_page()` continuation URLs now pass through the same origin normalization as service-provided next links, preventing authenticated requests from being sent to an arbitrary host. +- **HTTP DELETE contracts** — generated operations now preserve declared success payloads and ordinary HTTP 404 errors regardless of verb. Only explicitly curated resource deletions, currently ARM deployment deletion, treat an already absent target as idempotent success. +- **Orderful transaction responses** — `list_transactions` now preserves and returns the runtime JSON payload despite the managed connector Swagger omitting its response schema. +- **Relative continuation URLs** — pagers now resolve bare relative continuation links against the current page URL, preserving nested resource paths. +- **Azure Core exception compatibility**: `ConnectorException` now derives from `HttpResponseError` and exposes the failed response status, reason, headers, and body while preserving connector-specific operation and path details. +- **Generation provenance**: a pinned generator/compiler manifest records source metadata and canonical hashes for the complete 99-connector sync/aio catalog. +- **Request timeout enforcement**: Client-level and per-operation `timeout` + configures Azure Core retry and transport deadlines. Async clients also bound + the complete network operation, including response loading and body reads. + Sync clients now bound response-body loading as part of the same total deadline, + including time already spent receiving headers and responses that continuously + deliver small chunks. + Sync clients preserve transport timeouts for explicit policy chains without a + retry policy. + Sync clients no longer run timed requests on uncancellable daemon threads, so + closing a client cannot race a request still using its transport. Zero and + negative values disable SDK and transport deadlines. - **Async transport compatibility**: Empty buffered responses now produce normal snapshots and connector errors without re-reading consumed streams. Injected transports receive only supported timeout options and close through their asynchronous lifecycle. +- **Default transport configuration**: Standard Azure Core transport options, + including `connection_verify` and `connection_cert`, now configure the owned + Requests and aiohttp transports instead of being ignored. - **Explicit Azure Core policy chains**: `per_call_policies` and `per_retry_policies` now compose with an explicit `policies` chain instead of being silently discarded. Per-retry extensions require an `AsyncRetryPolicy`, @@ -65,7 +99,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Generated caller-supplied and internal-default query values escape reserved characters, including `/`, so paths, URLs, and collection values remain within their intended query parameters. -- **Microsoft Dataverse**: Corrected `create_attachment_async()` to accept GUID/string row IDs instead of integers. +- **Microsoft Dataverse**: Corrected `create_attachment()` to accept GUID/string row IDs instead of integers. ## [0.5.0b1] - 2026-08-31 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 30d3d11..d464139 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -99,14 +99,14 @@ This project follows Python best practices documented in [.github/copilot-instru - **PEP 8** — Standard Python style guide (79 character line limit) - **Type hints** — All public API signatures must have type hints (PEP 484) -- **Async/await** — Use async patterns for all I/O operations +- **Sync/aio parity** — Keep root synchronous and `.aio` asynchronous behavior aligned - **Naming conventions:** - `snake_case` for functions, methods, variables - `PascalCase` for classes - `UPPER_SNAKE_CASE` for constants - `_snake_case` for private methods/attributes - **Docstrings** — Google-style docstrings for all public APIs -- **Context managers** — Use `async with` for client lifecycle management +- **Context managers** — Use `with` for root clients and `async with` for aio clients ### Automated Enforcement @@ -121,7 +121,7 @@ Run `flake8 src/ tests/` locally before pushing to catch style issues early. ## Generated Code -Connector client files in `src/azure/connectors/*.py` (except `sdk/` subpackage) are produced by an internal Microsoft code generator that is not publicly accessible at this time. **Do not submit pull requests that directly modify generated files** — changes will be overwritten the next time the code is regenerated. +Connector client files in `src/azure/connectors/*.py` and `src/azure/connectors/aio/*.py` are produced by an internal Microsoft code generator. **Do not submit pull requests that directly modify generated files** — changes will be overwritten the next time the code is regenerated. If you find a bug or want to suggest an improvement in the generated code: @@ -133,6 +133,7 @@ If you find a bug or want to suggest an improvement in the generated code: **Files safe to modify:** - `src/azure/connectors/sdk/*.py` — Core SDK infrastructure (not generated) +- `src/azure/connectors/sdk/aio/*.py` — Async core SDK infrastructure (not generated) - `tests/*.py` — All test files - `samples/*.py` — Sample code - Documentation files (`.md` files) diff --git a/GENERATION.md b/GENERATION.md index f515862..6a2f5c7 100644 --- a/GENERATION.md +++ b/GENERATION.md @@ -7,9 +7,9 @@ This document describes how to generate typed Python connector clients using the The **CodefulSdkGenerator** tool generates typed Python clients from managed connector swagger definitions. The generated code provides: - **Type-safe contracts** - Dataclass models with proper JSON field mappings -- **Typed client classes** - Async methods for each connector action with comprehensive docstrings +- **Paired client classes** - Root sync and `.aio` async clients with identical unsuffixed operations - **Authentication handling** - Caller-owned Azure Core token or key credentials -- **Async/await support** - Native asyncio integration through the Azure Core pipeline +- **Azure Core paging** - `ItemPaged` and `AsyncItemPaged` for collection operations ## Prerequisites @@ -52,38 +52,41 @@ cd dotnet build .\src\tools\CodefulSdkGenerator\LogicAppsCompiler.Cli\LogicAppsCompiler.Cli.csproj -c Release ``` -The compiled executable will be at: +The compiled compiler assembly will be at: ```text -src\tools\CodefulSdkGenerator\LogicAppsCompiler.Cli\bin\Release\net8.0\LogicAppsCompiler.exe +src\tools\CodefulSdkGenerator\LogicAppsCompiler.Cli\bin\Release\net8.0\LogicAppsCompiler.dll ``` ## Generation Commands -Use the [live-download workflow](#live-regeneration-and-review) for every refresh -and review. The examples below show CLI argument forms, not permission to reuse -responses from an earlier run. +Capture live definitions only when intentionally refreshing the committed +Swagger inputs. Normal regeneration uses the reviewed snapshots in this +repository. ### Generate Python Client SDK (Recommended) -Generates typed async Python clients for calling connectors directly from Azure Functions: +Generates synchronous and asynchronous Python clients in one request: ```powershell # Generate all connectors -LogicAppsCompiler.exe --pythonDirectClient +dotnet LogicAppsCompiler.dll --pythonDirectClient # Generate specific connectors only -LogicAppsCompiler.exe --pythonDirectClient --connectors=office365,sharepointonline,teams +dotnet LogicAppsCompiler.dll --pythonDirectClient --connectors=office365,sharepointonline,teams # Example: Generate to this SDK repo's src/azure/connectors folder -LogicAppsCompiler.exe "/src/azure/connectors" --pythonDirectClient --connectors=office365 +dotnet LogicAppsCompiler.dll "/src/azure/connectors" --pythonDirectClient --connectors=office365 ``` **Output structure per connector:** -- `{connector}.py` - Combined dataclass models and client in one file (e.g., `office365.py`, `sharepointonline.py`) +- `{connector}.py` - Synchronous client plus shared models, aliases, enums, and trigger metadata +- `aio/{connector}.py` - Asynchronous client importing and re-exporting shared declarations from root -**Note:** The CLI accepts one positional output directory. Use `--pythonDirectClient` for Python generation. +The generator writes each pair atomically and removes both outputs if either +member fails. The CLI accepts one positional output directory. Use +`--pythonDirectClient` for Python generation. ### Generate C# DirectClient SDK @@ -97,12 +100,12 @@ LogicAppsCompiler.exe --directClient --connectors=office365 LogicAppsCompiler.exe --directClient --language=csharp --connectors=office365 ``` -## Live Regeneration and Review +## Catalog Regeneration -Refresh existing clients from live managed connector definitions. Set the source -subscription and region explicitly, and use a new empty temporary `ARMCACHE_PATH` -for every run. The generator's cache is only a transport implementation detail; -never seed it from repository fixtures or reuse a previous run's responses. +To refresh connector contracts, set the source subscription and region +explicitly and use a new empty temporary `ARMCACHE_PATH`. Generate into an +isolated output directory so the complete result can be reviewed before it +replaces the committed client catalog. ```powershell $env:AZURE_SUBSCRIPTION_ID = "" @@ -114,7 +117,8 @@ $liveCachePath = Join-Path $env:TEMP ("connector-live-" + [guid]::NewGuid()) New-Item -ItemType Directory -Path $liveCachePath, $outputDirectory -Force | Out-Null try { $env:ARMCACHE_PATH = $liveCachePath - LogicAppsCompiler.exe $outputDirectory --directClient --language=python "--connectors=$connectorNames" + dotnet LogicAppsCompiler.dll $outputDirectory --directClient --language=python ` + "--connectors=$connectorNames" } finally { $env:ARMCACHE_PATH = $previousCachePath @@ -122,27 +126,43 @@ finally { } ``` -Check per-connector failures as well as the CLI exit code. Record the exact -generator revision, linked PR and its status, source subscription, region, and capture time. -Paired generator/SDK PRs show generated output from the active generator PR before -it merges. Label that source as unmerged; final SDK merge still requires upstream integration. -Do not add cache folders or replay scaffolding as part of a client refresh. - -Reviewers must fetch live definitions independently using their own new empty -temporary directory. Do not give the producer's responses to the reviewer as -generation inputs. Compare generated outputs after normalizing CRLF to LF; -investigate live differences instead of substituting cached inputs to make them match. +Record the full AzureUX-BPM generator revision, compiler hash, source metadata, +and canonical generated-output hashes in `generation.manifest.json`. Validate +exact sync/aio inventory parity, the lazy client registry, and package type stubs +before committing the reviewed output. ### Pageable Results -Pageable operations expose async iterators. Iteration follows continuation links and -yields items directly; an empty response yields no items. Do not await a page envelope: +Read-collection operations return Azure Core pagers, including bounded read +collections without continuation metadata. Arrays returned by mutations and +other actions remain eager payloads. Pager iteration follows continuation links +when the contract provides them and yields items directly; an empty response +yields no items. Do not await pager construction: ```python -async for item in client.get_items_async(...): +for item in sync_client.list_items(...): + process_item(item) + +async for item in async_client.list_items(...): process_item(item) ``` +Root clients return `ItemPaged`; aio clients return `AsyncItemPaged`. Both +support `by_page(continuation_token=...)`. Request controls and response hooks +apply to every page request. + +### Long-Running Operations + +Retained operations with an HTTP 202 `Location` polling contract use matching +`begin_*` methods. Root clients return `LROPoller[T]`; aio clients return +`AsyncLROPoller[T]` after the `begin_*` call is awaited. Resolve the final +payload with `poller.result()` while the connector client remains open. + +The generator does not infer polling from HTTP 202 alone. Status-document +protocols, cancellation, and poller continuation tokens are not currently +generated. Request controls and response hooks apply to the initial request and +every polling request. + ### Consumer Review Checks - Capture known response collections directly in semantic names, such as @@ -166,12 +186,11 @@ async for item in client.get_items_async(...): # office365.py - Auto-generated Python DirectClient SDK # Do not edit this file directly. -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, List, Dict, Any from datetime import datetime -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ConnectorClientBase @@ -181,13 +200,13 @@ from azure.connectors.sdk import ConnectorClientBase class GraphCalendarEventClientReceive: """Response for calendar event operations.""" - subject: Optional[str] = None + subject: Optional[str] = dataclass_field(default=None, kw_only=True) """Event subject.""" - start: Optional[str] = None + start: Optional[str] = dataclass_field(default=None, kw_only=True) """Event start time (ISO 8601).""" - end: Optional[str] = None + end: Optional[str] = dataclass_field(default=None, kw_only=True) """Event end time (ISO 8601).""" # ... other fields @@ -200,11 +219,11 @@ class Office365Client(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, - transport: Optional[AsyncHttpTransport] = None, + timeout: float = 30.0, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """Initialize the Office 365 client with an Azure Core credential.""" @@ -214,22 +233,23 @@ class Office365Client(ConnectorClientBase): super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, transport=transport, **kwargs, ) self._connection_runtime_url = connection_runtime_url.rstrip("/") - async def send_email_v2_async( + def send_email_v2( self, to: str, subject: str, body: str, + *, from_address: Optional[str] = None, cc: Optional[str] = None, bcc: Optional[str] = None, importance: Optional[str] = None, - is_html: bool = True + is_html: bool = True, ) -> None: """ Send an email. @@ -244,10 +264,15 @@ class Office365Client(ConnectorClientBase): importance: Email importance (Low, Normal, High) is_html: Whether body is HTML """ - # Generated implementation calls self._http_client.send_async(...) + # Generated implementation calls self._http_client.send(...) # with proper serialization and error handling ``` +The paired `aio/office365.py` defines the same `Office365Client` operations +with `async def`, `AsyncTokenCredential`, and `AsyncHttpTransport`. It imports +models and other shared declarations from `azure.connectors.office365` rather +than generating duplicate definitions. + ### Key Patterns in Generated Code #### 1. Root Schema Aliases @@ -264,19 +289,27 @@ String and integer enums become `Literal` aliases, and array roots become typed #### 2. Dataclass Models -Connector object schemas are generated as dataclasses with optional fields: +Connector object schemas are generated as dataclasses. Swagger-required fields +are required constructor arguments; optional fields are keyword-only and +default to `None`: ```python @dataclass class FileMetadata: """Metadata for a file in SharePoint or OneDrive.""" - - id: Optional[str] = None - name: Optional[str] = None - path: Optional[str] = None - size: Optional[int] = None - created_time: Optional[datetime] = None - modified_time: Optional[datetime] = None + + id: str + name: Optional[str] = dataclass_field(default=None, kw_only=True) + path: Optional[str] = dataclass_field(default=None, kw_only=True) + size: Optional[int] = dataclass_field(default=None, kw_only=True) + created_time: Optional[datetime] = dataclass_field( + default=None, + kw_only=True, + ) + modified_time: Optional[datetime] = dataclass_field( + default=None, + kw_only=True, + ) ``` #### 3. Client Inheritance @@ -290,31 +323,34 @@ class SharepointonlineClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, ): super().__init__(credential) self._connection_runtime_url = connection_runtime_url.rstrip("/") ``` This inheritance provides: + - HTTP client with retry logic - Authentication through caller-owned Azure Core credentials -- Lifecycle management (async context manager, close) +- Lifecycle management through matching sync or async context managers - Error handling with `ConnectorException` -#### 4. Async Method Signatures +#### 4. Matching Method Signatures -All connector actions are generated as async methods: +Root and aio clients expose the same unsuffixed operation names and parameters. +The execution model and pager type differ: ```python -async def get_items_async( +def list_items( self, dataset: str, table: str, + *, filter_query: Optional[str] = None, order_by: Optional[str] = None, - top: Optional[int] = None -) -> Dict[str, Any]: + top: Optional[int] = None, +) -> ItemPaged[dict[str, Any]]: """ Get items from a SharePoint list. @@ -324,15 +360,28 @@ async def get_items_async( filter_query: OData filter expression order_by: OData orderBy expression top: Maximum number of items to return - - Returns: - Dictionary with 'value' key containing list of items """ + ... +``` + +```python +def list_items( + self, + dataset: str, + table: str, + *, + filter_query: Optional[str] = None, + order_by: Optional[str] = None, + top: Optional[int] = None, +) -> AsyncItemPaged[dict[str, Any]]: + """Return the asynchronous item pager without awaiting construction.""" + ... ``` #### 5. Type Hints and Docstrings The generator produces: + - Full type hints for all parameters and return types - Docstrings from connector metadata - Optional parameter defaults @@ -342,22 +391,15 @@ The generator produces: After generating a new connector client: -1. **Copy the generated file** to `src/azure/connectors/`: +1. **Copy the generated pair** to `src/azure/connectors/`: ```powershell Copy-Item "output\office365.py" "src\azure\connectors\office365.py" + Copy-Item "output\aio\office365.py" "src\azure\connectors\aio\office365.py" ``` -2. **Update `src/azure/connectors/__init__.py`** to export the client: - - ```python - from azure.connectors.office365 import Office365Client - - __all__ = [ - "Office365Client", - # ... other clients - ] - ``` +2. **Regenerate package-level artifacts.** The helper writes the lazy client + registry and root/aio `.pyi` files. Do not edit them manually. 3. **Create unit tests** following the pattern in `tests/`: @@ -378,7 +420,10 @@ After generating a new connector client: pytest ``` -5. **Update documentation**: +5. **Create both sample variants** under `samples/sample_connector_usage/` and + `samples/sample_connector_usage/aio/`. + +6. **Update documentation**: - Add connector to README.md validated connectors table - Update ROADMAP.md status - Add sample code to `samples/` directory @@ -463,12 +508,17 @@ Every generated connector client MUST satisfy these invariants before merge: ### 2. Response Status Checking (All Operations) - Every HTTP operation MUST capture the response and check the status code -- Non-2xx responses MUST raise `ConnectorException` with status code and message +- Non-2xx responses MUST raise `ConnectorException`, an Azure Core + `HttpResponseError`, with status code and message, except for explicitly + curated resource-delete operations whose contract treats HTTP 404 as an + idempotent success +- Operations with a declared 2xx response schema MUST deserialize and return + that payload regardless of the HTTP method - Void operations (DELETE, PATCH, fire-and-forget POST) MUST NOT discard the response unchecked **Correct pattern:** ```python -response = await self.http_client.send_async( +response = self.http_client.send( method="DELETE", url=request_uri, ) @@ -485,13 +535,20 @@ if not (200 <= response.status < 300): **Incorrect pattern (MUST NOT pass review):** ```python -await self.http_client.send_async( # Result discarded - silent failures! +self.http_client.send( # Result discarded - silent failures! method="DELETE", url=request_uri, ) ``` -**Validation:** The `test_no_unchecked_send_async_calls` test in `tests/test_code_quality.py` scans for unchecked `send_async` calls. Additionally, unit tests for void methods MUST assert that non-2xx responses raise `ConnectorException`. +The generator owns the narrow allow-list for resource-delete operations that +accept HTTP 404. Do not infer idempotent success from the `DELETE` verb alone; +connectors also use that verb for actions whose missing target is an error. + +The aio pattern awaits the same `send` method. **Validation:** +`test_no_unchecked_send_calls` in `tests/test_code_quality.py` scans root and aio +modules for discarded calls. Unit tests for void methods must also assert that +non-2xx responses raise `ConnectorException`. ### 3. Test Coverage @@ -506,7 +563,7 @@ await self.http_client.send_async( # Result discarded - silent failures! | POST with body | At least 1 test asserting body is forwarded + 1 error test | | PUT with body | At least 1 test asserting body is forwarded + 1 error test | | PATCH with body | At least 1 test asserting body is forwarded + 1 error test | -| DELETE | At least 1 success test + 1 error test verifying exception raised | +| DELETE | At least 1 success test + 1 non-404 error test verifying exception raised; HTTP 404 must be covered as success regardless of the operation name | **Connectors with >20 public methods** are not required to have a test class per method. Representative coverage — one test group per HTTP verb type used by the connector — satisfies the acceptance criteria, provided the body-forwarding and non-2xx paths are both covered. @@ -516,7 +573,8 @@ await self.http_client.send_async( # Result discarded - silent failures! - All public types (dataclasses) referenced by method signatures MUST be defined - No `# type: ignore` comments unless accompanied by a tracked issue link -- All optional parameters MUST have `Optional[T]` type hints and default values +- All optional parameters MUST have `Optional[T]` type hints and default values; + Swagger-required model fields MUST remain required constructor arguments ## Generator File Locations (BPM Repository) @@ -531,7 +589,10 @@ When fixing generator bugs (per the "fix the generator, not generated output" ru ### Key Differences from .NET Generator -The .NET SDK centralizes error handling in `ConnectorClientBase.CallConnectorAsync()` — this base method auto-throws on non-2xx for both value-returning and void operations. The Python emitter must explicitly generate the status check in each method body because Python's `http_client.send_async()` does not auto-raise. +The .NET SDK centralizes error handling in +`ConnectorClientBase.CallConnectorAsync()`. The Python emitter must explicitly +generate the status check in each root and aio method body because +`http_client.send()` does not auto-raise. **If you find a Python generator bug:** 1. Fix it in `DirectClientPythonCodeGenerator.cs` @@ -569,6 +630,12 @@ Track known generator issues here to prevent silent recurrence across releases. | Operation methods corrected Swagger spelling or split acronym letters | Fixed in generator | `docusign`, `github`, `googletasks`, `pdfco`, `salesforce`, `signinghub`, `slack`, `wordonlinebusiness`, `zohosign` | Fixed | Python applies deterministic acronym-aware snake_case and connector-scoped corrections for known malformed operation IDs. | | Colliding wire names dropped after Python normalization | Fixed in generator | `teams`, `shifts`, `todo` | Fixed | Distinct generated fields preserve both `id` and `@odata.id`; serializer tests set both values together. | | String-encoded integer enum tokens emitted as string literals | Fixed in generator | `etsy` | Fixed | Python now normalizes quoted enum tokens to the declared integer schema type. All Phase 6 and 7 clients were regenerated; only `etsy` changed. | +| Pageable item properties and bounded collection envelopes misclassified | Fixed in generator | `azuredigitaltwins`, `insightly`, `jira`, `documentdb`, `sql`, and other collection connectors | Fixed | Explicit pageable operations infer omitted item names and use recognized continuation fields present in the response schema. Bounded read envelopes select conventional primary arrays over auxiliary array metadata and emit `list_*` pagers, while mutation/action arrays remain eager. | +| Mutation arrays were lazy and primitive pagers used dictionary item types | Fixed in generator | `azuread`, `docusign`, `eventhubs`, `meetingroommap`, `mq`, `msgraphgroupsanduser`, `onedrive`, `powerbi`, `replicon`, `sendgrid`, `servicebus`, `yammer` | Fixed | Bounded mutation responses execute eagerly under action names and preserve response envelopes. Read collections retain primitive pager item types in sync and aio contracts. | +| Caller continuation URLs bypassed pagination origin normalization | Fixed in generator | All pageable connectors | Fixed | `by_page(continuation_token=...)` now routes caller tokens through the same URL resolver as service-provided next links before transport receives the request. | +| Typeless dynamic request models omitted mapping inputs | Fixed in generator | `docuware` | Fixed | Dynamic dataclass request annotations now accept either the generated model or `Mapping[str, Any]`. | +| Operation name used as a proxy for HTTP DELETE semantics | Fixed in generator | `arm`, `zohosign`, and other delete operations | Fixed | Generated HTTP `DELETE` methods return `None` for HTTP 404 regardless of their normalized names. Non-DELETE operations preserve their response and ordinary failure behavior even when their names begin with `delete_`. | +| Successful response discarded when Swagger omits its schema | Fixed in generator | `orderful` | Fixed | The Python-specific `ListTransactions` override preserves the runtime JSON payload without changing other language emitters. | | Create/update operations missing request body | [BPM #TBD](https://dev.azure.com/msazure/One/_workitems/edit/TBD) | Varies by connector | Investigation | Some POST/PATCH operations may drop body parameters | **Adding a new defect:** diff --git a/README.md b/README.md index 7aed889..92ff83c 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ Type-safe Python clients for [Azure connectors](https://learn.microsoft.com/conn Azure provides a rich ecosystem of [managed connectors](https://learn.microsoft.com/connectors/connector-reference/) that bridge your code to SaaS services, PaaS resources, and on-premises systems. Originally powering Azure Logic Apps and Power Automate, these connectors are now available as **standalone, strongly-typed Python clients** for any Python application — no workflow service required. -- **Async/await native** — Built on `aiohttp` with full async support for modern Python applications -- **Type-safe operations** — Generated async methods with type hints and comprehensive docstrings +- **Sync and async clients** — Use synchronous clients at the package root or matching asynchronous clients under `.aio` +- **Type-safe operations** — Both modes expose identical unsuffixed methods with type hints and comprehensive docstrings - **Built-in authentication** — Managed identity, Azure Identity, and API key token providers - **Resilient HTTP** — Configurable retries with exponential backoff for safe HTTP methods; unsafe methods make one attempt by default - **1,000+ connectors** — Any Azure managed connector available via API Hub can be generated @@ -37,17 +37,17 @@ Azure provides a rich ecosystem of [managed connectors](https://learn.microsoft. ┌─────────────────────────────────────┐ │ Your Azure Function / Python App │ │ │ -│ async with Office365Client(...): │ -│ await client.send_email(...) │ +│ with Office365Client(...): │ +│ client.send_email(...) │ └──────────────┬──────────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ Generated Connector Clients │ -│ (office365.py, teams.py, etc.) │ +│ (root sync + aio async modules) │ │ │ -│ • Typed async methods per action │ -│ • Dataclass models from Swagger │ +│ • Matching unsuffixed operations │ +│ • Shared models from Swagger │ │ • Docstrings from connector meta │ └──────────────┬──────────────────────┘ │ depends on @@ -78,39 +78,34 @@ pip install azure-connectors[dev] ## Quick Start -### Example: Send an email with Office 365 +### Example: Send an email synchronously ```python -import asyncio - -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors.office365 import Office365Client, SendEmailInput -async def send_email_example(): +def send_email_example(): connection_url = "https://example.azure.com/connections/office365" - async with DefaultAzureCredential() as credential: - async with Office365Client(connection_url, credential) as client: - await client.send_email_async( + with DefaultAzureCredential() as credential: + with Office365Client(connection_url, credential) as client: + client.send_email( input=SendEmailInput( to="recipient@example.com", subject="Hello from Python SDK", body="

Sent with the Azure Connectors Python SDK.

", ) ) - - -asyncio.run(send_email_example()) ``` -### Example: List SharePoint items +### Example: List SharePoint items asynchronously ```python from azure.identity.aio import DefaultAzureCredential -from azure.connectors.sharepointonline import SharepointonlineClient +from azure.connectors.aio.sharepointonline import SharepointonlineClient async def list_sharepoint_items(): @@ -120,7 +115,7 @@ async def list_sharepoint_items(): async with SharepointonlineClient(connection_url, credential) as client: items = [ item - async for item in client.get_items_async( + async for item in client.list_items( dataset="https://contoso.sharepoint.com/sites/MySite", table="MyList", ) @@ -135,7 +130,8 @@ async def list_sharepoint_items(): ```python from azure.identity.aio import DefaultAzureCredential -from azure.connectors.teams import DynamicPostMessageRequest, TeamsClient +from azure.connectors.aio.teams import TeamsClient +from azure.connectors.teams import DynamicPostMessageRequest async def post_teams_message(): @@ -143,7 +139,7 @@ async def post_teams_message(): async with DefaultAzureCredential() as credential: async with TeamsClient(connection_url, credential) as client: - await client.post_message_to_conversation_async( + await client.post_message_to_conversation( input=DynamicPostMessageRequest( additional_properties={ "body": { @@ -157,6 +153,36 @@ async def post_teams_message(): ) ``` +### Example: Wait for a long-running Kusto query + +Long-running operations use an Azure SDK-style `begin_*` method. Keep the +client open until the poller reaches its terminal response: + +```python +from azure.identity import DefaultAzureCredential + +from azure.connectors.kusto import KustoClient, QueryAndListSchema + + +def run_kusto_query(): + connection_url = "https://example.azure.com/connections/kusto" + + with DefaultAzureCredential() as credential: + with KustoClient(connection_url, credential) as client: + poller = client.begin_list_kusto_results( + input=QueryAndListSchema( + cluster="https://contoso.kusto.windows.net", + db="Samples", + csl="StormEvents | take 5", + ) + ) + return poller.result() +``` + +The matching aio method is awaited to create the poller, then +`await poller.result()` waits for completion. See the +[long-running operations guide](docs/long-running-operations.md). + ### Retry safety By default, `GET`, `HEAD`, `OPTIONS`, and `TRACE` use the configured retry settings. `POST`, `PUT`, `PATCH`, `DELETE`, and other methods make one attempt after a transient response or transport error because the connector may already have completed the side effect. @@ -164,14 +190,14 @@ By default, `GET`, `HEAD`, `OPTIONS`, and `TRACE` use the configured retry setti Only opt in when the connector operation can tolerate replay, preferably with a service-supported idempotency key or deduplication: ```python -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors.teams import TeamsClient -async def use_teams_client(connection_url: str): - async with DefaultAzureCredential() as credential: - async with TeamsClient( +def use_teams_client(connection_url: str): + with DefaultAzureCredential() as credential: + with TeamsClient( connection_url, credential, max_retry_attempts=3, @@ -181,6 +207,7 @@ async def use_teams_client(connection_url: str): ``` `max_retry_attempts`, timeout, and backoff settings govern eligible retries. This is the same [cross-language retry-safety contract](https://github.com/Azure/Connectors-NET-SDK/blob/main/docs/retry-safety.md) as the .NET and Node.js SDKs. + ## Validated Connectors The following connectors have been generated and validated with comprehensive test coverage: @@ -298,14 +325,14 @@ Generated clients require a caller-owned Azure Core credential. ### Managed Identity ```python -from azure.identity.aio import ManagedIdentityCredential +from azure.identity import ManagedIdentityCredential from azure.connectors.office365 import Office365Client -async def use_managed_identity(connection_url: str): - async with ManagedIdentityCredential() as credential: - async with Office365Client(connection_url, credential) as client: +def use_managed_identity(connection_url: str): + with ManagedIdentityCredential() as credential: + with Office365Client(connection_url, credential) as client: print(client.connector_name) ``` @@ -313,10 +340,10 @@ Pass `client_id="your-client-id"` to `ManagedIdentityCredential` for a user-assi ### Azure Identity Credentials -Any asynchronous Azure Identity credential can be passed directly: +Root clients accept synchronous Azure Identity credentials: ```python -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors.office365 import Office365Client @@ -324,7 +351,16 @@ credential = DefaultAzureCredential() client = Office365Client(connection_url, credential) ``` -The caller owns the credential and must close it. Prefer an `async with` credential context as shown above. +Asynchronous clients use the matching credential and client modules: + +```python +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors.aio.office365 import Office365Client +``` + +The caller owns the credential and must close it. Prefer `with` for synchronous +credentials and `async with` for asynchronous credentials. ### API Key @@ -345,29 +381,27 @@ Pass retry, timeout, transport, and Azure Core policy settings directly to the g client = Office365Client( connection_url, credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, use_exponential_backoff=True, initial_retry_delay_seconds=1.0, ) ``` -`timeout_seconds` is one total network budget for each request, including +The client-level `timeout` is one total network budget for each request, including retries, response loading, and body reads. Each generated operation also accepts keyword-only `timeout`, `headers`, `client_request_id`, and `response_hook` -request controls; `timeout` overrides that total budget for one operation. Set -either timeout to zero or a negative value to disable SDK and transport +request controls; the operation-level `timeout` overrides that total budget for +one operation. Set either timeout to zero or a negative value to disable SDK and transport deadlines for the selected requests. -Generated clients accept any Azure Core `AsyncHttpTransport`. The client closes -an injected transport through its asynchronous lifecycle; the caller retains -ownership of the credential. The SDK enforces the total request budget across -transports and applies transport-specific timeout options only when supported. -`per_call_policies` and `per_retry_policies` are composed with the default or an -explicit `policies` chain. An explicit chain using `per_retry_policies` must -contain an `AsyncRetryPolicy`. Explicit chains without a retry policy remain -supported; the SDK enforces positive total request deadlines without forwarding -retry-only options to the transport. +Root clients accept Azure Core `HttpTransport` implementations and aio clients +accept `AsyncHttpTransport` implementations. Clients close injected transports +through the matching lifecycle; callers retain ownership of credentials. The +SDK enforces the total request budget across transports and applies +transport-specific timeout options only when supported. `per_call_policies` and +`per_retry_policies` compose with the default or an explicit `policies` chain. +Per-retry extensions require the matching sync or async retry policy. ## Project Structure @@ -376,16 +410,22 @@ azure-connectors/ ├── src/azure/connectors/ │ ├── sdk/ # Azure Core runtime infrastructure │ │ ├── client_base.py # Base connector client -│ │ ├── http_client.py # Async pipeline and retry policies +│ │ ├── http_client.py # Sync pipeline and retry policies +│ │ ├── aio/ # Async runtime counterparts │ │ ├── response.py # Immutable response hook contracts │ │ └── exceptions.py # Exception types -│ ├── office365.py # Office 365 generated client +│ ├── aio/ # Async generated clients +│ ├── office365.py # Sync client and shared models │ ├── sharepointonline.py # SharePoint generated client │ └── teams.py # Teams generated client ├── tests/ # Comprehensive test suite ├── samples/ # Usage examples └── docs/ # Additional documentation ``` + +See [Migrate to sync and aio clients](docs/migration-sync-aio.md) for the +breaking changes from the asynchronous-only preview. + ## SDK-Type Bindings for Azure Functions The SDK supports **SDK-type bindings** for Python Function apps, allowing functions to bind to and return rich, strongly-typed objects instead of raw JSON payloads. This enables cleaner code and better IDE support with type hints. diff --git a/ROADMAP.md b/ROADMAP.md index 0075a94..080c537 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -12,7 +12,7 @@ This document tracks the development roadmap for the Azure Connectors Python SDK | Component | Status | |-----------|--------| -| Core SDK | ✅ Complete — Token providers, HTTP client, retry logic, async/await | +| Core SDK | ✅ Complete — Sync/aio Azure Core pipelines, credentials, retries, and paging | | Connectors | ✅ 99 connectors — See [README.md](README.md#validated-connectors) | | CI/CD | ✅ Complete — GitHub Actions for pytest, flake8, build | | PyPI Publishing | ✅ Complete — Release workflow ready | @@ -27,9 +27,9 @@ This document tracks the development roadmap for the Azure Connectors Python SDK ### Completed - [x] Core SDK abstractions (`ConnectorClientBase`, `ConnectorHttpClient`) -- [x] Azure Core credentials (async Azure Identity and API key) +- [x] Azure Core credentials (sync/aio Azure Identity and API key) - [x] HTTP client with retry logic and exponential backoff -- [x] Async/await support throughout +- [x] Matching synchronous and asynchronous client surfaces - [x] Type hints and dataclass models - [x] Office 365 Outlook connector - [x] SharePoint Online connector diff --git a/docs/api/index.md b/docs/api/index.md index 8c5da2a..73fa403 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -2,13 +2,26 @@ The API reference is generated from the current Python source on every documentation build. -## Core SDK +## Synchronous core SDK -Core modules provide authentication, client lifecycle, HTTP behavior, serialization, options, exceptions, and trigger payload types. These modules are maintained by the SDK team. +Root core modules provide synchronous client lifecycle, HTTP behavior, +serialization, exceptions, and trigger payload types. The aio core section +documents asynchronous runtime counterparts. -## Connector modules +## Connector clients -Each shipped connector has its own generated module containing an asynchronous client and the request and response models reachable from that connector's contract. Connector pages are discovered automatically, so newly generated modules appear without a separate documentation allow-list. +Each shipped connector has a synchronous root module containing its client and +the shared request and response declarations reachable from that connector's +contract. The matching aio module contains the asynchronous client and +re-exports the exact root-owned declarations. Both clients expose identical +unsuffixed operation names. + +Root pageable operations return `ItemPaged`; aio pageable operations return +`AsyncItemPaged`. Location-backed long-running operations return `LROPoller` +or `AsyncLROPoller` from matching `begin_*` methods. + +All four API sections are discovered automatically, so new paired modules +appear without a separate documentation allow-list. Generated connector source is read-only. Corrections to generated signatures or docstrings must be made in the CodefulSdkGenerator and regenerated into this repository. diff --git a/docs/azure-sdk-guidelines.md b/docs/azure-sdk-guidelines.md new file mode 100644 index 0000000..35e8776 --- /dev/null +++ b/docs/azure-sdk-guidelines.md @@ -0,0 +1,55 @@ +# Azure SDK guideline alignment + +This SDK follows the Azure SDK Design Guidelines for Python where they fit the +managed connector execution model. The table records intentional Phase 2 +decisions so future changes preserve the public contract. + +| Area | Decision | Status | +|---|---|---| +| Sync and async APIs | Provide synchronous clients at the connector root and asynchronous clients under `.aio`. | Follow | +| Method names | Use the same unsuffixed operation name on sync and aio clients. | Follow | +| Credentials | Accept caller-owned `TokenCredential`/`AsyncTokenCredential` or `AzureKeyCredential`. | Follow | +| Transports | Accept Azure Core `HttpTransport`/`AsyncHttpTransport` implementations. | Follow | +| Paging | Return `ItemPaged`/`AsyncItemPaged` and support `by_page(continuation_token=...)`. | Follow | +| Models | Define wire models once in the root connector module and share object identity with aio. | Project convention | +| Imports | Export clients lazily from package roots while retaining direct per-connector imports. | Follow | +| Errors | Derive connector service errors from Azure Core `HttpResponseError`. | Follow | +| Request options | Expose keyword-only `timeout`, `headers`, `client_request_id`, and `response_hook` on both modes. | Follow | +| Long-running operations | Return `LROPoller`/`AsyncLROPoller` for retained operations with an HTTP 202 `Location` contract. | Follow | +| API versions | Use each generated operation's managed-connector Swagger version; do not expose a client-level `api_version` override. | Intentional deviation | +| Return values | Return connector payloads directly rather than Azure Core `Response[T]` wrappers. | Intentional deviation | + +## Namespace shape + +```python +# Synchronous client and shared models +from azure.connectors.office365 import Office365Client, SendEmailInput + +# Asynchronous client; models still come from the root module +from azure.connectors.aio.office365 import Office365Client +from azure.connectors.office365 import SendEmailInput + +# Clients are also available as lazy package-root exports +from azure.connectors import Office365Client +from azure.connectors.aio import Office365Client +``` + +The two clients have distinct identities and runtimes. Models, type aliases, +enums, and `TRIGGER_OPERATIONS` have shared identity across the paired modules. + +Location-backed operations use the same `begin_*` name in both modes. Azure +status-document protocols, poller continuation tokens, and cancellation are +not part of the current contract. + +Managed connectors can route operations to different service API versions +within one client. Generated operations therefore retain their Swagger-declared +internal version defaults instead of accepting one constructor-level +`api_version` that could override unrelated routes. + +## Compatibility policy + +The pre-1.0 async-only surface is replaced rather than shimmed. Root modules do +not retain asynchronous client aliases, and aio methods do not retain `_async` +aliases. Package-root exports are lazy so importing `azure.connectors` does not +load every generated module. See the [migration guide](migration-sync-aio.md) +for mechanical changes. diff --git a/docs/generated-contract.md b/docs/generated-contract.md new file mode 100644 index 0000000..f80075e --- /dev/null +++ b/docs/generated-contract.md @@ -0,0 +1,69 @@ +# Generated connector contract + +Generated connector clients are committed artifacts produced by the BPM +CodefulSdkGenerator. Do not hand-edit files under `src/azure/connectors/` or +`src/azure/connectors/aio/`. + +## Paired output + +One Python generation request must emit an atomic pair for every connector: + +```text +src/azure/connectors/.py # sync client and shared declarations +src/azure/connectors/aio/.py # async client, imports shared declarations +``` + +If either member fails, the generator must not leave a partial pair. Both files +must come from the same generator revision and the same captured connector +contract. + +## Public invariants + +- Root operations are synchronous; aio operations are asynchronous except that + pageable methods construct and return their pager without being awaited. +- Paired clients have the same class name, unsuffixed operation names, + parameters, request controls, and non-paging return payload types. +- Root read-collection operations return `ItemPaged`; aio read-collection + operations return `AsyncItemPaged`. This includes bounded read collections + without a continuation-link contract. Arrays returned by mutations and other + actions remain eager operation payloads. +- Dataclasses, type aliases, enums, and `TRIGGER_OPERATIONS` are declared only + in root and imported by aio, preserving object identity. +- Swagger-required dataclass properties are required constructor arguments; + only optional properties default to `None`. +- Each module defines an explicit `__all__`; paired exports match except for the + distinct client object. +- Generated clients are available from their connector modules and as lazy + package-root exports. The generated registry and `.pyi` files keep runtime + discovery and static typing synchronized without eagerly importing every + connector module. +- Retained operations with an HTTP 202 `Location` response contract use + `begin_*` and return `LROPoller[T]` or `AsyncLROPoller[T]`. LRO classification + takes precedence over paging, and bare HTTP 202 responses remain ordinary. +- `ConnectorException` derives from Azure Core `HttpResponseError` while + retaining connector operation, path, status, and response-body details. + +Paging must preserve validation, connector error behavior, empty pages, +continuation links, request controls, and response hooks on every request. +Service links and caller-provided continuation tokens pass through the same URL +resolver. Links from a different origin are rebased onto the connection runtime +origin before the next request. + +The shipped catalog contains exactly 44 paired LRO methods: 5 in Kusto and 39 +in Plumsail. Internal Kusto retrieval helpers and superseded Plumsail revisions +remain filtered by the existing operation-retention rules. + +## Regeneration evidence + +The `generation.manifest.json` file records the exact generator commit and +compiler hash, source subscription and region, capture time, and hashes for +every generated module, registry, and package type stub. Source Swagger files +used during generation are not committed to this repository. + +Use the pinned generator revision and the live-metadata workflow in +`GENERATION.md` to refresh the complete sync/aio catalog. Review source metadata +changes and generated output together before updating the manifest. + +Before submission, verify exact root/aio catalog parity, compile every generated +module, run connector and runtime tests, validate both sample catalogs, build +the documentation, and inspect the wheel and source distribution inventories. diff --git a/docs/index.md b/docs/index.md index ee04f98..c26a3f0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,30 +11,48 @@ Build type-safe Python integrations with Azure managed connectors for services s python -m pip install azure-connectors ``` -The SDK requires Python 3.10 or later and provides asynchronous connector clients, typed request models, generated schema classes, and Azure Identity integration. Connector operation responses are currently returned as dictionaries rather than generated model instances. +The SDK requires Python 3.10 or later and provides synchronous connector clients at the package root, asynchronous clients under `.aio`, shared typed models, and Azure Identity integration. Non-pageable connector responses are returned as payload values; pageable operations return Azure Core pagers. ## Create a client -Generated clients require a caller-owned asynchronous Azure Identity credential or an `AzureKeyCredential`. +Generated clients require a caller-owned Azure Identity credential or an `AzureKeyCredential`. Root clients are synchronous: ```python -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors.office365 import Office365Client +def list_messages(connection_url: str) -> None: + with DefaultAzureCredential() as credential: + with Office365Client(connection_url, credential) as client: + messages = client.get_emails( + folder_path="Inbox", + ) + print(messages) +``` + +Use the matching client under `azure.connectors.aio` for asynchronous code. Operation names are identical on both surfaces and never use an `_async` suffix. Models remain in the root connector module. + +```python +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors.aio.office365 import Office365Client + + async def list_messages(connection_url: str) -> None: async with DefaultAzureCredential() as credential: async with Office365Client(connection_url, credential) as client: - messages = await client.get_emails_async( - folder_path="Inbox", - ) + messages = await client.get_emails(folder_path="Inbox") print(messages) ``` + Connector signatures are generated from their managed connector contracts. Consult the [API reference](api/index.md) for the exact client method and model names in the current branch. ## Next steps - [Set up a connector connection](connection-setup.md) +- [Migrate from the async-only preview](migration-sync-aio.md) - [Browse the API reference](api/index.md) +- [Review the generated contract](generated-contract.md) - [Understand Azure Functions SDK-type bindings](sdk-type-bindings.md) diff --git a/docs/long-running-operations.md b/docs/long-running-operations.md new file mode 100644 index 0000000..67c93cf --- /dev/null +++ b/docs/long-running-operations.md @@ -0,0 +1,44 @@ +# Long-running operations + +Kusto and Plumsail operations that declare an HTTP 202 `Location` polling +contract use Azure Core pollers. Their generated method names begin with +`begin_`. + +## Synchronous clients + +```python +with KustoClient(connection_url, credential) as client: + poller = client.begin_list_kusto_results(input=query) + result = poller.result() +``` + +`LROPoller` begins polling in a background thread. `result()` waits for the +terminal response and returns its deserialized payload. `wait(timeout=...)` +limits how long that call waits; it does not cancel the connector operation. + +## Asynchronous clients + +```python +async with KustoClient(connection_url, credential) as client: + poller = await client.begin_list_kusto_results(input=query) + result = await poller.result() +``` + +`AsyncLROPoller` starts polling when it is awaited through `result()`, `wait()`, +or the poller itself. + +## Polling behavior + +- HTTP 202 responses must provide a `Location` header. +- Polling requests use GET and honor numeric or HTTP-date `Retry-After` values. +- Relative and connector-backend polling URLs are routed through the + authenticated connection runtime origin. +- `timeout`, `headers`, `client_request_id`, and `response_hook` are forwarded + to the initial request and every poll request. `timeout` applies to each + network request, not the lifetime of the long-running operation. +- A non-202 success response completes the poller. Terminal non-success + responses raise `ConnectorException`. + +Keep the connector client open until polling completes. Poller continuation +tokens, cancellation, `Azure-AsyncOperation` status documents, and +`Operation-Location` final-resource protocols are not currently supported. diff --git a/docs/migration-sync-aio.md b/docs/migration-sync-aio.md new file mode 100644 index 0000000..3375eb9 --- /dev/null +++ b/docs/migration-sync-aio.md @@ -0,0 +1,98 @@ +# Migrate to sync and aio clients + +The sync/aio release replaces the asynchronous-only preview API. This is a +clean break: compatibility aliases for the old imports and `_async` operation +names are not provided. + +## Choose a client + +Synchronous clients live in each root connector module. Asynchronous clients +live in the matching `aio` module. Both clients expose the same unsuffixed +operation names. + +| Use case | Client import | Credential | +|---|---|---| +| Synchronous code | `azure.connectors.` | `azure.core.credentials.TokenCredential` | +| Asynchronous code | `azure.connectors.aio.` | `azure.core.credentials_async.AsyncTokenCredential` | + +Import request and response models from the root connector module in both +modes. The aio module re-exports those same objects, but root imports make model +ownership explicit and avoid coupling application models to an execution mode. + +## Update asynchronous code + +Move the client import under `aio` and remove `_async` from every operation: + +```python +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors.aio.office365 import Office365Client +from azure.connectors.office365 import SendEmailInput + + +async def send_email(connection_url: str) -> None: + async with DefaultAzureCredential() as credential: + async with Office365Client(connection_url, credential) as client: + await client.send_email( + SendEmailInput( + to="recipient@example.com", + subject="Hello", + body="Sent with Azure Connectors.", + ) + ) +``` + +Before this release, the client was imported from +`azure.connectors.office365` and the operation was named `send_email_async`. + +## Use the synchronous default + +Root clients use synchronous Azure Identity credentials and context managers: + +```python +from azure.identity import DefaultAzureCredential + +from azure.connectors.office365 import Office365Client, SendEmailInput + + +def send_email(connection_url: str) -> None: + with DefaultAzureCredential() as credential: + with Office365Client(connection_url, credential) as client: + client.send_email( + SendEmailInput( + to="recipient@example.com", + subject="Hello", + body="Sent with Azure Connectors.", + ) + ) +``` + +## Migrate pageable operations + +Pageable operations no longer return `AsyncIterator`. They return Azure Core +pagers and continue to yield connector items directly. + +```python +# Sync: azure.core.paging.ItemPaged +for item in sync_client.list_items(dataset=site_url, table=list_name): + process(item) + +# Async: azure.core.async_paging.AsyncItemPaged +async for item in async_client.list_items(dataset=site_url, table=list_name): + process(item) +``` + +Do not await pager construction. Use `by_page(continuation_token=...)` when +page boundaries or a saved continuation token are required. + +## Removed preview forms + +- Root asynchronous clients and `_async` operation names. +- Awaiting pageable operations as response dictionaries. +- Treating collected page items as a response envelope with a `value` field. +- Importing a generated client from a package-level barrel module. + +Location-backed Kusto and Plumsail operations now use `begin_*` methods. Root +clients return `LROPoller`; aio clients return `AsyncLROPoller` after awaiting +the `begin_*` call. Resolve the terminal payload with `poller.result()` and keep +the connector client open until polling completes. diff --git a/generation.manifest.json b/generation.manifest.json new file mode 100644 index 0000000..bf5a657 --- /dev/null +++ b/generation.manifest.json @@ -0,0 +1,731 @@ +{ + "manifestVersion": 1, + "generator": { + "repository": "https://msazure.visualstudio.com/One/_git/AzureUX-BPM", + "tool": "CodefulSdkGenerator (LogicAppsCompiler)", + "revision": "b9c9fd25aeeefb309e17054b9bd0697f9b6d4f41", + "compilerSha256": "628dc66c24ff136391dc2d416597e86148bdf3214ec9ab870d9b797c6edb5680" + }, + "swaggerSource": { + "kind": "live-arm-metadata", + "location": "westus", + "capturedAtUtc": "2026-10-12T20:13:21Z", + "primarySubscriptionId": "29374ed4-cdf5-4269-8f87-a1c68dd60276", + "subscriptionExceptions": { + "f34b22a3-2202-4fb1-b040-1332bd928c84": [ + "onedrive", + "orderful", + "universalprint" + ] + } + }, + "packageArtifacts": { + "clientRegistry": { + "path": "src/azure/connectors/_client_registry.py", + "sha256": "1ca2f1db679b442a2e97dc05e21a83c14bba1656d173c0279e0f921e63c2cdd7" + }, + "rootStub": { + "path": "src/azure/connectors/__init__.pyi", + "sha256": "c023c6c6684343946e45a065ee80261adde2e513cc5c6ea75cb598e48d7baa1b" + }, + "asyncRootStub": { + "path": "src/azure/connectors/aio/__init__.pyi", + "sha256": "32b376f740c43c9b38b19b098e142f1fba56e2604c85e0e79bcdaa43111fc56f" + } + }, + "connectors": [ + { + "apiName": "arm", + "outputFile": "src/azure/connectors/arm.py", + "asyncOutputFile": "src/azure/connectors/aio/arm.py", + "outputSha256": "8b411ebf410a8db3a15bee8deedf317d85d151a6000a437bcd130292a95f9e4a", + "asyncOutputSha256": "550d650fa8ba8592d6a49718f929a68558003000e93533571d8712b00355fd46" + }, + { + "apiName": "azuread", + "outputFile": "src/azure/connectors/azuread.py", + "asyncOutputFile": "src/azure/connectors/aio/azuread.py", + "outputSha256": "6ddb925960b21c851097fba2ed2257ba111fe96a5aae1777eb85dc9f59762916", + "asyncOutputSha256": "561bd727bd6a56e6413071b43b2ebe33b427937028baf2a1979ee40c374850c0" + }, + { + "apiName": "azureautomation", + "outputFile": "src/azure/connectors/azureautomation.py", + "asyncOutputFile": "src/azure/connectors/aio/azureautomation.py", + "outputSha256": "36b05b6d4089814406ba9b82047b1f4a7d552fdcdcf44999de8e25c4e5a9ec64", + "asyncOutputSha256": "2dd4198f82c6a87fdc0fd9d8e27272018121d8ec3988f5c3750283d14f6f7bf3" + }, + { + "apiName": "azureblob", + "outputFile": "src/azure/connectors/azureblob.py", + "asyncOutputFile": "src/azure/connectors/aio/azureblob.py", + "outputSha256": "db992f19e9e4bab4f5579c553fbe3e66b83b4816bac8b369931914c94368435c", + "asyncOutputSha256": "f76208b3fa17d97236f74fde2dfbf3a851721dc033fb5084e464f4fb87b8bc60" + }, + { + "apiName": "azuredatafactory", + "outputFile": "src/azure/connectors/azuredatafactory.py", + "asyncOutputFile": "src/azure/connectors/aio/azuredatafactory.py", + "outputSha256": "6ede17808b90703cf0ce986a991911cd3f66f7d9f8c4743c8bf9cd50e8aab83c", + "asyncOutputSha256": "f4c94f751220119956588097aebb410eb101afbbb0fecb448b45c44c483b7436" + }, + { + "apiName": "azuredigitaltwins", + "outputFile": "src/azure/connectors/azuredigitaltwins.py", + "asyncOutputFile": "src/azure/connectors/aio/azuredigitaltwins.py", + "outputSha256": "21ec22356e4fad1dfa9bbbc720a5c565d4179a81c72fc2b8fd117f10e1e10ea3", + "asyncOutputSha256": "6fd1a19f7afc19fe4660e42db2bdb9734d37b3b35f0d83e149fb72ad889b72c7" + }, + { + "apiName": "azureeventgrid", + "outputFile": "src/azure/connectors/azureeventgrid.py", + "asyncOutputFile": "src/azure/connectors/aio/azureeventgrid.py", + "outputSha256": "a1fc8a515c00abfda92b410c0a85008a9241b9a9881e143c7129d833fc7cb44f", + "asyncOutputSha256": "681dc31129c80a5ce77d06d35488a43b44923f51b5c2167aac43de03de85f99c" + }, + { + "apiName": "azureiotcentral", + "outputFile": "src/azure/connectors/azureiotcentral.py", + "asyncOutputFile": "src/azure/connectors/aio/azureiotcentral.py", + "outputSha256": "b255a2ce85b4172f7cb41cb7b9e97d74a709e7f0ac899126244a605b512a3da6", + "asyncOutputSha256": "dad3edae55936ad7c8ee173b3af120a08fedf4757a5ab10e55ac9a5d2f73ba7a" + }, + { + "apiName": "azuremonitorlogs", + "outputFile": "src/azure/connectors/azuremonitorlogs.py", + "asyncOutputFile": "src/azure/connectors/aio/azuremonitorlogs.py", + "outputSha256": "9529bd630e558c14361d6ce4edd4684c2d005ec1dd0d337880a1228e264fb836", + "asyncOutputSha256": "ae11705d9ddb9aec6ee2e1fa6aec70b3f268dc1c4bd916bb6adacc03d9f496e4" + }, + { + "apiName": "azurequeues", + "outputFile": "src/azure/connectors/azurequeues.py", + "asyncOutputFile": "src/azure/connectors/aio/azurequeues.py", + "outputSha256": "116e5d3f81354aec7953b162879325f84f3dcacfb4a5b97f09f161d7093227b9", + "asyncOutputSha256": "fe7c3bdffcceec4b4288a4e47fee16717fb81d137ec7ba9a2eb501269cc7f126" + }, + { + "apiName": "azuretables", + "outputFile": "src/azure/connectors/azuretables.py", + "asyncOutputFile": "src/azure/connectors/aio/azuretables.py", + "outputSha256": "fa00271d10e09ab7411a5004a734a0132dd6c8e9beb732b68bea22401340681c", + "asyncOutputSha256": "50df79ce2a4f590f32cb5b348e99bc902059aefb0957453e2ed838c32ccd6237" + }, + { + "apiName": "azurevm", + "outputFile": "src/azure/connectors/azurevm.py", + "asyncOutputFile": "src/azure/connectors/aio/azurevm.py", + "outputSha256": "9979d392f23ae8b7b82ce403422019492453b0705fb69494aa72e4372406631c", + "asyncOutputSha256": "70f414082061645d9aa7c00cede5b17b9baffa20173951286dddb9339778799f" + }, + { + "apiName": "box", + "outputFile": "src/azure/connectors/box.py", + "asyncOutputFile": "src/azure/connectors/aio/box.py", + "outputSha256": "d46b56fb2ce5ec7d9e895918ecc99770c093c606762841d04174d4ad03f68966", + "asyncOutputSha256": "117a4f75e7084e80b8289c67713b815dbf7ffcb30056f290dbc8faa350a6ad9c" + }, + { + "apiName": "campfire", + "outputFile": "src/azure/connectors/campfire.py", + "asyncOutputFile": "src/azure/connectors/aio/campfire.py", + "outputSha256": "19cf78bb40219a49939a42d2d39c24dad6be01b1b127a16a5b5c30315275e4d0", + "asyncOutputSha256": "6d1db4b5028c9a2fdc0b31ffa714bef5758a03e06c46e33f77ecbbda0b47d660" + }, + { + "apiName": "clicksendsms", + "outputFile": "src/azure/connectors/clicksendsms.py", + "asyncOutputFile": "src/azure/connectors/aio/clicksendsms.py", + "outputSha256": "d3e90eb63f574332b1c2dade4aee03840787ef24b7b9c6248bf6e2d7e5aedd38", + "asyncOutputSha256": "f7771438f4a3339aabc4e623c7253a437a8c07d342d830a8850263b353842c23" + }, + { + "apiName": "cloudconvert", + "outputFile": "src/azure/connectors/cloudconvert.py", + "asyncOutputFile": "src/azure/connectors/aio/cloudconvert.py", + "outputSha256": "6b1d8a1c43b118bca42a0f4275d78f5d78c3cb0cd3954616c786dde827776899", + "asyncOutputSha256": "1fc634e871b3759898f11e79c60305392a644aa8c1c2cb079524af5544eebe7b" + }, + { + "apiName": "cloudmersiveconvert", + "outputFile": "src/azure/connectors/cloudmersiveconvert.py", + "asyncOutputFile": "src/azure/connectors/aio/cloudmersiveconvert.py", + "outputSha256": "7ed6cb8a951707b3ed911d709359bf69a1f65db0df69cee3b4754156842b19f0", + "asyncOutputSha256": "86ba5ae513751acbc32dcf91da1872511f6050660f51b25deb88bd99439bc24b" + }, + { + "apiName": "commondataservice", + "outputFile": "src/azure/connectors/commondataservice.py", + "asyncOutputFile": "src/azure/connectors/aio/commondataservice.py", + "outputSha256": "122dcd490f4dd9a0e1dc305596dbea71552eaab9900c3e68a73f5487c66c7684", + "asyncOutputSha256": "23f1274730216e32b0b2c2041088be34115d05ebe0cf70e957f43c212bf84522" + }, + { + "apiName": "documentdb", + "outputFile": "src/azure/connectors/documentdb.py", + "asyncOutputFile": "src/azure/connectors/aio/documentdb.py", + "outputSha256": "289b16d0c13905d0268806fa532622fc4e8a08a66f919e77793855156d450863", + "asyncOutputSha256": "3b34525348eb2c9e9994527a51f1142f27672f8b483c7225d2e04cf4d24a202e" + }, + { + "apiName": "docusign", + "outputFile": "src/azure/connectors/docusign.py", + "asyncOutputFile": "src/azure/connectors/aio/docusign.py", + "outputSha256": "55219a8cb3695594c23122eb0046d0c4482f6d80f321116f1fff665348a9cf86", + "asyncOutputSha256": "2ffe69b77e365547c8cb4bea85b1aa19b88918932881f4627245f45e6165c82d" + }, + { + "apiName": "docuware", + "outputFile": "src/azure/connectors/docuware.py", + "asyncOutputFile": "src/azure/connectors/aio/docuware.py", + "outputSha256": "6ed1c2e443b7964cace0adb89b573515344f357c6c811ba576b34b520cd6c471", + "asyncOutputSha256": "96eb5906c4998c9099ba75aae1b5508297cf337df832aad41b3caa024cffa96c" + }, + { + "apiName": "dropbox", + "outputFile": "src/azure/connectors/dropbox.py", + "asyncOutputFile": "src/azure/connectors/aio/dropbox.py", + "outputSha256": "bbdff010e465bdf1997c63d7068df59bf306ae0d06be7aa91e43acd89ba27074", + "asyncOutputSha256": "7dcd269c5286f9c545e9be654e2f08988980102859e06a453067bde935889492" + }, + { + "apiName": "dynamicsax", + "outputFile": "src/azure/connectors/dynamicsax.py", + "asyncOutputFile": "src/azure/connectors/aio/dynamicsax.py", + "outputSha256": "fba8f7b49bac54249189419e2443d563c5c1a417a58f8e9d7eea4eccd32e30aa", + "asyncOutputSha256": "c0c18b16a11e8e858bde6232c5e16ba3ecae586f8b7779decdbe36e90e549bf0" + }, + { + "apiName": "elfsquaddata", + "outputFile": "src/azure/connectors/elfsquaddata.py", + "asyncOutputFile": "src/azure/connectors/aio/elfsquaddata.py", + "outputSha256": "3dded34e0ae53f0bcdd8ea8531b5c39366c699a04d6354f71c42ac46205860d0", + "asyncOutputSha256": "97700f4a049a734afeb141df941a0209ad0e8f52bbbfd6af72c1f795455f13f7" + }, + { + "apiName": "etsy", + "outputFile": "src/azure/connectors/etsy.py", + "asyncOutputFile": "src/azure/connectors/aio/etsy.py", + "outputSha256": "b75a6bebce12de1e18e7927feafb04858179344422417942104c6d918f47afb3", + "asyncOutputSha256": "a777fe2405f5c0470abd0b109724c2b55dff1e352ff215799ebba95ec5d0f4dc" + }, + { + "apiName": "eventbrite", + "outputFile": "src/azure/connectors/eventbrite.py", + "asyncOutputFile": "src/azure/connectors/aio/eventbrite.py", + "outputSha256": "6bfdb9364ac9571a500d2ea6480cb556db5b1300c3bc42116840da5605f66be2", + "asyncOutputSha256": "952516f5d50111940f2a38ed36b5ab80beaeb4ffe6247f95c318307170141570" + }, + { + "apiName": "eventhubs", + "outputFile": "src/azure/connectors/eventhubs.py", + "asyncOutputFile": "src/azure/connectors/aio/eventhubs.py", + "outputSha256": "413395ffc06c25df429315c49bd0d765b75dd902fb484e40174d84174dbaf806", + "asyncOutputSha256": "dd158809eb94a03a58262d385575919a69e94e4471f0780b1c9b570d1619a482" + }, + { + "apiName": "excelonline", + "outputFile": "src/azure/connectors/excelonline.py", + "asyncOutputFile": "src/azure/connectors/aio/excelonline.py", + "outputSha256": "674affe736d2d5bc447018d7a17bd4b08ab1328af91ddb05abd39f712cb5ae1f", + "asyncOutputSha256": "d17150758ac1823173ba2cb74b86cf97c857d14618d93791d1f0a2576930df43" + }, + { + "apiName": "excelonlinebusiness", + "outputFile": "src/azure/connectors/excelonlinebusiness.py", + "asyncOutputFile": "src/azure/connectors/aio/excelonlinebusiness.py", + "outputSha256": "a4d3fe42a7fbce7ffaea215b57b12b7d3c146497afc34d993ef06d96228d4f92", + "asyncOutputSha256": "bdde50f727f3178471a46b8361d9dc7514d889859cfcb0a5fc5ce1e90efb82c7" + }, + { + "apiName": "formstackforms", + "outputFile": "src/azure/connectors/formstackforms.py", + "asyncOutputFile": "src/azure/connectors/aio/formstackforms.py", + "outputSha256": "afdf0995ef9e59bb7fc0b9be26db60382d52f3bf1d9da1da77de0411b76e45a4", + "asyncOutputSha256": "1ecb09e7a56dcc2625c76b6991ee39d9e756b7ebc2738dc4a26cc774d0e0eb05" + }, + { + "apiName": "freshservice", + "outputFile": "src/azure/connectors/freshservice.py", + "asyncOutputFile": "src/azure/connectors/aio/freshservice.py", + "outputSha256": "123f882b47a7164b4e29515495f6376bbe78f8afbf0210d5a27d721ff2679ad9", + "asyncOutputSha256": "b28bfcc43f8685aed3ccbd88b805320abc05f18ab380cf1287f11caf27a46088" + }, + { + "apiName": "ftp", + "outputFile": "src/azure/connectors/ftp.py", + "asyncOutputFile": "src/azure/connectors/aio/ftp.py", + "outputSha256": "dec41b59b097547184a57be678605bedb1b91ebee2505d51817778285fa99b64", + "asyncOutputSha256": "e31f1006cd00bed5607544dcd06a16326f3bcf937f864a72de771e771fc592ea" + }, + { + "apiName": "github", + "outputFile": "src/azure/connectors/github.py", + "asyncOutputFile": "src/azure/connectors/aio/github.py", + "outputSha256": "716832c5b0246fec33741bc63699f2f16350eaeed7a1c62cd0b4493ba6b4a055", + "asyncOutputSha256": "9cf6578590dcae31c7918842d6b797cd25bb46d384b5d9f6e7e0c5298189e68e" + }, + { + "apiName": "googlecalendar", + "outputFile": "src/azure/connectors/googlecalendar.py", + "asyncOutputFile": "src/azure/connectors/aio/googlecalendar.py", + "outputSha256": "75398e1f244eea52c0f671d750c1796d3f45ca41ca8973f62fda6e964898160b", + "asyncOutputSha256": "6602cdea0053e2318b416bbbe320a3552062e1b91660cf39c478b7c47dc249ae" + }, + { + "apiName": "googledrive", + "outputFile": "src/azure/connectors/googledrive.py", + "asyncOutputFile": "src/azure/connectors/aio/googledrive.py", + "outputSha256": "550964859c6f6c4a78c27f523aa000a130b3db770f34e7d88860e5fca0d85e52", + "asyncOutputSha256": "681be243672436877accae82f77607ac860e84d971da8c46fe00b295e38c93b1" + }, + { + "apiName": "googletasks", + "outputFile": "src/azure/connectors/googletasks.py", + "asyncOutputFile": "src/azure/connectors/aio/googletasks.py", + "outputSha256": "2cd1fde5fed4c0ed034a0f3e6267e5ed266f6b30130dc75de9405b05622ad9b1", + "asyncOutputSha256": "4f872113535e4c1b996527a38d4d39953718c463f6c1f839c06bbde9a2d24400" + }, + { + "apiName": "impexium", + "outputFile": "src/azure/connectors/impexium.py", + "asyncOutputFile": "src/azure/connectors/aio/impexium.py", + "outputSha256": "b9f86a2ffbd1fa8a99a7249f99cc354dcacd0d8e1fa4146b0878f863a704385e", + "asyncOutputSha256": "90ee084d4e4d15652b61e84bfb7d75c6ac309b1dbcf99ad535101150797527c1" + }, + { + "apiName": "infusionsoft", + "outputFile": "src/azure/connectors/infusionsoft.py", + "asyncOutputFile": "src/azure/connectors/aio/infusionsoft.py", + "outputSha256": "a126b2b73775e9733192cba76f2e23b48b4b01d1764370752e7a6a91a06249e1", + "asyncOutputSha256": "a0a64b850fc26ed66a7107b7bc63563aa85874d9b14270f856cf8eb43d4fe463" + }, + { + "apiName": "insightly", + "outputFile": "src/azure/connectors/insightly.py", + "asyncOutputFile": "src/azure/connectors/aio/insightly.py", + "outputSha256": "1348d4f2cf319ede3d3170c6d0e97b4200a1ac5cea68d88fe440680f558928ab", + "asyncOutputSha256": "2588199484ce145ebbc4ea7d44fb6da1bda8275b17dece0073e07cec9bafcee0" + }, + { + "apiName": "jedoxodatahub", + "outputFile": "src/azure/connectors/jedoxodatahub.py", + "asyncOutputFile": "src/azure/connectors/aio/jedoxodatahub.py", + "outputSha256": "69d6b0afd1ef99486a5193add4108caef04cd0bc7a3e7a24f09b5f84659fcfbf", + "asyncOutputSha256": "1b86674e8c8338d9edee84066f7a1d797797484ed3a58fdaf478ff2a1e82585b" + }, + { + "apiName": "jira", + "outputFile": "src/azure/connectors/jira.py", + "asyncOutputFile": "src/azure/connectors/aio/jira.py", + "outputSha256": "d52ea503644056b8b803c79d92d0b4026bb0c5d16b19cc30bb227902a1927052", + "asyncOutputSha256": "31643062cefe4ae2287188ec68676f7460688535ed3d207094781e4cac1b6446" + }, + { + "apiName": "keyvault", + "outputFile": "src/azure/connectors/keyvault.py", + "asyncOutputFile": "src/azure/connectors/aio/keyvault.py", + "outputSha256": "897f0e4a1edd5f9c36d45b72e68afb8813a92042e8f017d7bf7081ea26875f61", + "asyncOutputSha256": "0d073c5335f5e49df3c9aa2050b3d262039090d3164fdb050184ab693969837d" + }, + { + "apiName": "kusto", + "outputFile": "src/azure/connectors/kusto.py", + "asyncOutputFile": "src/azure/connectors/aio/kusto.py", + "outputSha256": "6888211814cb7fd975a3c0c5d2d8fc065217b7e3338e059cdd705ff5a4b2cf7b", + "asyncOutputSha256": "8fbcf80bb4eaba9e3e2ce2ff837fbd0396bbf392b4fe3fdcec62d955c49169eb" + }, + { + "apiName": "mailchimp", + "outputFile": "src/azure/connectors/mailchimp.py", + "asyncOutputFile": "src/azure/connectors/aio/mailchimp.py", + "outputSha256": "cdc17de3aa5fcd6ba03607b055318ff133c47c77cac9282681db5cf4037906cb", + "asyncOutputSha256": "daf584f845b03a8d9ca6da2861880f445825a1cd23799b47ee627a905ba2451b" + }, + { + "apiName": "meetingroommap", + "outputFile": "src/azure/connectors/meetingroommap.py", + "asyncOutputFile": "src/azure/connectors/aio/meetingroommap.py", + "outputSha256": "ff8174f69128c6e43210fa176fcf558f18e12156f97fe41819f45e64a4aea98f", + "asyncOutputSha256": "7122e2a6a191c6606366906252a9f3aed6230500ded1356fb0f548a737e294e8" + }, + { + "apiName": "microsoftbookings", + "outputFile": "src/azure/connectors/microsoftbookings.py", + "asyncOutputFile": "src/azure/connectors/aio/microsoftbookings.py", + "outputSha256": "018a07b59482e4a37228b61ba7be7687f0372d772cb3211b2f4b1e03d23174ba", + "asyncOutputSha256": "7440adf6ac80b124b472686fadaa307452b0213fc634fcfdb97cfa000485eff9" + }, + { + "apiName": "microsoftforms", + "outputFile": "src/azure/connectors/microsoftforms.py", + "asyncOutputFile": "src/azure/connectors/aio/microsoftforms.py", + "outputSha256": "6fc588be612b607dee98a12144c5c64597ec1488e27ad9d54391eae1db7f896f", + "asyncOutputSha256": "a77342a6343420c22ee9a4c1bb0654c260dae94bd4ceefa8b9a3e580a472460d" + }, + { + "apiName": "monday", + "outputFile": "src/azure/connectors/monday.py", + "asyncOutputFile": "src/azure/connectors/aio/monday.py", + "outputSha256": "2dcd70e31b40d6dc0316becca11de7e97a63d65f243acef22605aa555cd1c95d", + "asyncOutputSha256": "ab2577dd194c7f4e72b3447ef059e51bbbeb83e35064e401f6fbb77ebc60987f" + }, + { + "apiName": "mq", + "outputFile": "src/azure/connectors/mq.py", + "asyncOutputFile": "src/azure/connectors/aio/mq.py", + "outputSha256": "e68b57f56283dfd76a1695bada303082b1b73cd11314e8d8f836d002cef73e65", + "asyncOutputSha256": "53d05d14fec5352f7a00264a1dce03b2509ae00ab5e32cd35bc5cca6dd3d8ddf" + }, + { + "apiName": "msgraphgroupsanduser", + "outputFile": "src/azure/connectors/msgraphgroupsanduser.py", + "asyncOutputFile": "src/azure/connectors/aio/msgraphgroupsanduser.py", + "outputSha256": "40a47f00590276af1c2690e91379514e46fa1ae62cd6e574efa2791882db5e09", + "asyncOutputSha256": "35491ff502e47e2dbdcaae0904b07261dfd09d13d143d6235c12f8835beaa509" + }, + { + "apiName": "office365", + "outputFile": "src/azure/connectors/office365.py", + "asyncOutputFile": "src/azure/connectors/aio/office365.py", + "outputSha256": "7b068277e7b75b958af61327f5835685a72d96d02dd74469254ed60ce20dc79e", + "asyncOutputSha256": "539f08a6f5c660630b4b5b1ca10334b2a7d18e41bb39278a82be81fb9fb9c75e" + }, + { + "apiName": "office365groups", + "outputFile": "src/azure/connectors/office365groups.py", + "asyncOutputFile": "src/azure/connectors/aio/office365groups.py", + "outputSha256": "1654502a6c4b6df0a50b2d81ab69ade6215a115052e90755a6206f7497566480", + "asyncOutputSha256": "b09694d0fa20da383bfeb4efe3b943b4c02f72a57c4851ae1a28af2f978729ca" + }, + { + "apiName": "office365groupsmail", + "outputFile": "src/azure/connectors/office365groupsmail.py", + "asyncOutputFile": "src/azure/connectors/aio/office365groupsmail.py", + "outputSha256": "860975344e917f482ae0f8e3923f0b39c3f586b26e88dabcb4005bbd60277971", + "asyncOutputSha256": "4e5ffabb5a26675c4a6014791e76e752644c6caf11c65fad793c3101b309e14c" + }, + { + "apiName": "office365users", + "outputFile": "src/azure/connectors/office365users.py", + "asyncOutputFile": "src/azure/connectors/aio/office365users.py", + "outputSha256": "6e28b9027c69f14a05da97795462679d0c90db80b983c004bb2419bb2a985a39", + "asyncOutputSha256": "2d234f95ede630def9d12600248a8fda022e806d1955398bf475546e383b7e88" + }, + { + "apiName": "onedrive", + "outputFile": "src/azure/connectors/onedrive.py", + "asyncOutputFile": "src/azure/connectors/aio/onedrive.py", + "outputSha256": "9f624be8dae44949e38a9159f27a3bed3500505f904c35a45ecd3c1596440a18", + "asyncOutputSha256": "a888472ce8d248c65273430a06485257174895901913d59a0d653bf837aa7b5e" + }, + { + "apiName": "onedriveforbusiness", + "outputFile": "src/azure/connectors/onedriveforbusiness.py", + "asyncOutputFile": "src/azure/connectors/aio/onedriveforbusiness.py", + "outputSha256": "4bc741dd092ac1c8fce85f4b543b2b48eebb58825692cbb1c75d37d7155a1567", + "asyncOutputSha256": "694f3d4aa09977588cc1788d3ee3585321ae704e3be55c8b9a7683dfe36c9e6d" + }, + { + "apiName": "onenote", + "outputFile": "src/azure/connectors/onenote.py", + "asyncOutputFile": "src/azure/connectors/aio/onenote.py", + "outputSha256": "428e2f7985f73f7381142f88f3c6d6d80877924f298eab4e22dbb1e86b4ea424", + "asyncOutputSha256": "3d6039ef1d9c103de6c3db5d72004266d663b4a85d7b33a04dc7139b3f46c884" + }, + { + "apiName": "orderful", + "outputFile": "src/azure/connectors/orderful.py", + "asyncOutputFile": "src/azure/connectors/aio/orderful.py", + "outputSha256": "f152ee55db1f20fd385004c117a559a1a8d035212f6318b850b4e0355c7ff5ce", + "asyncOutputSha256": "b258d5017c26c5125ebf7c05c86cc65487bdea337e9f998ca8ddea6d2711ceb4" + }, + { + "apiName": "outlook", + "outputFile": "src/azure/connectors/outlook.py", + "asyncOutputFile": "src/azure/connectors/aio/outlook.py", + "outputSha256": "1be10fbec82f049c4138afefe24c5163a5b6ad9ce141fa3cd898fe63cb654ab7", + "asyncOutputSha256": "e841a5d4112818337cbb41ae664f5d00177a47f346d9961105b6a213e1ca0f0c" + }, + { + "apiName": "pdfco", + "outputFile": "src/azure/connectors/pdfco.py", + "asyncOutputFile": "src/azure/connectors/aio/pdfco.py", + "outputSha256": "1c5b711e6cb3a15d470a052d1161fe92cc2e4a1c1531bae3e41a3e03174931c8", + "asyncOutputSha256": "1646a35255c1e43a70e2f6b267f325c05e715d51e1d00615af68fa16a590d67a" + }, + { + "apiName": "pipedrive", + "outputFile": "src/azure/connectors/pipedrive.py", + "asyncOutputFile": "src/azure/connectors/aio/pipedrive.py", + "outputSha256": "605cc988214469de7a4e178398d802e65287c5b4df2dbd5be94853b023d387d3", + "asyncOutputSha256": "79459fbefc0a9e2b6b5dca7dbd88e8c73f3992aa558f928c8e47ad9b3eba8716" + }, + { + "apiName": "planner", + "outputFile": "src/azure/connectors/planner.py", + "asyncOutputFile": "src/azure/connectors/aio/planner.py", + "outputSha256": "8b858d258e1f6ffeef541202cda0e8961fe61a89d14d455dce589867c899aace", + "asyncOutputSha256": "6bd9a45844fb51524c0f359b2b9023375a2aff181ad7089b7701201b1ae4abed" + }, + { + "apiName": "plivo", + "outputFile": "src/azure/connectors/plivo.py", + "asyncOutputFile": "src/azure/connectors/aio/plivo.py", + "outputSha256": "9f0b29fdb1c2a072ee7c06f383601562e7d5f007f0774e7c9675963f2acd20aa", + "asyncOutputSha256": "be4bd0a6e3c04cd220cd67744379da5ddc6e4b520e6627f17001a71c82230509" + }, + { + "apiName": "plumsail", + "outputFile": "src/azure/connectors/plumsail.py", + "asyncOutputFile": "src/azure/connectors/aio/plumsail.py", + "outputSha256": "dc6dc5e7f991214f9775ac086f895b13330d776b940792394e8a4557896b05bc", + "asyncOutputSha256": "9b4af7f0f7b1cafb36695a429312796b6da9e98827c6a57fe4ea6d1989982c6d" + }, + { + "apiName": "powerbi", + "outputFile": "src/azure/connectors/powerbi.py", + "asyncOutputFile": "src/azure/connectors/aio/powerbi.py", + "outputSha256": "2f4601649afac460e880532c34d09045d11daee266f1968ad171089a72bf7407", + "asyncOutputSha256": "c5fc5bce59a11f0c82224f6d4119f581aaf21a5c9422be290af0a02a289faf71" + }, + { + "apiName": "projectplace", + "outputFile": "src/azure/connectors/projectplace.py", + "asyncOutputFile": "src/azure/connectors/aio/projectplace.py", + "outputSha256": "b3c0a2da29c617184ac14cbf264b75745860ebf6263b45c43f40f638ba3d848f", + "asyncOutputSha256": "4cb00176e973753edaf92eb27a4a9fc386d24e80654eb37ebfeb2bdb3a5ccaad" + }, + { + "apiName": "replicon", + "outputFile": "src/azure/connectors/replicon.py", + "asyncOutputFile": "src/azure/connectors/aio/replicon.py", + "outputSha256": "a6dbac74957b5d4da5186573e5f5a0234d872abeaffe5d4a76686bb2950f0881", + "asyncOutputSha256": "1ff55679a50a32fb6dab37e72d7a2a1d1642945247c17c0d02a0eb5e119a6b92" + }, + { + "apiName": "revai", + "outputFile": "src/azure/connectors/revai.py", + "asyncOutputFile": "src/azure/connectors/aio/revai.py", + "outputSha256": "64e298bb5185b36e02030bcd5a49e0ced2a83538fc0bbf3c4c6ae61326d4001f", + "asyncOutputSha256": "0635f928a5e092855c3da47d281aa0d671d1489ed9e715e946514265c5f35cf3" + }, + { + "apiName": "rss", + "outputFile": "src/azure/connectors/rss.py", + "asyncOutputFile": "src/azure/connectors/aio/rss.py", + "outputSha256": "cccd106cf46b7b297849fc1c82b3010e46beae6b92c768699ef41856da5e7b80", + "asyncOutputSha256": "cb50b3d947549ca6f5b5956f2025eaed9e6306532fdbbb5f9ac3c427726f2447" + }, + { + "apiName": "salesforce", + "outputFile": "src/azure/connectors/salesforce.py", + "asyncOutputFile": "src/azure/connectors/aio/salesforce.py", + "outputSha256": "b8ee0415667b5d7051caecc0708169d8e2521f416ebdd085420b34ed59bd1a37", + "asyncOutputSha256": "11a4fea3142502e581e66512d09edbfc1e0c32c0861e23b31853588ac6826de0" + }, + { + "apiName": "seismicplanner", + "outputFile": "src/azure/connectors/seismicplanner.py", + "asyncOutputFile": "src/azure/connectors/aio/seismicplanner.py", + "outputSha256": "8a42af8627bac5c95b634f6dfdf0bc56812cb01d5f5deb3750229fe017b61291", + "asyncOutputSha256": "63822896af6e9f6f7edbb3ba73d136236cc20ddcca673d5eedb0f4ce8e52fc3d" + }, + { + "apiName": "sendgrid", + "outputFile": "src/azure/connectors/sendgrid.py", + "asyncOutputFile": "src/azure/connectors/aio/sendgrid.py", + "outputSha256": "d11a1f11e4822a3ee5dc944d3a3885e96bd72ef3c0b11f8ad194f51b7fc2df95", + "asyncOutputSha256": "2ddc91f26be84a8a2e59206bdd803a35d8435d3a799b968e815ff247b3802beb" + }, + { + "apiName": "servicebus", + "outputFile": "src/azure/connectors/servicebus.py", + "asyncOutputFile": "src/azure/connectors/aio/servicebus.py", + "outputSha256": "f6af3bf3b02fc5692c32ffb116fa1d32664b8b67d7965a9c18606b131b9dea5a", + "asyncOutputSha256": "32e72de1c031bc8956f83155a9f26695eaaab8a0a73f71c60bbc8c7183028e18" + }, + { + "apiName": "sharepointonline", + "outputFile": "src/azure/connectors/sharepointonline.py", + "asyncOutputFile": "src/azure/connectors/aio/sharepointonline.py", + "outputSha256": "e8744a881ba482f933920cf2ada8d198061bea7ac97495927d988064dca2ecad", + "asyncOutputSha256": "4e21f7deab19a9e5cad6387bbeaf2eec829c0ff0a1ab3edc51fdfdac2bb5a345" + }, + { + "apiName": "shifts", + "outputFile": "src/azure/connectors/shifts.py", + "asyncOutputFile": "src/azure/connectors/aio/shifts.py", + "outputSha256": "63cc544df2903894fcb39b4270c217cea09a8c8df91c929ba3dc9f48c4a031b0", + "asyncOutputSha256": "b17def4aba62a2c20a29395df6c8ad21b9e31bd63f656a892841383dac04112a" + }, + { + "apiName": "signinghub", + "outputFile": "src/azure/connectors/signinghub.py", + "asyncOutputFile": "src/azure/connectors/aio/signinghub.py", + "outputSha256": "7dd457ba507c15f8105a31698d45454362ff93dc55b6cbb5cb8e2895c80cd992", + "asyncOutputSha256": "07007dd8dba2b065a1fe22bf1a07f48042727422ab405992e469602b7b8f2df1" + }, + { + "apiName": "slack", + "outputFile": "src/azure/connectors/slack.py", + "asyncOutputFile": "src/azure/connectors/aio/slack.py", + "outputSha256": "348bbd316f9bd4d8462d02d300ed085ef43574be381007e4a585a12bb69fd230", + "asyncOutputSha256": "9a1ed65989c5ced40a911c31afa44689c7b724b298cc1d1a7ac68fee4288b598" + }, + { + "apiName": "smtp", + "outputFile": "src/azure/connectors/smtp.py", + "asyncOutputFile": "src/azure/connectors/aio/smtp.py", + "outputSha256": "aeeddbd8580df8b1d4716bf334e519bd659092d0eb9c44577511ecd3a9c92f55", + "asyncOutputSha256": "836a31654c6140ec4c9c2021c32f2660ad9e6885756cce284a6c2f835113c067" + }, + { + "apiName": "sql", + "outputFile": "src/azure/connectors/sql.py", + "asyncOutputFile": "src/azure/connectors/aio/sql.py", + "outputSha256": "c2f5fd0399ce8ff8252f9e1a36400a58c77b6521e3df0482205201661116dde6", + "asyncOutputSha256": "d5f2f59ea1dd6ab5dc5f3807dc84ebd101b587f87565278a85662717dae462e7" + }, + { + "apiName": "starmind", + "outputFile": "src/azure/connectors/starmind.py", + "asyncOutputFile": "src/azure/connectors/aio/starmind.py", + "outputSha256": "687888e2b0cf8b4978ff9e113e14073f8d46683a7893dd817069231d4f715068", + "asyncOutputSha256": "f09f7d3f997a21801ca4d084da79fd614a88bcc9845663b0e05fce3e7eb5ecac" + }, + { + "apiName": "starrezrestv1", + "outputFile": "src/azure/connectors/starrezrestv1.py", + "asyncOutputFile": "src/azure/connectors/aio/starrezrestv1.py", + "outputSha256": "dd7f534f5d05447d11c765735b1c0beec8423789bb571bd1e7684f95c2c2d8b7", + "asyncOutputSha256": "1ee7e0d29ed5d4c0e5291bd288f0c50314c8913caaa18484313c3b14ea990be4" + }, + { + "apiName": "tallyfy", + "outputFile": "src/azure/connectors/tallyfy.py", + "asyncOutputFile": "src/azure/connectors/aio/tallyfy.py", + "outputSha256": "d3b6438f00a677bc87ad0bbb9bb689712de5eb76000150e28dfc2f69dc981c68", + "asyncOutputSha256": "732315d0408d665e9cd475cea76fd3dc96f8a53ad11dcc07a5a7aa4c9e147be9" + }, + { + "apiName": "teams", + "outputFile": "src/azure/connectors/teams.py", + "asyncOutputFile": "src/azure/connectors/aio/teams.py", + "outputSha256": "b559a5edb373bec4992f0b8d699f3ecc0418f14ddca1cb664a867a617abdbe07", + "asyncOutputSha256": "d56e8f90f615e4eff5b21f5840f9bf2cbb04596bc1d392a3cea0ae996d2b3ae7" + }, + { + "apiName": "textrequest", + "outputFile": "src/azure/connectors/textrequest.py", + "asyncOutputFile": "src/azure/connectors/aio/textrequest.py", + "outputSha256": "e90a7ab553795a914e69c4b17573769a42591f01e4c0f6ff04173dbd1e51b1cb", + "asyncOutputSha256": "c9bfcf8692acf7792aa775125d4a4017c13adf0ea1f708ee431e5e55221b4c33" + }, + { + "apiName": "ticketmaster", + "outputFile": "src/azure/connectors/ticketmaster.py", + "asyncOutputFile": "src/azure/connectors/aio/ticketmaster.py", + "outputSha256": "11e7a78c71e0a3644837e2eb1ced2e481d2ee05b750ed1ef48cb9a90b6a967e6", + "asyncOutputSha256": "4a85c4b9acf6f11e700c909bcbe2b705bd0184c103b438ac49390a18182faf9d" + }, + { + "apiName": "todo", + "outputFile": "src/azure/connectors/todo.py", + "asyncOutputFile": "src/azure/connectors/aio/todo.py", + "outputSha256": "aabbfbe9c8caa0f751f14454ed722ebcde2d90893c5c7b5d736505b8893dd59c", + "asyncOutputSha256": "19362eabc94016bbe8bea9d110172c60eb2ae6e9d215a4238eab4813cea3661a" + }, + { + "apiName": "trello", + "outputFile": "src/azure/connectors/trello.py", + "asyncOutputFile": "src/azure/connectors/aio/trello.py", + "outputSha256": "8ab6a5f2a7f2c777edc92e3334033908460d997c56c839758809096043aff0b7", + "asyncOutputSha256": "9fe415ab128653a0f2f61541ab027691574acfeeb948b46f8b307f04fbb3159f" + }, + { + "apiName": "twitter", + "outputFile": "src/azure/connectors/twitter.py", + "asyncOutputFile": "src/azure/connectors/aio/twitter.py", + "outputSha256": "66bba00854d8197b5c327b58e3de52101c5570cdcbb4f14d208c828bc36b220c", + "asyncOutputSha256": "ece210456ad30bb1233d32b7e4da726b8d610027a1818b4deeca48970da8b637" + }, + { + "apiName": "typeform", + "outputFile": "src/azure/connectors/typeform.py", + "asyncOutputFile": "src/azure/connectors/aio/typeform.py", + "outputSha256": "66d38e9e8c40997779028b13223808c4002b6352380cc37624c74b57d2ea13f3", + "asyncOutputSha256": "1feaa3dcf681f63410371c5eb088ce64924366ff2c6557ff154c0579cd12fb97" + }, + { + "apiName": "universalprint", + "outputFile": "src/azure/connectors/universalprint.py", + "asyncOutputFile": "src/azure/connectors/aio/universalprint.py", + "outputSha256": "bebe1e1d3fcdec288aa9cd219c4321001f51ff69c458a98cb39e33d525d4adab", + "asyncOutputSha256": "0a17df1c3ce0d65f975d3eda98767b41cf237700757285b653a088bab2949626" + }, + { + "apiName": "waywedo", + "outputFile": "src/azure/connectors/waywedo.py", + "asyncOutputFile": "src/azure/connectors/aio/waywedo.py", + "outputSha256": "c8e6394b2c042b86d13908ff60a993885f2e6885769114738de28ec71c9743c7", + "asyncOutputSha256": "35eee1214173a81687cf7899fa28199ea5ce72fe30412f55a730ffcef2886d20" + }, + { + "apiName": "wdatp", + "outputFile": "src/azure/connectors/wdatp.py", + "asyncOutputFile": "src/azure/connectors/aio/wdatp.py", + "outputSha256": "c8cf44f4b2a72f053fd60a500938a4e58123db18ef0fb9654c5a8cdc58559fa2", + "asyncOutputSha256": "c6992615ea12cd317fdd7700fd9d0cd1c934b40ca12f822ff11a0ea27bbf4b66" + }, + { + "apiName": "webex", + "outputFile": "src/azure/connectors/webex.py", + "asyncOutputFile": "src/azure/connectors/aio/webex.py", + "outputSha256": "5ae1df6036dbfcce94eb605367bf610d237f202d46091b54bc74086db63bcbf8", + "asyncOutputSha256": "39fecdc4d947c54dc754f1e8844d21a4a7360a083edb7b206c7b39c685cfb955" + }, + { + "apiName": "wordonlinebusiness", + "outputFile": "src/azure/connectors/wordonlinebusiness.py", + "asyncOutputFile": "src/azure/connectors/aio/wordonlinebusiness.py", + "outputSha256": "4dd9240e0df2dd9751bbdc93801f240f0f21959c9f648d85431e1be93f7fe2fb", + "asyncOutputSha256": "a1966b946426e663ea8c8a7e632f2d2ba749d8dcbac1580481e493fccc745b9f" + }, + { + "apiName": "wordpress", + "outputFile": "src/azure/connectors/wordpress.py", + "asyncOutputFile": "src/azure/connectors/aio/wordpress.py", + "outputSha256": "689ab6c3b504ca581ec8778538610c979098e1ea3e1ebdc3b14e40049102f19b", + "asyncOutputSha256": "46692bd67d72c4de6df6d8ac3d784adb60a25f2ab3ff68cfcefba5880c83eb9c" + }, + { + "apiName": "yammer", + "outputFile": "src/azure/connectors/yammer.py", + "asyncOutputFile": "src/azure/connectors/aio/yammer.py", + "outputSha256": "e583679b78f7fd22de52530d09fa06abec978d19d7e47f7cec76b71dfacd2a54", + "asyncOutputSha256": "523e2b19ffe22bfeb57ececc98fbab674c5a7a5db259b88f3bf4db0c2537f224" + }, + { + "apiName": "zendesk", + "outputFile": "src/azure/connectors/zendesk.py", + "asyncOutputFile": "src/azure/connectors/aio/zendesk.py", + "outputSha256": "31e54325ebcb1a21ec4a64b1762274a42202d4535b26c9bf3e25cff1fefbbb60", + "asyncOutputSha256": "cb45b9e75f50d4037b8ada21d92c7acdf0c2318196b2e0529ef15fdf4130941e" + }, + { + "apiName": "zeptomail", + "outputFile": "src/azure/connectors/zeptomail.py", + "asyncOutputFile": "src/azure/connectors/aio/zeptomail.py", + "outputSha256": "a46ebb70ac9dc41b283f9748d34ae8f55ef83b8bea528bdf2c4839788c505820", + "asyncOutputSha256": "c57588a81e5736a0d965e59f1400a92cd1298d7ba15a464bf20a3df3ef21180a" + }, + { + "apiName": "zohosign", + "outputFile": "src/azure/connectors/zohosign.py", + "asyncOutputFile": "src/azure/connectors/aio/zohosign.py", + "outputSha256": "00ede7d91909f3188d36192245d45b9ccb265d842c516a95dcb8b8534a4fa794", + "asyncOutputSha256": "0645a7d8b147dd4be9d78885d25cf7231904fb5e5cc05be5e80e0245b7a0cd08" + } + ] +} diff --git a/samples/sample_connector_usage/README.md b/samples/sample_connector_usage/README.md index a077d8d..b2ec0fa 100644 --- a/samples/sample_connector_usage/README.md +++ b/samples/sample_connector_usage/README.md @@ -10,10 +10,16 @@ This directory contains samples demonstrating how to use the Azure Connectors SD ## Samples -Each sample file (`sample_connector_usage_*.py`) demonstrates a specific connector's operations. Run any sample with: +Each connector has a synchronous sample in this directory and an asynchronous +counterpart under `aio/`. Both catalogs contain 99 files and use identical +unsuffixed operation names. Run either mode with: ```bash +# Synchronous python sample_connector_usage_.py + +# Asynchronous +python aio/sample_connector_usage_.py ``` | Sample | Connector | Environment Variable | @@ -128,40 +134,74 @@ $env:OFFICE365_CONNECTION_URL = "https://[region].azure-apihub.net/apim/office36 export OFFICE365_CONNECTION_URL="https://[region].azure-apihub.net/apim/office365/[connection-id]" ``` -## Usage Pattern +## Usage Patterns + +Root connector modules provide synchronous clients and shared models: + +```python +from azure.identity import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors. import Client + +CONNECTION_URL = "https://[region].azure-apihub.net/apim//[connection-id]" + +def main(): + with DefaultAzureCredential() as credential: + with Client(CONNECTION_URL, credential) as client: + try: + result = client.() + print(result) + except ConnectorException as ex: + print(f"Connector error: {ex}") +``` -All connector clients follow the same async context manager pattern: +Asynchronous clients live in the matching `aio` connector module. Import +request and response models from the root module: ```python import asyncio + from azure.identity.aio import DefaultAzureCredential + from azure.connectors import ConnectorException -from azure.connectors. import Client +from azure.connectors.aio. import Client +from azure.connectors. import CONNECTION_URL = "https://[region].azure-apihub.net/apim//[connection-id]" + async def main(): - credential = DefaultAzureCredential() - - async with Client(CONNECTION_URL, credential) as client: - try: - result = await client._async() - print(result) - except ConnectorException as ex: - print(f"Connector error: {ex}") + async with DefaultAzureCredential() as credential: + async with Client(CONNECTION_URL, credential) as client: + try: + result = await client.(()) + print(result) + except ConnectorException as ex: + print(f"Connector error: {ex}") + asyncio.run(main()) ``` +Pageable operations return `ItemPaged` from root clients and `AsyncItemPaged` +from aio clients. Iterate the pager directly; do not await pager construction. + ## Error Handling -The SDK provides structured error handling via `ConnectorException`: +The SDK provides structured error handling via `ConnectorException` in both +modes: ```python -from azure.connectors import ConnectorException +try: + result = client.some_operation() +except ConnectorException as ex: + print(f"Status: {ex.status_code}, Message: {ex}") +``` +```python try: - result = await client.some_operation_async() + result = await client.some_operation() except ConnectorException as ex: print(f"Status: {ex.status_code}, Message: {ex}") ``` @@ -170,12 +210,12 @@ except ConnectorException as ex: 1. Set up a connection in Azure Portal (see [connection-setup.md](../../docs/connection-setup.md)) 2. Set the connection runtime URL environment variable -3. Run the sample for your connector +3. Run the sync or aio sample for your connector 4. Use typed clients in your application 5. Deploy to Azure Functions or run locally ## Reference -- Python SDK: [PythonSDK/src/azure_workflows_connectors_sdk](../../src/azure_workflows_connectors_sdk) +- API Reference: [Azure Connectors Python SDK](https://azure.github.io/connectors-python-sdk/) - Generation Guide: [GENERATION.md](../../GENERATION.md) -- .NET Sample: [DotnetSDK/samples/SampleConnectorUsage](../../../DotnetSDK/samples/SampleConnectorUsage) +- Migration Guide: [Sync/aio migration](../../docs/migration-sync-aio.md) diff --git a/samples/sample_connector_usage/aio/__init__.py b/samples/sample_connector_usage/aio/__init__.py new file mode 100644 index 0000000..92497bf --- /dev/null +++ b/samples/sample_connector_usage/aio/__init__.py @@ -0,0 +1 @@ +"""Asynchronous connector usage samples.""" diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_arm.py b/samples/sample_connector_usage/aio/sample_connector_usage_arm.py new file mode 100644 index 0000000..072e125 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_arm.py @@ -0,0 +1,179 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure Resource Manager (ARM) sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the ARM client from the Azure Connectors Python SDK to interact +with Azure Resource Manager APIs. + +Prerequisites: +1. Azure subscription with ARM connection +2. ARM connection in Connector Namespaces (with OAuth consent) +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:ARM_CONNECTION_URL = "https://[region].azure-apihub.net/apim/arm/[connection-id]" + + python sample_connector_usage_arm.py + +Note: + The ARM connector uses OAuth (user-delegated Azure AD token). + The connection requires OAuth consent via the consent link flow. +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.arm import ArmClient + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/arm/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "ARM_CONNECTION_URL", + "" +) + + +async def example_1_list_subscriptions(): + """Example 1: List all subscriptions accessible to the authenticated user.""" + print("\n=== Example 1: List Subscriptions ===") + + async with DefaultAzureCredential() as credential: + + async with ArmClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + subscriptions = [ + item async for item in client.list_subscriptions() + ] + + if subscriptions: + print(f"Found {len(subscriptions)} subscription(s):") + for sub in subscriptions: + sub_id = sub.get("subscriptionId", "N/A") + display_name = sub.get("displayName", "N/A") + state = sub.get("state", "N/A") + print(f" - {display_name}") + print(f" ID: {sub_id}") + print(f" State: {state}") + else: + print("No subscriptions found or empty response.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_list_subscriptions_with_details(): + """Example 2: List subscriptions with full details.""" + print("\n=== Example 2: List Subscriptions with Details ===") + + async with DefaultAzureCredential() as credential: + + async with ArmClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + subscriptions = [ + item async for item in client.list_subscriptions() + ] + + if subscriptions: + print(f"Retrieved {len(subscriptions)} subscription(s) with details:\n") + + for i, sub in enumerate(subscriptions, 1): + print(f"Subscription {i}:") + print(f" Display Name: {sub.get('displayName', 'N/A')}") + print(f" Subscription ID: {sub.get('subscriptionId', 'N/A')}") + print(f" Tenant ID: {sub.get('tenantId', 'N/A')}") + print(f" State: {sub.get('state', 'N/A')}") + print(f" Full ID: {sub.get('id', 'N/A')}") + + # Check for subscription policies + policies = sub.get("subscriptionPolicies", {}) + if policies: + print(" Policies:") + print(f" Quota ID: {policies.get('quotaId', 'N/A')}") + print(f" Spending Limit: {policies.get('spendingLimit', 'N/A')}") + + auth_source = sub.get("authorizationSource", "N/A") + print(f" Authorization Source: {auth_source}") + print() + + else: + print("No subscriptions found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_filter_enabled_subscriptions(): + """Example 3: List only enabled subscriptions.""" + print("\n=== Example 3: Filter Enabled Subscriptions ===") + + async with DefaultAzureCredential() as credential: + + async with ArmClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + subscriptions = [ + item async for item in client.list_subscriptions() + ] + + if subscriptions: + enabled_subs = [ + sub for sub in subscriptions + if sub.get("state", "").lower() == "enabled" + ] + + print(f"Found {len(enabled_subs)} enabled subscription(s) " + f"out of {len(subscriptions)} total:\n") + + for sub in enabled_subs: + print(f" - {sub.get('displayName', 'N/A')}") + print(f" ID: {sub.get('subscriptionId', 'N/A')}") + + # Show disabled/warned subscriptions if any + other_subs = [ + sub for sub in subscriptions + if sub.get("state", "").lower() != "enabled" + ] + if other_subs: + print(f"\nSubscriptions with other states ({len(other_subs)}):") + for sub in other_subs: + print(f" - {sub.get('displayName', 'N/A')} " + f"({sub.get('state', 'N/A')})") + else: + print("No subscriptions found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + print("Azure Resource Manager (ARM) sample usage for the Azure Connectors Python SDK") + print("=" * 60) + + if not CONNECTION_RUNTIME_URL: + print("\nWARNING: ARM_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL to run actual API calls.") + print("Format: https://[region].azure-apihub.net/apim/arm/[connection-id]") + return + + await example_1_list_subscriptions() + await example_2_list_subscriptions_with_details() + await example_3_filter_enabled_subscriptions() + + print("\n" + "=" * 60) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_azuread.py b/samples/sample_connector_usage/aio/sample_connector_usage_azuread.py new file mode 100644 index 0000000..1c0e959 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_azuread.py @@ -0,0 +1,267 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure AD (Microsoft Entra ID) sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure AD client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Azure AD connection +2. Azure AD connection in Connector Namespaces (with OAuth consent) +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:AZUREAD_CONNECTION_URL = "https://[region].azure-apihub.net/apim/azuread/[connection-id]" + + python sample_connector_usage_azuread.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.azuread import AzureadClient +from azure.connectors.azuread import ( + CreateOffice365GroupInput, + CreateSecurityGroupInput, + CreateGroupInput, + CreateUserRequest, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/azuread/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "AZUREAD_CONNECTION_URL", + "" +) + + +async def example_1_create_office365_group(): + """Example 1: Create an Office 365 group.""" + print("\n=== Example 1: Create Office 365 Group ===") + + group_name = os.environ.get("TEST_O365_GROUP_NAME", "") + if not group_name: + print("Set TEST_O365_GROUP_NAME environment variable to create a group.") + print("Example: $env:TEST_O365_GROUP_NAME = 'SDK Test Group'") + return + + async with DefaultAzureCredential() as credential: + + async with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + input_data = CreateOffice365GroupInput( + display_name=group_name, + description="Created via Azure Connectors SDK for Python", + mail_nickname=group_name.replace(" ", "-").lower(), + group_types=["Unified"], + security_enabled=False, + mail_enabled=True, + ) + + result = await client.create_office365_group(input=input_data) + + if result: + print("Office 365 group created:") + print(f" ID: {result.get('id', 'N/A')}") + print(f" Display Name: {result.get('displayName', 'N/A')}") + print(f" Mail: {result.get('mail', 'N/A')}") + print(f" Created: {result.get('createdDateTime', 'N/A')}") + else: + print("Group created (no response returned).") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_create_security_group(): + """Example 2: Create a security group.""" + print("\n=== Example 2: Create Security Group ===") + + group_name = os.environ.get("TEST_SECURITY_GROUP_NAME", "") + if not group_name: + print("Set TEST_SECURITY_GROUP_NAME environment variable to create a group.") + print("Example: $env:TEST_SECURITY_GROUP_NAME = 'SDK Security Group'") + return + + async with DefaultAzureCredential() as credential: + + async with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + input_data = CreateSecurityGroupInput( + display_name=group_name, + description="Security group created via Azure Connectors SDK", + mail_nickname=group_name.replace(" ", "-").lower(), + security_enabled=True, + mail_enabled=False, + ) + + result = await client.create_security_group(input=input_data) + + if result: + print("Security group created:") + print(f" ID: {result.get('id', 'N/A')}") + print(f" Display Name: {result.get('displayName', 'N/A')}") + print(f" Security Enabled: {result.get('securityEnabled', 'N/A')}") + else: + print("Security group created (no response returned).") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_create_group(): + """Example 3: Create a generic group.""" + print("\n=== Example 3: Create Group ===") + + group_name = os.environ.get("TEST_GROUP_NAME", "") + if not group_name: + print("Set TEST_GROUP_NAME environment variable to create a group.") + print("Example: $env:TEST_GROUP_NAME = 'SDK Generic Group'") + return + + # Group type: 'Unified' for O365, empty list for security group + group_type = os.environ.get("TEST_GROUP_TYPE", "Unified") + group_types = [group_type] if group_type else [] + + async with DefaultAzureCredential() as credential: + + async with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + input_data = CreateGroupInput( + display_name=group_name, + description="Group created via Azure Connectors SDK", + mail_nickname=group_name.replace(" ", "-").lower(), + group_types=group_types, + security_enabled=not bool(group_types), + mail_enabled=bool(group_types), + ) + + result = await client.create_group(input=input_data) + + if result: + print("Group created:") + print(f" ID: {result.get('id', 'N/A')}") + print(f" Display Name: {result.get('displayName', 'N/A')}") + print(f" Group Types: {result.get('groupTypes', [])}") + print(f" Mail Enabled: {result.get('mailEnabled', 'N/A')}") + print(f" Security Enabled: {result.get('securityEnabled', 'N/A')}") + else: + print("Group created (no response returned).") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_create_user(): + """Example 4: Create a new user.""" + print("\n=== Example 4: Create User ===") + + user_principal_name = os.environ.get("TEST_USER_UPN", "") + display_name = os.environ.get("TEST_USER_DISPLAY_NAME", "") + temp_password = os.environ.get("TEST_USER_PASSWORD", "") + + if not user_principal_name or not display_name: + print("Set environment variables to create a user:") + print(" $env:TEST_USER_UPN = 'newuser@yourdomain.onmicrosoft.com'") + print(" $env:TEST_USER_DISPLAY_NAME = 'New User'") + print(" $env:TEST_USER_PASSWORD = 'TempPassword123!'") + return + + async with DefaultAzureCredential() as credential: + + async with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + input_data = CreateUserRequest( + account_enabled=True, + display_name=display_name, + mail_nickname=user_principal_name.split("@")[0], + user_principal_name=user_principal_name, + password_profile={ + "password": temp_password or "TempPassword123!", + "forceChangePasswordNextSignIn": True, + }, + ) + + result = await client.create_user(input=input_data) + + if result: + print("User created:") + print(f" ID: {result.get('id', 'N/A')}") + print(f" Display Name: {result.get('displayName', 'N/A')}") + print(f" UPN: {result.get('userPrincipalName', 'N/A')}") + print(f" Mail: {result.get('mail', 'N/A')}") + else: + print("User created (no response returned).") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_remove_member_from_group(): + """Example 5: Remove a member from a group.""" + print("\n=== Example 5: Remove Member From Group ===") + + group_id = os.environ.get("TEST_GROUP_ID", "") + member_id = os.environ.get("TEST_MEMBER_ID", "") + + if not group_id or not member_id: + print("Set environment variables to remove a member:") + print(" $env:TEST_GROUP_ID = ''") + print(" $env:TEST_MEMBER_ID = ''") + return + + async with DefaultAzureCredential() as credential: + + async with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + await client.remove_member_from_group( + group_id=group_id, + member_id=member_id, + ) + + print("Member removed from group:") + print(f" Group ID: {group_id}") + print(f" Member ID: {member_id}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + print("Azure AD (Microsoft Entra ID) sample usage for the Azure Connectors Python SDK") + print("=" * 60) + + if not CONNECTION_RUNTIME_URL: + print("\nWARNING: AZUREAD_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL to run actual API calls.") + print("Format: https://[region].azure-apihub.net/apim/azuread/[connection-id]") + return + + await example_1_create_office365_group() + await example_2_create_security_group() + await example_3_create_group() + await example_4_create_user() + await example_5_remove_member_from_group() + + print("\n" + "=" * 60) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_azureautomation.py b/samples/sample_connector_usage/aio/sample_connector_usage_azureautomation.py new file mode 100644 index 0000000..a469627 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_azureautomation.py @@ -0,0 +1,284 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure Automation sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure Automation client from the Azure Connectors Python SDK +to interact with Azure Automation accounts, runbooks, and jobs. + +Prerequisites: +1. Azure subscription with Azure Automation connection +2. Azure Automation connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:AZUREAUTOMATION_CONNECTION_URL = "https://....azure-apihub.net/apim/..." + $env:AZUREAUTOMATION_SUBSCRIPTION_ID = "00000000-0000-0000-0000-000000000000" + $env:AZUREAUTOMATION_RESOURCE_GROUP = "my-resource-group" + $env:AZUREAUTOMATION_ACCOUNT = "my-automation-account" + $env:AZUREAUTOMATION_JOB_ID = "00000000-0000-0000-0000-000000000000" # for status/output + + python sample_connector_usage_azureautomation.py + +Available operations: +- Create automation jobs +- Get job status +- Get job output +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.azureautomation import AzureautomationClient +from azure.connectors.azureautomation import ( + CreateJobInput, + CreateJobResponse, + Subscription, + ResourceGroup, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/azureautomation/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "AZUREAUTOMATION_CONNECTION_URL", + "" +) + +# Required parameters for Azure Automation operations +SUBSCRIPTION_ID = os.environ.get( + "AZUREAUTOMATION_SUBSCRIPTION_ID", + "" +) +RESOURCE_GROUP_NAME = os.environ.get( + "AZUREAUTOMATION_RESOURCE_GROUP", + "" +) +AUTOMATION_ACCOUNT = os.environ.get( + "AZUREAUTOMATION_ACCOUNT", + "" +) +JOB_ID = os.environ.get( + "AZUREAUTOMATION_JOB_ID", + "" +) + + +async def example_1_client_initialization(): + """Example 1: Initialize and verify the client.""" + print("\n=== Example 1: Client Initialization ===") + + async with DefaultAzureCredential() as credential: + + async with AzureautomationClient( + CONNECTION_RUNTIME_URL, credential + ) as client: + try: + print("Client initialized successfully") + print(f"Connector name: {client.connector_name}") + print("Client is ready for Azure Automation operations") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_create_job(): + """Example 2: Create an automation job.""" + print("\n=== Example 2: Create Automation Job ===") + + async with DefaultAzureCredential() as credential: + + async with AzureautomationClient( + CONNECTION_RUNTIME_URL, credential + ) as client: + try: + # Create a new automation job + result = await client.create_job( + input=CreateJobInput(properties={}), + subscription_id=SUBSCRIPTION_ID, + resource_group_name=RESOURCE_GROUP_NAME, + automation_account=AUTOMATION_ACCOUNT, + ) + + if result: + print(f"Job created: {result.get('id', 'N/A')}") + props = result.get("properties", {}) + print(f"Status: {props.get('status', 'Unknown')}") + else: + print("Job created (no response body)") + + except ConnectorException as ex: + print(f"Connector error: {ex.status_code} - {ex.response_body}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_create_job_and_wait(): + """Example 3: Create a job and wait for completion.""" + print("\n=== Example 3: Create Job and Wait ===") + + async with DefaultAzureCredential() as credential: + + async with AzureautomationClient( + CONNECTION_RUNTIME_URL, credential + ) as client: + try: + # Create job with wait parameter to wait for completion + result = await client.create_job( + input=CreateJobInput(properties={}), + subscription_id=SUBSCRIPTION_ID, + resource_group_name=RESOURCE_GROUP_NAME, + automation_account=AUTOMATION_ACCOUNT, + wait=True, + ) + + if result: + props = result.get("properties", {}) + print(f"Job completed with status: {props.get('status')}") + else: + print("Job completed (no response body)") + + except ConnectorException as ex: + print(f"Connector error: {ex.status_code}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_get_job_status(): + """Example 4: Get the status of a job.""" + print("\n=== Example 4: Get Job Status ===") + + async with DefaultAzureCredential() as credential: + + async with AzureautomationClient( + CONNECTION_RUNTIME_URL, credential + ) as client: + try: + # Get status of a job + result = await client.get_status_of_job( + subscription_id=SUBSCRIPTION_ID, + resource_group_name=RESOURCE_GROUP_NAME, + automation_account=AUTOMATION_ACCOUNT, + job_id=JOB_ID + ) + + if result: + print(f"Job ID: {result.get('id', 'N/A')}") + props = result.get("properties", {}) + print(f"Status: {props.get('status', 'Unknown')}") + print(f"Start time: {props.get('startTime', 'N/A')}") + print(f"End time: {props.get('endTime', 'N/A')}") + else: + print("No job status returned") + + except ConnectorException as ex: + print(f"Connector error: {ex.status_code}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_get_job_output(): + """Example 5: Get the output of a job.""" + print("\n=== Example 5: Get Job Output ===") + + async with DefaultAzureCredential() as credential: + + async with AzureautomationClient( + CONNECTION_RUNTIME_URL, credential + ) as client: + try: + # Get output from a completed job + output = await client.get_job_output( + subscription_id=SUBSCRIPTION_ID, + resource_group_name=RESOURCE_GROUP_NAME, + automation_account=AUTOMATION_ACCOUNT, + job_id=JOB_ID + ) + + if output: + # Output is returned as bytes + print("Job output:") + if isinstance(output, bytes): + print(output.decode("utf-8")) + else: + print(output) + else: + print("No output returned") + + except ConnectorException as ex: + print(f"Connector error: {ex.status_code}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_6_dataclass_usage(): + """Example 6: Working with Azure Automation data types.""" + print("\n=== Example 6: Data Types ===") + + # CreateJobResponse - represents an automation job + job = CreateJobResponse( + id="/subscriptions/xxx/resourceGroups/rg/providers/" + "Microsoft.Automation/automationAccounts/account/jobs/job123", + properties={ + "status": "Running", + "runbook": {"name": "MyRunbook"}, + "startTime": "2024-01-15T10:00:00Z" + } + ) + print(f"Job ID: {job.id}") + print(f"Job Status: {job.properties.get('status')}") + + # Subscription - Azure subscription info + subscription = Subscription( + subscription_id="00000000-0000-0000-0000-000000000000", + display_name="Production Subscription", + state="Enabled" + ) + print(f"Subscription: {subscription.display_name}") + + # ResourceGroup - for targeting automation accounts + rg = ResourceGroup( + id="/subscriptions/xxx/resourceGroups/automation-rg", + name="automation-rg" + ) + print(f"Resource Group: {rg.name}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: AZUREAUTOMATION_CONNECTION_URL environment variable " + "not set.") + print("Set it to your connection runtime URL from Azure Portal.") + print("\nRunning data type examples without connection...\n") + await example_6_dataclass_usage() + return + + if not all([SUBSCRIPTION_ID, RESOURCE_GROUP_NAME, AUTOMATION_ACCOUNT]): + print("Error: Missing required environment variables.") + print("Required: AZUREAUTOMATION_SUBSCRIPTION_ID, " + "AZUREAUTOMATION_RESOURCE_GROUP, AZUREAUTOMATION_ACCOUNT") + print("\nRunning data type examples without connection...\n") + await example_6_dataclass_usage() + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_client_initialization() + await example_2_create_job() + await example_3_create_job_and_wait() + await example_4_get_job_status() + await example_5_get_job_output() + await example_6_dataclass_usage() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_azureblob.py b/samples/sample_connector_usage/aio/sample_connector_usage_azureblob.py new file mode 100644 index 0000000..911d18b --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_azureblob.py @@ -0,0 +1,270 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure Blob Storage sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure Blob Storage client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Azure Blob Storage connection +2. Azure Blob Storage connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Note: Azure Blob Storage uses key-based auth (accountName + accessKey), not OAuth. +The connection must be created with parameterValues in a single PUT — no consent link flow. + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:AZUREBLOB_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/azureblob/[connection-id]" + ) + $env:TEST_STORAGE_ACCOUNT = "mystorageaccount" + + python sample_connector_usage_azureblob.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.azureblob import AzureblobClient + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/azureblob/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "AZUREBLOB_CONNECTION_URL", + "" +) + +# Storage account name (dataset parameter in API calls) +STORAGE_ACCOUNT = os.environ.get( + "TEST_STORAGE_ACCOUNT", + "" +) + + +async def example_1_get_blob_metadata(): + """Example 1: Get blob metadata by path.""" + print("\n=== Example 1: Get Blob Metadata ===") + + blob_path = os.environ.get("TEST_BLOB_PATH", "") + if not blob_path: + print("Set TEST_BLOB_PATH environment variable to a blob path.") + print("Example: $env:TEST_BLOB_PATH = 'container/folder/file.txt'") + return + + async with DefaultAzureCredential() as credential: + + async with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: + + metadata = await client.get_file_metadata_by_path( + dataset=STORAGE_ACCOUNT, + path=blob_path, + ) + + if metadata: + print(f"Blob Metadata for '{blob_path}':") + print(f" Name: {metadata.get('Name', 'N/A')}") + print(f" Path: {metadata.get('Path', 'N/A')}") + print(f" Size: {metadata.get('Size', 'N/A')} bytes") + print(f" Last Modified: {metadata.get('LastModified', 'N/A')}") + print(f" Media Type: {metadata.get('MediaType', 'N/A')}") + print(f" ETag: {metadata.get('ETag', 'N/A')}") + else: + print(f"No metadata returned for: {blob_path}") + + +async def example_2_download_blob(): + """Example 2: Download blob content.""" + print("\n=== Example 2: Download Blob Content ===") + + blob_path = os.environ.get("TEST_BLOB_PATH", "") + if not blob_path: + print("Set TEST_BLOB_PATH environment variable to a blob path.") + print("Example: $env:TEST_BLOB_PATH = 'container/folder/file.txt'") + return + + async with DefaultAzureCredential() as credential: + + async with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: + content = await client.get_file_content_by_path( + dataset=STORAGE_ACCOUNT, + path=blob_path, + ) + + if content: + file_name = os.path.basename(blob_path) + print(f"Downloaded blob '{file_name}': {len(content)} bytes") + + # Show preview for text files + if len(content) < 1000: + try: + text_preview = content.decode("utf-8")[:200] + print(f" Preview: {text_preview}...") + except UnicodeDecodeError: + print(" (Binary content)") + else: + print(f"No content returned for: {blob_path}") + + +async def example_3_upload_blob(): + """Example 3: Upload a blob.""" + print("\n=== Example 3: Upload Blob ===") + + folder_path = os.environ.get("TEST_FOLDER_PATH", "") + if not folder_path: + print("Set TEST_FOLDER_PATH environment variable to a container/folder path.") + print("Example: $env:TEST_FOLDER_PATH = 'mycontainer/uploads'") + return + + blob_name = "sample-upload.txt" + blob_content = "Hello from Azure Connectors SDK for Python!\nUploaded at: " + \ + asyncio.get_event_loop().time().__str__() + + async with DefaultAzureCredential() as credential: + + async with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + metadata = await client.create_file( + input=blob_content.encode("utf-8"), + dataset=STORAGE_ACCOUNT, + folder_path=folder_path, + name=blob_name, + ) + + if metadata: + print(f"Uploaded blob '{blob_name}' to '{folder_path}':") + print(f" ID: {metadata.get('Id', 'N/A')}") + print(f" Path: {metadata.get('Path', 'N/A')}") + print(f" Size: {len(blob_content)} bytes") + else: + print("Blob uploaded (no metadata returned).") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_list_blobs(): + """Example 4: List blobs in a container/folder.""" + print("\n=== Example 4: List Blobs ===") + + folder_id = os.environ.get("TEST_FOLDER_ID", "") + if not folder_id: + print("Set TEST_FOLDER_ID environment variable to a folder identifier.") + print("Example: $env:TEST_FOLDER_ID = 'JTJmbXljb250YWluZXI=' (base64 encoded path)") + print("Or use list_root_folder to list root container blobs.") + + # Try listing root folder instead + print("\nListing root folder blobs instead...") + async with DefaultAzureCredential() as credential: + + async with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + blobs = [item async for item in client.list_root_folder( + dataset=STORAGE_ACCOUNT, + )] + + if blobs: + print(f"Found {len(blobs)} items in root:") + for blob in blobs[:10]: # Show first 10 + name = blob.get("Name", "N/A") + is_folder = blob.get("IsFolder", False) + size = blob.get("Size", 0) + item_type = "folder" if is_folder else f"{size} bytes" + print(f" - {name} ({item_type})") + else: + print("No blobs found in root folder.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + return + + async with DefaultAzureCredential() as credential: + + async with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + blobs = [item async for item in client.list_folder( + dataset=STORAGE_ACCOUNT, + id=folder_id, + )] + + if blobs: + print(f"Found {len(blobs)} items:") + for blob in blobs[:10]: # Show first 10 + name = blob.get("Name", "N/A") + is_folder = blob.get("IsFolder", False) + size = blob.get("Size", 0) + item_type = "folder" if is_folder else f"{size} bytes" + print(f" - {name} ({item_type})") + else: + print("No blobs found in folder.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_delete_blob(): + """Example 5: Delete a blob.""" + print("\n=== Example 5: Delete Blob ===") + + blob_id = os.environ.get("TEST_BLOB_ID", "") + if not blob_id: + print("Set TEST_BLOB_ID environment variable to a blob identifier.") + print("Example: $env:TEST_BLOB_ID = 'JTJmbXljb250YWluZXIlMmZmaWxlLnR4dA=='") + print("You can get blob IDs from the list_folder response.") + return + + async with DefaultAzureCredential() as credential: + + async with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + await client.delete_file( + dataset=STORAGE_ACCOUNT, + id=blob_id, + ) + + print(f"Successfully deleted blob: {blob_id}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + print("Azure Blob Storage sample usage for the Azure Connectors Python SDK") + print("=" * 60) + + if not CONNECTION_RUNTIME_URL: + print("\nWARNING: AZUREBLOB_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL to run actual API calls.") + print("Format: https://[region].azure-apihub.net/apim/azureblob/[connection-id]") + return + + if not STORAGE_ACCOUNT: + print("\nWARNING: TEST_STORAGE_ACCOUNT environment variable not set.") + print("Set it to your storage account name.") + return + + await example_1_get_blob_metadata() + await example_2_download_blob() + await example_3_upload_blob() + await example_4_list_blobs() + await example_5_delete_blob() + + print("\n" + "=" * 60) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_azuredatafactory.py b/samples/sample_connector_usage/aio/sample_connector_usage_azuredatafactory.py new file mode 100644 index 0000000..1c9b03d --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_azuredatafactory.py @@ -0,0 +1,241 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure Data Factory sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure Data Factory client from the Azure Connectors Python SDK +to create, monitor, and cancel pipeline runs. + +Prerequisites: +1. Azure subscription with Azure Data Factory +2. Azure Data Factory connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:AZUREDATAFACTORY_CONNECTION_URL = "https://....azure-apihub.net/apim/..." + + python sample_connector_usage_azuredatafactory.py + +Available operations: +- Create pipeline runs +- Get pipeline run status +- Cancel pipeline runs +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.azuredatafactory import AzuredatafactoryClient +from azure.connectors.azuredatafactory import ( + ParameterValueSpecification, + CreatePipelineRunResponse, + PipelineRun, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/azuredatafactory/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "AZUREDATAFACTORY_CONNECTION_URL", + "" +) + +# Azure resource details - update these for your environment +SUBSCRIPTION_ID = os.environ.get("AZURE_SUBSCRIPTION_ID", "your-subscription-id") +RESOURCE_GROUP = os.environ.get("AZURE_RESOURCE_GROUP", "your-resource-group") +DATA_FACTORY_NAME = os.environ.get("ADF_NAME", "your-data-factory") +PIPELINE_NAME = os.environ.get("ADF_PIPELINE_NAME", "your-pipeline") + + +async def example_1_create_pipeline_run(): + """Example 1: Create a new pipeline run.""" + print("\n=== Example 1: Create Pipeline Run ===") + + async with DefaultAzureCredential() as credential: + + async with AzuredatafactoryClient( + CONNECTION_RUNTIME_URL, credential + ) as client: + try: + # Create parameters for the pipeline run + parameters = ParameterValueSpecification( + additional_properties={ + # Add your pipeline parameters here + # "inputPath": "/data/input", + # "outputPath": "/data/output", + } + ) + + # Create the pipeline run + result = await client.create_pipeline_run( + input=parameters, + subscription_id=SUBSCRIPTION_ID, + resource_group_name=RESOURCE_GROUP, + data_factory_name=DATA_FACTORY_NAME, + pipeline_name=PIPELINE_NAME, + ) + + if result: + run_id = result.get("runId", "Unknown") + print("Pipeline run created successfully!") + print(f"Run ID: {run_id}") + return run_id + else: + print("Pipeline run created (no response body)") + return None + + except ConnectorException as ex: + print(f"Connector error: {ex.status_code} - {ex.response_body}") + return None + except Exception as ex: + print(f"Error: {ex}") + return None + + +async def example_2_get_pipeline_run_status(run_id: str): + """Example 2: Get the status of a pipeline run.""" + print("\n=== Example 2: Get Pipeline Run Status ===") + + if not run_id: + print("No run ID provided, skipping...") + return + + async with DefaultAzureCredential() as credential: + + async with AzuredatafactoryClient( + CONNECTION_RUNTIME_URL, credential + ) as client: + try: + # Get the pipeline run status + result = await client.get_pipeline_run( + subscription_id=SUBSCRIPTION_ID, + resource_group_name=RESOURCE_GROUP, + data_factory_name=DATA_FACTORY_NAME, + pipeline_run_name=run_id, + ) + + if result: + print(f"Pipeline: {result.get('pipelineName', 'N/A')}") + print(f"Run ID: {result.get('runId', 'N/A')}") + print(f"Status: {result.get('status', 'Unknown')}") + print(f"Start Time: {result.get('runStart', 'N/A')}") + print(f"End Time: {result.get('runEnd', 'N/A')}") + duration = result.get('durationInMs') + if duration: + print(f"Duration: {duration}ms ({duration / 1000:.2f}s)") + message = result.get('message') + if message: + print(f"Message: {message}") + else: + print("No run status returned") + + except ConnectorException as ex: + print(f"Connector error: {ex.status_code}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_cancel_pipeline_run(run_id: str): + """Example 3: Cancel a running pipeline.""" + print("\n=== Example 3: Cancel Pipeline Run ===") + + if not run_id: + print("No run ID provided, skipping...") + return + + async with DefaultAzureCredential() as credential: + + async with AzuredatafactoryClient( + CONNECTION_RUNTIME_URL, credential + ) as client: + try: + # Cancel the pipeline run + await client.cancel_pipeline_run( + subscription_id=SUBSCRIPTION_ID, + resource_group_name=RESOURCE_GROUP, + data_factory_name=DATA_FACTORY_NAME, + pipeline_run_name=run_id, + ) + + print(f"Pipeline run {run_id} cancellation requested") + + except ConnectorException as ex: + print(f"Connector error: {ex.status_code}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_dataclass_usage(): + """Example 4: Working with Azure Data Factory data types.""" + print("\n=== Example 4: Data Types ===") + + # CreatePipelineRunResponse - represents a created pipeline run + run_response = CreatePipelineRunResponse( + run_id="12345678-1234-1234-1234-123456789012" + ) + print(f"Run Response ID: {run_response.run_id}") + + # PipelineRun - represents pipeline run details + run = PipelineRun( + run_id="12345678-1234-1234-1234-123456789012", + pipeline_name="CopyDataPipeline", + status="Succeeded", + duration_in_ms=45000, + parameters={"inputPath": "/data/input", "outputPath": "/data/output"}, + run_start="2024-01-15T10:00:00Z", + run_end="2024-01-15T10:00:45Z" + ) + print(f"Pipeline: {run.pipeline_name}") + print(f"Status: {run.status}") + print(f"Duration: {run.duration_in_ms}ms") + + # ParameterValueSpecification - for passing pipeline parameters + params = ParameterValueSpecification( + additional_properties={ + "sourceContainer": "raw-data", + "targetContainer": "processed-data", + "filePattern": "*.csv" + } + ) + print(f"Parameters: {params.additional_properties}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: AZUREDATAFACTORY_CONNECTION_URL environment variable " + "not set.") + print("Set it to your connection runtime URL from Azure Portal.") + print("\nRunning data type examples without connection...\n") + await example_4_dataclass_usage() + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + print(f"Subscription: {SUBSCRIPTION_ID}") + print(f"Resource Group: {RESOURCE_GROUP}") + print(f"Data Factory: {DATA_FACTORY_NAME}") + print(f"Pipeline: {PIPELINE_NAME}") + + # Create a pipeline run + run_id = await example_1_create_pipeline_run() + + # Get the status of the run + if run_id: + await example_2_get_pipeline_run_status(run_id) + + # Uncomment to cancel the run (be careful with this!) + # if run_id: + # await example_3_cancel_pipeline_run(run_id) + + # Show data type usage + await example_4_dataclass_usage() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_azuredigitaltwins.py b/samples/sample_connector_usage/aio/sample_connector_usage_azuredigitaltwins.py new file mode 100644 index 0000000..8b977f8 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_azuredigitaltwins.py @@ -0,0 +1,266 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure Digital Twins sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure Digital Twins client from the Azure Connectors Python SDK +to manage digital twins, models, relationships, and queries. + +Prerequisites: +1. Azure subscription with Azure Digital Twins instance +2. Azure Digital Twins connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:AZUREDIGITALTWINS_CONNECTION_URL = "https://....azure-apihub.net/apim/..." + + python sample_connector_usage_azuredigitaltwins.py + +Available operations: +- Model management (list, get, delete) +- Twin management (create, get, update, delete) +- Relationship management +- Query twins +- Send telemetry +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.azuredigitaltwins import AzuredigitaltwinsClient +from azure.connectors.azuredigitaltwins import ( + QueryTwinsInput, + SendTelemetryInput, + TwinRelationship, + IncomingRelationship, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/azuredigitaltwins/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "AZUREDIGITALTWINS_CONNECTION_URL", + "" +) + + +async def example_1_list_models(): + """Example 1: List all models in the instance.""" + print("\n=== Example 1: List Models ===") + + async with DefaultAzureCredential() as credential: + + async with AzuredigitaltwinsClient( + CONNECTION_RUNTIME_URL, credential + ) as client: + try: + # List all models + models = [item async for item in client.list_models( + include_model_definition="true" + )] + + if models: + print(f"Found {len(models)} models:") + for model in models: + print(f" - {model.get('id', 'Unknown')}") + else: + print("No models found") + + except ConnectorException as ex: + print(f"Connector error: {ex.status_code} - {ex.response_body}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_get_twin(): + """Example 2: Get a specific digital twin.""" + print("\n=== Example 2: Get Twin ===") + + async with DefaultAzureCredential() as credential: + twin_id = "room1" # Replace with your twin ID + + async with AzuredigitaltwinsClient( + CONNECTION_RUNTIME_URL, credential + ) as client: + try: + # Get a twin by ID + result = await client.get_twin_by_id(twinid=twin_id) + + if result: + print(f"Twin ID: {result.get('$dtId', 'Unknown')}") + metadata = result.get("$metadata", {}) + print(f"Model: {metadata.get('$model', 'Unknown')}") + + # Print properties + for key, value in result.items(): + if not key.startswith("$"): + print(f" {key}: {value}") + else: + print(f"Twin '{twin_id}' not found") + + except ConnectorException as ex: + print(f"Connector error: {ex.status_code}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_query_twins(): + """Example 3: Query digital twins.""" + print("\n=== Example 3: Query Twins ===") + + async with DefaultAzureCredential() as credential: + + async with AzuredigitaltwinsClient( + CONNECTION_RUNTIME_URL, credential + ) as client: + try: + # Query all twins + query_input = QueryTwinsInput( + query="SELECT * FROM digitaltwins" + ) + result = await client.query_twins(input=query_input) + + if result and result.get("value"): + print(f"Query results: {result['value']}") + else: + print("No twins found matching query") + + # Check for continuation token for pagination + if result and result.get("continuation_token"): + print("More results available (use continuation_token)") + + except ConnectorException as ex: + print(f"Connector error: {ex.status_code}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_list_relationships(): + """Example 4: List relationships for a twin.""" + print("\n=== Example 4: List Relationships ===") + + async with DefaultAzureCredential() as credential: + twin_id = "room1" # Replace with your twin ID + + async with AzuredigitaltwinsClient( + CONNECTION_RUNTIME_URL, credential + ) as client: + try: + # List outgoing relationships + outgoing = [item async for item in client.list_relationships(twinid=twin_id)] + + if outgoing: + print(f"Outgoing relationships from {twin_id}:") + for rel in outgoing: + print(f" -> {rel.get('$targetId')} " + f"({rel.get('$relationshipName')})") + else: + print(f"No outgoing relationships from {twin_id}") + + # List incoming relationships + incoming = [item async for item in client.list_incoming_relationships( + twinid=twin_id + )] + + if incoming: + print(f"Incoming relationships to {twin_id}:") + for rel in incoming: + print(f" <- {rel.get('$sourceId')} " + f"({rel.get('$relationshipName')})") + else: + print(f"No incoming relationships to {twin_id}") + + except ConnectorException as ex: + print(f"Connector error: {ex.status_code}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_send_telemetry(): + """Example 5: Send telemetry from a twin.""" + print("\n=== Example 5: Send Telemetry ===") + + async with DefaultAzureCredential() as credential: + twin_id = "room1" # Replace with your twin ID + + async with AzuredigitaltwinsClient( + CONNECTION_RUNTIME_URL, credential + ) as client: + try: + # Send telemetry + telemetry = SendTelemetryInput( + value='{"temperature": 72.5, "humidity": 45}' + ) + await client.send_telemetry( + input=telemetry, + twinid=twin_id + ) + + print(f"Telemetry sent for twin '{twin_id}'") + + except ConnectorException as ex: + print(f"Connector error: {ex.status_code}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_6_dataclass_usage(): + """Example 6: Working with Azure Digital Twins data types.""" + print("\n=== Example 6: Data Types ===") + + # TwinRelationship - represents a relationship between twins + relationship = TwinRelationship( + source_id="room1", + relationship_id="rel-001", + target_id="floor1", + relationship_name="isPartOf", + etag="abc123" + ) + print(f"Relationship: {relationship.source_id} -> {relationship.target_id}") + print(f"Type: {relationship.relationship_name}") + + # IncomingRelationship - represents an incoming relationship + incoming = IncomingRelationship( + source_id="building1", + relationship_id="rel-002", + relationship_name="contains" + ) + print(f"Incoming: {incoming.source_id} ({incoming.relationship_name})") + + # QueryTwinsInput - for querying twins + query = QueryTwinsInput( + query="SELECT * FROM digitaltwins WHERE temperature > 70", + continuation_token=None + ) + print(f"Query: {query.query}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: AZUREDIGITALTWINS_CONNECTION_URL environment variable " + "not set.") + print("Set it to your connection runtime URL from Azure Portal.") + print("\nRunning data type examples without connection...\n") + await example_6_dataclass_usage() + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_list_models() + await example_2_get_twin() + await example_3_query_twins() + await example_4_list_relationships() + # Uncomment to send telemetry (requires existing twin) + # await example_5_send_telemetry() + await example_6_dataclass_usage() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_azureeventgrid.py b/samples/sample_connector_usage/aio/sample_connector_usage_azureeventgrid.py new file mode 100644 index 0000000..b51720d --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_azureeventgrid.py @@ -0,0 +1,114 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure Event Grid sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure Event Grid client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with an Azure Event Grid connection +2. Azure Event Grid connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:AZUREEVENTGRID_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/azureeventgrid/[connection-id]" + ) + + python sample_connector_usage_azureeventgrid.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential +from azure.connectors.aio.azureeventgrid import AzureeventgridClient +from azure.connectors.azureeventgrid import ( + EventRequest, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/azureeventgrid/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "AZUREEVENTGRID_CONNECTION_URL", + "", +) + + +async def example_1_list_subscriptions(): + """Example 1: List Azure subscriptions available to the principal.""" + print("\n=== Example 1: List Subscriptions ===") + + async with DefaultAzureCredential() as credential: + + async with AzureeventgridClient(CONNECTION_RUNTIME_URL, credential) as client: + items = [item async for item in client.list_subscriptions()] + subscriptions = items + + print(f"Found {len(subscriptions)} subscription(s).") + for subscription in subscriptions[:10]: + display_name = subscription.get("displayName", "N/A") + subscription_id = subscription.get("subscriptionId", "N/A") + print(f" - {display_name} ({subscription_id})") + + +async def example_2_list_topic_types(): + """Example 2: List Event Grid topic types.""" + print("\n=== Example 2: List Topic Types ===") + + async with DefaultAzureCredential() as credential: + + async with AzureeventgridClient(CONNECTION_RUNTIME_URL, credential) as client: + items = [item async for item in client.list_topic_types()] + topic_types = items + + print(f"Found {len(topic_types)} topic type(s).") + for topic_type in topic_types[:10]: + print(f" - {topic_type.get('name', 'N/A')}") + + +async def example_3_build_event_request(): + """Example 3: Build an Event Grid request payload.""" + print("\n=== Example 3: Build Event Request ===") + + subscription_id = os.environ.get("AZUREEVENTGRID_SUBSCRIPTION_ID", "") + resource_type = os.environ.get("AZUREEVENTGRID_RESOURCE_TYPE", "") + + if not (subscription_id and resource_type): + print( + "Set AZUREEVENTGRID_SUBSCRIPTION_ID and AZUREEVENTGRID_RESOURCE_TYPE " + "to run this example." + ) + return + + request = EventRequest(properties={ + "subscriptionId": subscription_id, + "resourceType": resource_type, + "subscriptionName": "sdk-sample-subscription", + }) + print(f"Prepared Event Grid request properties: {request.properties}") + print("The generated client exposes discovery operations, not subscription creation.") + + +async def main(): + """Run all Azure Event Grid connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: AZUREEVENTGRID_CONNECTION_URL environment variable is not set.") + print("Set it to your Azure Event Grid connector runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_list_subscriptions() + await example_2_list_topic_types() + await example_3_build_event_request() + + print("\n=== Azure Event Grid sample completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_azureiotcentral.py b/samples/sample_connector_usage/aio/sample_connector_usage_azureiotcentral.py new file mode 100644 index 0000000..5eebdab --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_azureiotcentral.py @@ -0,0 +1,132 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure IoT Central sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure IoT Central client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with an Azure IoT Central connection +2. Azure IoT Central connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:AZUREIOTCENTRAL_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/azureiotcentral/[connection-id]" + ) + $env:AZUREIOTCENTRAL_APPLICATION = "[application-host-or-id]" + + python sample_connector_usage_azureiotcentral.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.azureiotcentral import AzureiotcentralClient +from azure.connectors.azureiotcentral import ( + DeviceGroup, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/azureiotcentral/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "AZUREIOTCENTRAL_CONNECTION_URL", + "", +) + +# The IoT Central application host or ID the operations target. +APPLICATION = os.environ.get("AZUREIOTCENTRAL_APPLICATION", "") + + +async def example_1_list_devices(): + """Example 1: List devices in the IoT Central application.""" + print("\n=== Example 1: List Devices ===") + + async with DefaultAzureCredential() as credential: + + async with AzureiotcentralClient(CONNECTION_RUNTIME_URL, credential) as client: + devices = [ + item async for item in client.list_devices( + application=APPLICATION + ) + ] + + print(f"Found {len(devices)} device(s).") + for device in devices[:10]: + display_name = device.get("displayName", "N/A") + device_id = device.get("id", "N/A") + print(f" - {display_name} ({device_id})") + + +async def example_2_list_device_groups(): + """Example 2: List device groups in the IoT Central application.""" + print("\n=== Example 2: List Device Groups ===") + + async with DefaultAzureCredential() as credential: + + async with AzureiotcentralClient(CONNECTION_RUNTIME_URL, credential) as client: + device_groups = [ + item async for item in client.list_device_groups( + application=APPLICATION + ) + ] + + print(f"Found {len(device_groups)} device group(s).") + for device_group in device_groups[:10]: + display_name = device_group.get("displayName", "N/A") + group_id = device_group.get("id", "N/A") + print(f" - {display_name} ({group_id})") + + +async def example_3_create_device_group(): + """Example 3: Create or update a device group.""" + print("\n=== Example 3: Create Device Group ===") + + device_group_id = os.environ.get("AZUREIOTCENTRAL_DEVICE_GROUP_ID", "") + + if not device_group_id: + print("Set AZUREIOTCENTRAL_DEVICE_GROUP_ID to run this example.") + return + + async with DefaultAzureCredential() as credential: + + async with AzureiotcentralClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.device_groups_set( + input=DeviceGroup( + display_name="SDK sample group", + filter="status = 'registered'", + ), + device_group_id=device_group_id, + application=APPLICATION, + ) + group_id = result.get("id", "N/A") if result else "N/A" + print(f"Device group upserted: {group_id}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def main(): + """Run all Azure IoT Central connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: AZUREIOTCENTRAL_CONNECTION_URL environment variable is not set.") + print("Set it to your Azure IoT Central connector runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_list_devices() + await example_2_list_device_groups() + await example_3_create_device_group() + + print("\n=== Azure IoT Central sample completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_azuremonitorlogs.py b/samples/sample_connector_usage/aio/sample_connector_usage_azuremonitorlogs.py new file mode 100644 index 0000000..2e4b2f0 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_azuremonitorlogs.py @@ -0,0 +1,183 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure Monitor Logs sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure Monitor Logs client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Azure Monitor Logs access +2. Azure Monitor Logs connection in Connector Namespace +3. Connection runtime URL from Azure Portal +4. A Log Analytics workspace or Application Insights resource + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:AZUREMONITORLOGS_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/azuremonitorlogs/[connection-id]" + ) + + python sample_connector_usage_azuremonitorlogs.py +""" + +import asyncio +import os + +try: + from azure.identity.aio import DefaultAzureCredential + from azure.connectors import ConnectorException + from azure.connectors.aio.azuremonitorlogs import AzuremonitorlogsClient + from azure.connectors.azuremonitorlogs import ( + QueryDataInput, + VisualizeQueryInput, + ) + IMPORTS_AVAILABLE = True +except ImportError as import_error: + IMPORTS_AVAILABLE = False + IMPORT_ERROR = str(import_error) + + +CONNECTION_RUNTIME_URL = os.environ.get( + "AZUREMONITORLOGS_CONNECTION_URL", + "", +) + +SUBSCRIPTION_ID = os.environ.get("AZUREMONITORLOGS_SUBSCRIPTION", "") +RESOURCE_GROUP = os.environ.get("AZUREMONITORLOGS_RESOURCE_GROUP", "") +RESOURCE_TYPE = os.environ.get( + "AZUREMONITORLOGS_RESOURCE_TYPE", + "Microsoft.OperationalInsights/workspaces", +) +RESOURCE_NAME = os.environ.get("AZUREMONITORLOGS_RESOURCE_NAME", "") + + +def _print_configuration_help(): + print("Missing required environment variables.") + print("Please set:") + print(" AZUREMONITORLOGS_CONNECTION_URL") + print(" AZUREMONITORLOGS_SUBSCRIPTION") + print(" AZUREMONITORLOGS_RESOURCE_GROUP") + print(" AZUREMONITORLOGS_RESOURCE_NAME") + + +async def example_list_discovery_values(): + """List subscriptions and resource groups using discovery APIs.""" + print("\n=== Example 1: Discovery Operations ===") + + async with DefaultAzureCredential() as credential: + + async with AzuremonitorlogsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + subscriptions = [item async for item in client.list_subscriptions()] + count = len(subscriptions) if subscriptions else 0 + print(f"Found {count} subscriptions.") + + resource_groups = [item async for item in client.list_resource_groups( + subscriptions=SUBSCRIPTION_ID + )] + rg_count = len(resource_groups) if resource_groups else 0 + print(f"Found {rg_count} resource groups in subscription.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_run_query(): + """Run a KQL query and list tabular rows.""" + print("\n=== Example 2: Run Query Data ===") + + async with DefaultAzureCredential() as credential: + + async with AzuremonitorlogsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + request = QueryDataInput( + query="Heartbeat | take 5", + timerangetype="SetInQuery", + timerange={}, + ) + + result = await client.query_data( + input=request, + subscriptions=SUBSCRIPTION_ID, + resourcegroups=RESOURCE_GROUP, + resourcetype=RESOURCE_TYPE, + resourcename=RESOURCE_NAME, + ) + + rows = result + print(f"Returned {len(rows)} rows.") + for index, row in enumerate(rows[:3], 1): + print(f" Row {index}: {row}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_visualize_query(): + """Run query visualization.""" + print("\n=== Example 3: Visualize Query ===") + + async with DefaultAzureCredential() as credential: + + async with AzuremonitorlogsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + request = VisualizeQueryInput( + query=( + "Heartbeat " + "| summarize Count=count() by bin(TimeGenerated, 1h) " + "| order by TimeGenerated asc" + ), + timerangetype="SetInQuery", + timerange={}, + ) + + result = await client.visualize_query( + input=request, + subscriptions=SUBSCRIPTION_ID, + resourcegroups=RESOURCE_GROUP, + resourcetype=RESOURCE_TYPE, + resourcename=RESOURCE_NAME, + vis_type="linechart", + ) + + if result: + print("Visualization payload returned.") + print(f"Keys: {list(result.keys())}") + else: + print("Visualization completed with empty response.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run Azure Monitor Logs connector samples.""" + if not IMPORTS_AVAILABLE: + print("Required imports are unavailable:") + print(f" {IMPORT_ERROR}") + return + + if not CONNECTION_RUNTIME_URL: + _print_configuration_help() + return + + if not SUBSCRIPTION_ID or not RESOURCE_GROUP or not RESOURCE_NAME: + _print_configuration_help() + return + + await example_list_discovery_values() + await example_run_query() + await example_visualize_query() + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_azurequeues.py b/samples/sample_connector_usage/aio/sample_connector_usage_azurequeues.py new file mode 100644 index 0000000..39f1b5f --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_azurequeues.py @@ -0,0 +1,242 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure Storage Queues sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure Storage Queues client from the Azure Connectors Python SDK +to interact with Azure Storage Queue messages. + +Prerequisites: +1. Azure subscription with Azure Storage Queues connection +2. Azure Queues connection in Connector Namespaces (with access configured) +3. Connection runtime URL from Azure Portal +4. Azure Storage Account with queue storage + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:AZUREQUEUES_CONNECTION_URL = "https://...apihub.net/apim/azurequeues/..." + $env:AZUREQUEUES_STORAGE_ACCOUNT = "" + $env:AZUREQUEUES_QUEUE_NAME = "" + + python sample_connector_usage_azurequeues.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.azurequeues import AzurequeuesClient + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/azurequeues/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "AZUREQUEUES_CONNECTION_URL", + "" +) + +# Storage account name or queue endpoint +STORAGE_ACCOUNT = os.environ.get("AZUREQUEUES_STORAGE_ACCOUNT", "") + +# Queue name for message operations +QUEUE_NAME = os.environ.get("AZUREQUEUES_QUEUE_NAME", "") + + +async def example_1_list_queues(): + """Example 1: List all queues in a storage account.""" + print("\n=== Example 1: List Queues ===") + + if not STORAGE_ACCOUNT: + print("Set AZUREQUEUES_STORAGE_ACCOUNT environment variable.") + print("Example: $env:AZUREQUEUES_STORAGE_ACCOUNT = 'mystorageaccount'") + return + + async with DefaultAzureCredential() as credential: + + async with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_queues( + storage_account_name=STORAGE_ACCOUNT + )] + + if items: + print(f"Queues in storage account '{STORAGE_ACCOUNT}':") + for queue in items: + if isinstance(queue, dict): + print(f" - {queue.get('name', queue)}") + else: + print(f" - {queue}") + else: + print("No queues found or empty response.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_create_queue(): + """Example 2: Create a new queue.""" + print("\n=== Example 2: Create Queue ===") + + new_queue_name = os.environ.get("AZUREQUEUES_NEW_QUEUE_NAME", "") + if not STORAGE_ACCOUNT or not new_queue_name: + print("Set environment variables to create a queue:") + print(" $env:AZUREQUEUES_STORAGE_ACCOUNT = ''") + print(" $env:AZUREQUEUES_NEW_QUEUE_NAME = 'my-new-queue'") + return + + async with DefaultAzureCredential() as credential: + + async with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.put_queue( + storage_account_name=STORAGE_ACCOUNT, + queue_name=new_queue_name + ) + + print(f"Queue '{new_queue_name}' created successfully.") + if result: + print(f"Response: {result}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_put_message(): + """Example 3: Put a message on a queue.""" + print("\n=== Example 3: Put Message ===") + + if not STORAGE_ACCOUNT or not QUEUE_NAME: + print("Set environment variables to put a message:") + print(" $env:AZUREQUEUES_STORAGE_ACCOUNT = ''") + print(" $env:AZUREQUEUES_QUEUE_NAME = ''") + return + + async with DefaultAzureCredential() as credential: + + async with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + message_input = "Hello from Azure Connectors SDK for Python!" + + await client.put_message( + input=message_input, + storage_account_name=STORAGE_ACCOUNT, + queue_name=QUEUE_NAME + ) + + print(f"Message sent to queue '{QUEUE_NAME}':") + print(f" Content: {message_input}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_get_messages(): + """Example 4: Get messages from a queue.""" + print("\n=== Example 4: Get Messages ===") + + if not STORAGE_ACCOUNT or not QUEUE_NAME: + print("Set environment variables to get messages:") + print(" $env:AZUREQUEUES_STORAGE_ACCOUNT = ''") + print(" $env:AZUREQUEUES_QUEUE_NAME = ''") + return + + async with DefaultAzureCredential() as credential: + + async with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.get_messages( + storage_account_name=STORAGE_ACCOUNT, + queue_name=QUEUE_NAME, + numofmessages="5", # Get up to 5 messages + visibilitytimeout="30" # Hide messages for 30 seconds + ) + + if result: + queue_messages_list = result.get("QueueMessagesList", {}) + messages = queue_messages_list.get("QueueMessage", []) + if isinstance(messages, list): + print(f"Retrieved {len(messages)} message(s) from '{QUEUE_NAME}':") + for i, msg in enumerate(messages, 1): + print(f" Message {i}:") + print(f" ID: {msg.get('MessageId', 'N/A')}") + print(f" Text: {msg.get('MessageText', 'N/A')[:50]}...") + print(f" Pop Receipt: {msg.get('PopReceipt', 'N/A')[:20]}...") + print(f" Dequeue Count: {msg.get('DequeueCount', 'N/A')}") + print(f" Next Visible: {msg.get('TimeNextVisible', 'N/A')}") + else: + print(f"Response: {result}") + else: + print("No messages found or queue is empty.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_delete_message(): + """Example 5: Delete a message from a queue.""" + print("\n=== Example 5: Delete Message ===") + + message_id = os.environ.get("AZUREQUEUES_MESSAGE_ID", "") + pop_receipt = os.environ.get("AZUREQUEUES_POP_RECEIPT", "") + + if not STORAGE_ACCOUNT or not QUEUE_NAME or not message_id or not pop_receipt: + print("Set environment variables to delete a message:") + print(" $env:AZUREQUEUES_STORAGE_ACCOUNT = ''") + print(" $env:AZUREQUEUES_QUEUE_NAME = ''") + print(" $env:AZUREQUEUES_MESSAGE_ID = ''") + print(" $env:AZUREQUEUES_POP_RECEIPT = ''") + print("\nNote: Get message ID and pop receipt from Example 4.") + return + + async with DefaultAzureCredential() as credential: + + async with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + await client.delete_message( + storage_account_name=STORAGE_ACCOUNT, + queue_name=QUEUE_NAME, + message_id=message_id, + popreceipt=pop_receipt + ) + + print(f"Message '{message_id}' deleted from queue '{QUEUE_NAME}'.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + print("Azure Storage Queues sample usage for the Azure Connectors Python SDK") + print("=" * 60) + + if not CONNECTION_RUNTIME_URL: + print("\nWARNING: AZUREQUEUES_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL to run actual API calls.") + print("Format: https://[region].azure-apihub.net/apim/azurequeues/[id]") + return + + await example_1_list_queues() + await example_2_create_queue() + await example_3_put_message() + await example_4_get_messages() + await example_5_delete_message() + + print("\n" + "=" * 60) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_azuretables.py b/samples/sample_connector_usage/aio/sample_connector_usage_azuretables.py new file mode 100644 index 0000000..83c6c21 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_azuretables.py @@ -0,0 +1,281 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure Storage Tables sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure Storage Tables client from the Azure Connectors Python SDK +to interact with Azure Table Storage. + +Prerequisites: +1. Azure subscription with Azure Storage Tables connection +2. Azure Tables connection in Connector Namespaces (with access configured) +3. Connection runtime URL from Azure Portal +4. Azure Storage Account with table storage + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:AZURETABLES_CONNECTION_URL = "https://...apihub.net/apim/azuretables/..." + $env:AZURETABLES_STORAGE_ACCOUNT = "" + $env:AZURETABLES_TABLE_NAME = "" + + python sample_connector_usage_azuretables.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.azuretables import AzuretablesClient +from azure.connectors.azuretables import ( + CreateTableInput, + CreateEntityInput, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/azuretables/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "AZURETABLES_CONNECTION_URL", + "" +) + +# Storage account name +STORAGE_ACCOUNT = os.environ.get("AZURETABLES_STORAGE_ACCOUNT", "") + +# Table name for entity operations +TABLE_NAME = os.environ.get("AZURETABLES_TABLE_NAME", "") + + +async def example_1_list_tables(): + """Example 1: List all tables in a storage account.""" + print("\n=== Example 1: List Tables ===") + + if not STORAGE_ACCOUNT: + print("Set AZURETABLES_STORAGE_ACCOUNT environment variable.") + print("Example: $env:AZURETABLES_STORAGE_ACCOUNT = 'mystorageaccount'") + return + + async with DefaultAzureCredential() as credential: + + async with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + tables = [ + table + async for table in client.list_tables( + storage_account_name=STORAGE_ACCOUNT + ) + ] + + if tables: + print(f"Tables in storage account '{STORAGE_ACCOUNT}':") + for table in tables: + table_name = table.get("TableName", table) + print(f" - {table_name}") + else: + print("No tables found or empty response.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_create_table(): + """Example 2: Create a new table in the storage account.""" + print("\n=== Example 2: Create Table ===") + + new_table_name = os.environ.get("AZURETABLES_NEW_TABLE_NAME", "") + if not STORAGE_ACCOUNT or not new_table_name: + print("Set environment variables to create a table:") + print(" $env:AZURETABLES_STORAGE_ACCOUNT = ''") + print(" $env:AZURETABLES_NEW_TABLE_NAME = 'MyNewTable'") + return + + async with DefaultAzureCredential() as credential: + + async with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Create table input with table name in additional_properties + table_input = CreateTableInput( + additional_properties={"TableName": new_table_name} + ) + + result = await client.create_table( + input=table_input, + storage_account_name=STORAGE_ACCOUNT + ) + + print(f"Table '{new_table_name}' created successfully.") + if result: + print(f" OData ID: {result.get('odata.id', 'N/A')}") + print(f" Table Name: {result.get('TableName', 'N/A')}") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_create_entity(): + """Example 3: Insert a new entity into a table.""" + print("\n=== Example 3: Create Entity ===") + + if not STORAGE_ACCOUNT or not TABLE_NAME: + print("Set environment variables to create an entity:") + print(" $env:AZURETABLES_STORAGE_ACCOUNT = ''") + print(" $env:AZURETABLES_TABLE_NAME = ''") + return + + async with DefaultAzureCredential() as credential: + + async with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Create entity with PartitionKey, RowKey, and custom properties + entity_input = CreateEntityInput( + additional_properties={ + "PartitionKey": "SamplePartition", + "RowKey": "SampleRow001", + "Name": "Sample Entity", + "Description": "Created by Azure Connectors SDK for Python", + "Count": 42, + "IsActive": True + } + ) + + result = await client.create_entity( + input=entity_input, + storage_account_name=STORAGE_ACCOUNT, + table_name=TABLE_NAME + ) + + print(f"Entity created in table '{TABLE_NAME}':") + if result: + print(f" Partition Key: {result.get('PartitionKey', 'N/A')}") + print(f" Row Key: {result.get('RowKey', 'N/A')}") + else: + print(" Entity created (no response body).") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_get_entities(): + """Example 4: Query entities from a table.""" + print("\n=== Example 4: Get Entities ===") + + if not STORAGE_ACCOUNT or not TABLE_NAME: + print("Set environment variables to query entities:") + print(" $env:AZURETABLES_STORAGE_ACCOUNT = ''") + print(" $env:AZURETABLES_TABLE_NAME = ''") + return + + async with DefaultAzureCredential() as credential: + + async with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Query entities with optional filter + entities = [item async for item in client.list_entities( + storage_account_name=STORAGE_ACCOUNT, + table_name=TABLE_NAME, + # Optional: filter entities + # filter="PartitionKey eq 'SamplePartition'", + # Optional: select specific columns + # select="PartitionKey,RowKey,Name" + )] + + if entities: + print(f"Entities in table '{TABLE_NAME}':") + for i, entity in enumerate(entities[:5], 1): # Show first 5 + pk = entity.get("PartitionKey", "N/A") + rk = entity.get("RowKey", "N/A") + print(f" {i}. PartitionKey: {pk}, RowKey: {rk}") + if len(entities) > 5: + print(f" ... and {len(entities) - 5} more entities") + else: + print("No entities found or empty response.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_get_entity(): + """Example 5: Get a specific entity by PartitionKey and RowKey.""" + print("\n=== Example 5: Get Entity ===") + + partition_key = os.environ.get("AZURETABLES_PARTITION_KEY", "SamplePartition") + row_key = os.environ.get("AZURETABLES_ROW_KEY", "SampleRow001") + + if not STORAGE_ACCOUNT or not TABLE_NAME: + print("Set environment variables to get an entity:") + print(" $env:AZURETABLES_STORAGE_ACCOUNT = ''") + print(" $env:AZURETABLES_TABLE_NAME = ''") + print("Optional:") + print(" $env:AZURETABLES_PARTITION_KEY = ''") + print(" $env:AZURETABLES_ROW_KEY = ''") + return + + async with DefaultAzureCredential() as credential: + + async with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.get_entity( + storage_account_name=STORAGE_ACCOUNT, + table_name=TABLE_NAME, + partition_key=partition_key, + row_key=row_key + ) + + if result: + print(f"Entity found in '{TABLE_NAME}':") + print(f" Partition Key: {result.get('PartitionKey', 'N/A')}") + print(f" Row Key: {result.get('RowKey', 'N/A')}") + # Print custom properties (excluding system properties) + system_props = { + 'PartitionKey', 'RowKey', 'Timestamp', + 'odata.metadata', 'odata.etag' + } + custom_props = { + k: v for k, v in result.items() if k not in system_props + } + if custom_props: + print(" Custom properties:") + for key, value in custom_props.items(): + print(f" {key}: {value}") + else: + print("Entity not found.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + print("Azure Storage Tables sample usage for the Azure Connectors Python SDK") + print("=" * 60) + + if not CONNECTION_RUNTIME_URL: + print("\nWARNING: AZURETABLES_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL to run actual API calls.") + print("Format: https://[region].azure-apihub.net/apim/azuretables/[id]") + return + + await example_1_list_tables() + await example_2_create_table() + await example_3_create_entity() + await example_4_get_entities() + await example_5_get_entity() + + print("\n" + "=" * 60) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_azurevm.py b/samples/sample_connector_usage/aio/sample_connector_usage_azurevm.py new file mode 100644 index 0000000..a63a3b4 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_azurevm.py @@ -0,0 +1,224 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure VM sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure VM client from the Azure Connectors Python SDK to manage +virtual machines and VM scale sets. + +Prerequisites: +1. Azure subscription with Azure VM connection +2. Azure VM connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:AZUREVM_CONNECTION_URL = "https://[region].azure-apihub.net/apim/azurevm/[connection-id]" + + python sample_connector_usage_azurevm.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.azurevm import AzurevmClient + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/azurevm/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "AZUREVM_CONNECTION_URL", + "" +) + +# Sample resource identifiers (replace with your own) +SUBSCRIPTION_ID = os.environ.get("AZURE_SUBSCRIPTION_ID", "your-subscription-id") +RESOURCE_GROUP = os.environ.get("AZURE_RESOURCE_GROUP", "your-resource-group") +VM_NAME = os.environ.get("AZURE_VM_NAME", "your-vm-name") +VMSS_NAME = os.environ.get("AZURE_VMSS_NAME", "your-vmss-name") +VMSS_INSTANCE_ID = os.environ.get("AZURE_VMSS_INSTANCE_ID", "0") + + +async def example_1_get_virtual_machine(): + """Example 1: Get details of a virtual machine.""" + print("\n=== Example 1: Get Virtual Machine ===") + + async with DefaultAzureCredential() as credential: + + async with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.virtual_machine_get( + subscription_id=SUBSCRIPTION_ID, + resource_group_name=RESOURCE_GROUP, + virtual_machine_name=VM_NAME + ) + + if result: + print(f"VM Name: {result.get('name')}") + print(f"VM ID: {result.get('id')}") + props = result.get('properties', {}) + print(f"Provisioning State: {props.get('provisioningState')}") + else: + print("No VM found") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_start_virtual_machine(): + """Example 2: Start a virtual machine.""" + print("\n=== Example 2: Start Virtual Machine ===") + + async with DefaultAzureCredential() as credential: + + async with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + await client.virtual_machine_start( + subscription_id=SUBSCRIPTION_ID, + resource_group_name=RESOURCE_GROUP, + virtual_machine_name=VM_NAME + ) + + print(f"Start command sent for VM: {VM_NAME}") + print("Note: VM start is an async operation. Check Azure Portal for status.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_deallocate_virtual_machine(): + """Example 3: Deallocate (stop and release resources) a virtual machine.""" + print("\n=== Example 3: Deallocate Virtual Machine ===") + + async with DefaultAzureCredential() as credential: + + async with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + await client.virtual_machine_deallocate( + subscription_id=SUBSCRIPTION_ID, + resource_group_name=RESOURCE_GROUP, + virtual_machine_name=VM_NAME + ) + + print(f"Deallocate command sent for VM: {VM_NAME}") + print("Note: This releases compute resources. You won't be billed while deallocated.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_restart_virtual_machine(): + """Example 4: Restart a virtual machine.""" + print("\n=== Example 4: Restart Virtual Machine ===") + + async with DefaultAzureCredential() as credential: + + async with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + await client.virtual_machine_restart( + subscription_id=SUBSCRIPTION_ID, + resource_group_name=RESOURCE_GROUP, + virtual_machine_name=VM_NAME + ) + + print(f"Restart command sent for VM: {VM_NAME}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_get_vm_in_scale_set(): + """Example 5: Get details of a VM in a scale set.""" + print("\n=== Example 5: Get VM in Scale Set ===") + + async with DefaultAzureCredential() as credential: + + async with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.virtual_machine_in_scale_set_get( + subscription_id=SUBSCRIPTION_ID, + resource_group_name=RESOURCE_GROUP, + virtual_machine_scale_set_name=VMSS_NAME, + virtual_machine_in_scale_set_instance_id=VMSS_INSTANCE_ID + ) + + if result: + print(f"VMSS Instance Name: {result.get('name')}") + print(f"Instance ID: {result.get('instanceId')}") + props = result.get('properties', {}) + print(f"Provisioning State: {props.get('provisioningState')}") + else: + print("No VMSS instance found") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_6_scale_set_operations(): + """Example 6: Perform operations on a VM in a scale set.""" + print("\n=== Example 6: Scale Set VM Operations ===") + + async with DefaultAzureCredential() as credential: + + async with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Start VM in scale set + print(f"Starting VMSS instance {VMSS_INSTANCE_ID}...") + await client.virtual_machine_in_scale_set_start( + subscription_id=SUBSCRIPTION_ID, + resource_group_name=RESOURCE_GROUP, + virtual_machine_scale_set_name=VMSS_NAME, + virtual_machine_in_scale_set_instance_id=VMSS_INSTANCE_ID + ) + print("Start command sent") + + # Other available operations (commented out): + # - virtual_machine_in_scale_set_deallocate + # - virtual_machine_in_scale_set_power_off + # - virtual_machine_in_scale_set_restart + # - virtual_machine_in_scale_set_redeploy + # - virtual_machine_in_scale_set_reimage + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: AZUREVM_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + # Only run the read-only example by default + await example_1_get_virtual_machine() + + # Uncomment to run VM control operations: + # await example_2_start_virtual_machine() + # await example_3_deallocate_virtual_machine() + # await example_4_restart_virtual_machine() + # await example_5_get_vm_in_scale_set() + # await example_6_scale_set_operations() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_box.py b/samples/sample_connector_usage/aio/sample_connector_usage_box.py new file mode 100644 index 0000000..2e7dd26 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_box.py @@ -0,0 +1,144 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Box sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Box client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Box connection +2. Box connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:BOX_CONNECTION_URL = "https://[region].azure-apihub.net/apim/box/[connection-id]" + + python sample_connector_usage_box.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.box import BoxClient + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/box/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "BOX_CONNECTION_URL", + "", +) + + +async def example_1_list_root_folder(): + """Example 1: List items in the root folder.""" + print("\n=== Example 1: List Root Folder ===") + + async with DefaultAzureCredential() as credential: + + async with BoxClient(CONNECTION_RUNTIME_URL, credential) as client: + items = [item async for item in client.list_root_folder()] + + if items: + print(f"Found {len(items)} items in root folder:") + for item in items[:10]: + icon = "[DIR]" if item.get("IsFolder") else "[FILE]" + print(f" {icon} {item.get('Name', 'N/A')}") + else: + print("No root-folder items returned.") + + +async def example_2_get_file_metadata_by_path(): + """Example 2: Get file metadata by path.""" + print("\n=== Example 2: Get Metadata by Path ===") + + file_path = os.environ.get("BOX_TEST_FILE_PATH", "") + if not file_path: + print("Set BOX_TEST_FILE_PATH, for example '/Documents/report.pdf'.") + return + + async with DefaultAzureCredential() as credential: + + async with BoxClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + metadata = await client.get_file_metadata_by_path(path=file_path) + + if metadata: + print(f"Name: {metadata.get('Name', 'N/A')}") + print(f"Size: {metadata.get('Size', 'N/A')} bytes") + print(f"LastModified: {metadata.get('LastModified', 'N/A')}") + else: + print("No metadata returned.") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def example_3_create_file(): + """Example 3: Upload a file from bytes content.""" + print("\n=== Example 3: Create File ===") + + destination_folder = os.environ.get("BOX_TEST_DEST_FOLDER", "/Documents") + destination_name = os.environ.get("BOX_TEST_FILE_NAME", "sdk-sample.txt") + + async with DefaultAzureCredential() as credential: + + async with BoxClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.create_file( + input=b"Hello from azure-connectors Box sample!", + folder_path=destination_folder, + name=destination_name, + ) + + if result: + print(f"Created file id: {result.get('Id', 'N/A')}") + else: + print("Create operation completed with no response body.") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def example_4_list_folder_for_polling(): + """Example 4: List a folder as the basis for polling logic.""" + print("\n=== Example 4: List Folder for Polling ===") + + folder_id = os.environ.get("BOX_TEST_FOLDER_ID", "") + if not folder_id: + print("Set BOX_TEST_FOLDER_ID to test trigger polling calls.") + return + + async with DefaultAzureCredential() as credential: + + async with BoxClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_folder(id=folder_id)] + print(f"Folder listing returned {len(items)} item(s).") + print("Persist item IDs or timestamps to implement polling with this action client.") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def main(): + """Run all Box connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: BOX_CONNECTION_URL environment variable is not set.") + print("Set it to your Box connector runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_list_root_folder() + await example_2_get_file_metadata_by_path() + await example_3_create_file() + await example_4_list_folder_for_polling() + + print("\n=== Box sample completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_campfire.py b/samples/sample_connector_usage/aio/sample_connector_usage_campfire.py new file mode 100644 index 0000000..171f80f --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_campfire.py @@ -0,0 +1,104 @@ +""" +Campfire sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Campfire client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a Campfire connection +2. Campfire connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:CAMPFIRE_CONNECTION_URL = "https://[region].azure-apihub.net/apim/campfire/[id]" + + python sample_connector_usage_campfire.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.campfire import CampfireClient + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/campfire/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("CAMPFIRE_CONNECTION_URL", "") + + +async def example_1_list_accounts() -> None: + """Example 1: List accounts this user has access to.""" + print("\n=== Example 1: List Accounts ===") + + async with DefaultAzureCredential() as credential: + async with CampfireClient(CONNECTION_RUNTIME_URL, credential) as client: + accounts = [item async for item in client.list_accounts()] + print(f"Accounts: {accounts}") + + +async def example_2_list_rooms() -> None: + """Example 2: List the rooms in an account.""" + print("\n=== Example 2: List Rooms ===") + + async with DefaultAzureCredential() as credential: + async with CampfireClient(CONNECTION_RUNTIME_URL, credential) as client: + rooms = [item async for item in client.list_rooms(account="ACCOUNT_ID")] + print(f"Rooms: {rooms}") + + +async def example_3_create_message() -> None: + """Example 3: Send a message to a room.""" + print("\n=== Example 3: Create Message ===") + + async with DefaultAzureCredential() as credential: + async with CampfireClient(CONNECTION_RUNTIME_URL, credential) as client: + result = await client.create_message( + room_id="ROOM_ID", + account="ACCOUNT_ID", + message="Hello from the Campfire client in the Azure Connectors Python SDK.", + ) + print(f"Create message result: {result}") + + +async def example_4_get_user() -> None: + """Example 4: Get information about a user by ID.""" + print("\n=== Example 4: Get User ===") + + async with DefaultAzureCredential() as credential: + async with CampfireClient(CONNECTION_RUNTIME_URL, credential) as client: + user = await client.get_user(user_id=12345, account="ACCOUNT_ID") + print(f"User: {user}") + + +async def main() -> None: + """Run Campfire connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: CAMPFIRE_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Campfire sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + # Uncomment to list accounts/rooms, send a message, or get a user. + # await example_1_list_accounts() + # await example_2_list_rooms() + # await example_3_create_message() + # await example_4_get_user() + print("Set the example calls in main() to run against your instance.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_clicksendsms.py b/samples/sample_connector_usage/aio/sample_connector_usage_clicksendsms.py new file mode 100644 index 0000000..3f431a5 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_clicksendsms.py @@ -0,0 +1,115 @@ +""" +ClickSend SMS sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the ClickSend SMS client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a ClickSend SMS connection +2. ClickSend SMS connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:CLICKSENDSMS_CONNECTION_URL = "https://[region].azure-apihub.net/apim/clicksendsms/[id]" + + python sample_connector_usage_clicksendsms.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.clicksendsms import ClicksendsmsClient +from azure.connectors.clicksendsms import ( + CreateListInput, + SmsSendInput, +) + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/clicksendsms/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("CLICKSENDSMS_CONNECTION_URL", "") + + +async def example_1_send_sms() -> None: + """Example 1: Send an SMS message.""" + print("\n=== Example 1: Send SMS ===") + + async with DefaultAzureCredential() as credential: + async with ClicksendsmsClient(CONNECTION_RUNTIME_URL, credential) as client: + result = await client.sms_send( + input=SmsSendInput( + messages=[ + { + "to": "+61411111111", + "body": "Hello from the ClickSend SMS client in the Azure Connectors Python SDK.", + } + ], + ), + ) + print(f"Send result: {result}") + + +async def example_2_get_contact_lists() -> None: + """Example 2: Get contact lists.""" + print("\n=== Example 2: Get Contact Lists ===") + + async with DefaultAzureCredential() as credential: + async with ClicksendsmsClient(CONNECTION_RUNTIME_URL, credential) as client: + lists = await client.get_contact_lists(page=1, limit=10) + print(f"Contact lists: {lists}") + + +async def example_3_create_list() -> None: + """Example 3: Create a new contact list.""" + print("\n=== Example 3: Create Contact List ===") + + async with DefaultAzureCredential() as credential: + async with ClicksendsmsClient(CONNECTION_RUNTIME_URL, credential) as client: + result = await client.create_list( + input=CreateListInput(list_name="My New List"), + ) + print(f"Created list: {result}") + + +async def example_4_search_contact_lists() -> None: + """Example 4: Search contact lists.""" + print("\n=== Example 4: Search Contact Lists ===") + + async with DefaultAzureCredential() as credential: + async with ClicksendsmsClient(CONNECTION_RUNTIME_URL, credential) as client: + results = await client.search_contact_list(q="friends") + print(f"Search results: {results}") + + +async def main() -> None: + """Run ClickSend SMS connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: CLICKSENDSMS_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("ClickSend SMS sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + # Uncomment to send an SMS, list/create/search contact lists. + # await example_1_send_sms() + # await example_2_get_contact_lists() + # await example_3_create_list() + # await example_4_search_contact_lists() + print("Set the example calls in main() to run against your instance.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_cloudconvert.py b/samples/sample_connector_usage/aio/sample_connector_usage_cloudconvert.py new file mode 100644 index 0000000..18936b9 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_cloudconvert.py @@ -0,0 +1,31 @@ +"""CloudConvert sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.cloudconvert import CloudconvertClient + + +CONNECTION_RUNTIME_URL = os.environ.get("CLOUDCONVERT_CONNECTION_URL", "") + + +async def main() -> None: + """Get CloudConvert conversion options.""" + if not CONNECTION_RUNTIME_URL: + print("Set CLOUDCONVERT_CONNECTION_URL to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with CloudconvertClient(CONNECTION_RUNTIME_URL, credential) as client: + options = await client.get_convert_options() + print(f"Conversion options: {options}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_cloudmersiveconvert.py b/samples/sample_connector_usage/aio/sample_connector_usage_cloudmersiveconvert.py new file mode 100644 index 0000000..c0956e0 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_cloudmersiveconvert.py @@ -0,0 +1,101 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Cloudmersive Convert sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Cloudmersive Convert client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a Cloudmersive Convert connection +2. Cloudmersive Convert connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:CLOUDMERSIVECONVERT_CONNECTION_URL = + "https://[region].azure-apihub.net/apim/cloudmersiveconvert/[connection-id]" + + python sample_connector_usage_cloudmersiveconvert.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.cloudmersiveconvert import CloudmersiveconvertClient +from azure.connectors.cloudmersiveconvert import ( + GetDocxBodyRequest, + ScreenshotRequest, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/cloudmersiveconvert/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("CLOUDMERSIVECONVERT_CONNECTION_URL", "") + + +async def example_1_convert_url_to_pdf(): + """Example 1: Convert a web page URL to a PDF document.""" + print("\n=== Example 1: Convert URL to PDF ===") + + async with DefaultAzureCredential() as credential: + + async with CloudmersiveconvertClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + request = ScreenshotRequest( + url="https://www.example.com", + ) + + result = await client.convert_web_url_to_pdf(input=request) + + print(f"Converted PDF byte length: {len(result) if result else 0}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_get_docx_body(): + """Example 2: Get the body content from a Word DOCX document.""" + print("\n=== Example 2: Get DOCX body ===") + + async with DefaultAzureCredential() as credential: + + async with CloudmersiveconvertClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + request = GetDocxBodyRequest( + input_file_url="https://example.com/document.docx", + ) + + result = await client.edit_document_docx_body(input=request) + + print(f"DOCX body result: {result}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: CLOUDMERSIVECONVERT_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_convert_url_to_pdf() + await example_2_get_docx_body() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_commondataservice.py b/samples/sample_connector_usage/aio/sample_connector_usage_commondataservice.py new file mode 100644 index 0000000..b6f964b --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_commondataservice.py @@ -0,0 +1,286 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Microsoft Dataverse (Common Data Service) sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Microsoft Dataverse client from the Azure Connectors Python SDK. +This connector was formerly known as Common Data Service (legacy). + +Prerequisites: +1. Azure subscription with Microsoft Dataverse connection +2. Microsoft Dataverse connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:COMMONDATASERVICE_CONNECTION_URL = ` + "https://[region].azure-apihub.net/apim/commondataservice/[connection-id]" + + # The dataset is the Dataverse environment/organization URL. Because it + # contains "://", the SDK URL-encodes it twice so it survives apihub + # gateway routing. + $env:COMMONDATASERVICE_DATASET = "https://orgXXXXXXXX.crm.dynamics.com" + + python sample_connector_usage_commondataservice.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.commondataservice import CommondataserviceClient +from azure.connectors.commondataservice import ( + PostItemInput, + PatchItemInput, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/commondataservice/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "COMMONDATASERVICE_CONNECTION_URL", + "" +) + +# The dataset is the Dataverse environment/organization URL, e.g. +# "https://orgXXXXXXXX.crm.dynamics.com". The SDK double-encodes this path +# segment automatically. +DATASET = os.environ.get( + "COMMONDATASERVICE_DATASET", + "https://orgXXXXXXXX.crm.dynamics.com" +) + + +async def example_1_list_datasets(): + """Example 1: List the datasets (environments) available to the connection.""" + print("\n=== Example 1: List Datasets ===") + + async with DefaultAzureCredential() as credential: + + async with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_data_sets()] + + if items: + print(f"Found {len(items)} datasets:") + for dataset in items[:5]: + print(f" - {dataset.get('Name', dataset.get('DisplayName', 'N/A'))}") + else: + print("No datasets found") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_list_accounts(): + """Example 2: List rows from the 'accounts' table. + + Retrieves account rows with OData query options. + """ + print("\n=== Example 2: List Accounts ===") + + async with DefaultAzureCredential() as credential: + + async with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + accounts = [ + account + async for account in client.list_items( + dataset=DATASET, + table="accounts", + filter="statecode eq 0", # Active accounts only + orderby="name asc", + top=10, + ) + ] + + if accounts: + print(f"Found {len(accounts)} accounts:") + for account in accounts[:5]: + print(f" - {account.get('name', 'N/A')}") + else: + print("No accounts found") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_get_account_by_id(): + """Example 3: Get a single account row by its primary id.""" + print("\n=== Example 3: Get Account by ID ===") + + async with DefaultAzureCredential() as credential: + + # Replace with an actual account id from your Dataverse environment. + account_id = "00000000-0000-0000-0000-000000000000" + + async with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.get_item( + dataset=DATASET, + table="accounts", + id=account_id, + ) + + if result: + print(f"Account: {result.get('name', 'N/A')}") + print(f"Revenue: {result.get('revenue', 'N/A')}") + else: + print("Account not found") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_create_account(): + """Example 4: Add a new row to the 'accounts' table.""" + print("\n=== Example 4: Create Account ===") + + async with DefaultAzureCredential() as credential: + + async with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + new_account = PostItemInput( + additional_properties={ + "name": "Contoso Ltd.", + "description": "Sample account created via SDK", + "revenue": 1000000.00, + "websiteurl": "https://contoso.com", + } + ) + + result = await client.post_item( + input=new_account, + dataset=DATASET, + table="accounts", + ) + + if result: + print(f"Account created with id: {result.get('accountid', 'N/A')}") + else: + print("Account created successfully") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_update_account(): + """Example 5: Update an existing row in the 'accounts' table.""" + print("\n=== Example 5: Update Account ===") + + async with DefaultAzureCredential() as credential: + + # Replace with an actual account id. + account_id = "00000000-0000-0000-0000-000000000000" + + async with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + update_data = PatchItemInput( + additional_properties={ + "description": "Updated via SDK", + "revenue": 2000000.00, + } + ) + + await client.patch_item( + input=update_data, + dataset=DATASET, + table="accounts", + id=account_id, + ) + + print("Account updated successfully") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_6_create_attachment(): + """Example 6: Add a note attachment to an account row.""" + print("\n=== Example 6: Create Account Attachment ===") + + async with DefaultAzureCredential() as credential: + + # Replace with an actual account id from your Dataverse environment. + account_id = "00000000-0000-0000-0000-000000000000" + + async with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.create_attachment( + input=b"Sample attachment content", + dataset=DATASET, + table="accounts", + id=account_id, + display_name="sample-note.txt", + ) + + if result: + print(f"Attachment created with id: {result.get('annotationid', 'N/A')}") + else: + print("Attachment created successfully") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_7_get_table_metadata(): + """Example 7: Get metadata for the 'accounts' table.""" + print("\n=== Example 7: Get Table Metadata ===") + + async with DefaultAzureCredential() as credential: + + async with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.get_table( + dataset=DATASET, + table="accounts", + ) + + if result: + print(f"Table: {result.get('Name', result.get('DisplayName', 'N/A'))}") + else: + print("Table metadata not found") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: COMMONDATASERVICE_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + print(f"Using dataset: {DATASET}") + + await example_1_list_datasets() + await example_2_list_accounts() + await example_3_get_account_by_id() + await example_4_create_account() + await example_5_update_account() + await example_6_create_attachment() + await example_7_get_table_metadata() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_documentdb.py b/samples/sample_connector_usage/aio/sample_connector_usage_documentdb.py new file mode 100644 index 0000000..e1050df --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_documentdb.py @@ -0,0 +1,263 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure Cosmos DB (DocumentDB) sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure Cosmos DB client from the Azure Connectors Python SDK +to query documents in Cosmos DB containers. + +Note: The connector name "documentdb" reflects the original Azure DocumentDB +branding; it connects to Azure Cosmos DB accounts. + +Prerequisites: +1. Azure subscription with Azure Cosmos DB connection +2. DocumentDB connection in Connector Namespaces (with access configured) +3. Connection runtime URL from Azure Portal +4. Azure Cosmos DB account with a database and container + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:DOCUMENTDB_CONNECTION_URL = "https://...apihub.net/apim/documentdb/..." + $env:DOCUMENTDB_ACCOUNT = "" + $env:DOCUMENTDB_DATABASE = "" + $env:DOCUMENTDB_CONTAINER = "" + + python sample_connector_usage_documentdb.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.documentdb import DocumentdbClient + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/documentdb/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "DOCUMENTDB_CONNECTION_URL", + "" +) + +# Cosmos DB account name +COSMOS_DB_ACCOUNT = os.environ.get("DOCUMENTDB_ACCOUNT", "") + +# Database ID +DATABASE_ID = os.environ.get("DOCUMENTDB_DATABASE", "") + +# Container ID +CONTAINER_ID = os.environ.get("DOCUMENTDB_CONTAINER", "") + + +async def example_1_query_all_documents(): + """Example 1: Query all documents in a container.""" + print("\n=== Example 1: Query All Documents ===") + + if not COSMOS_DB_ACCOUNT or not DATABASE_ID or not CONTAINER_ID: + print("Set environment variables to query documents:") + print(" $env:DOCUMENTDB_ACCOUNT = ''") + print(" $env:DOCUMENTDB_DATABASE = ''") + print(" $env:DOCUMENTDB_CONTAINER = ''") + return + + async with DefaultAzureCredential() as credential: + + async with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + documents = [item async for item in client.list_query_documents( + cosmos_db_account_name=COSMOS_DB_ACCOUNT, + database_id=DATABASE_ID, + container_id=CONTAINER_ID, + query_text="SELECT * FROM c" + )] + + if documents: + count = len(documents) + print(f"Found {count} document(s) in container '{CONTAINER_ID}':") + for i, doc in enumerate(documents[:3], 1): # Show first 3 + doc_id = doc.get("id", "N/A") + print(f" {i}. id: {doc_id}") + if count > 3: + print(f" ... and {count - 3} more documents") + else: + print("No documents found or empty response.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_query_with_filter(): + """Example 2: Query documents with a filter condition.""" + print("\n=== Example 2: Query with Filter ===") + + if not COSMOS_DB_ACCOUNT or not DATABASE_ID or not CONTAINER_ID: + print("Set environment variables to query documents.") + return + + async with DefaultAzureCredential() as credential: + + async with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Query with WHERE clause - adjust field names for your schema + documents = [item async for item in client.list_query_documents( + cosmos_db_account_name=COSMOS_DB_ACCOUNT, + database_id=DATABASE_ID, + container_id=CONTAINER_ID, + query_text="SELECT * FROM c WHERE c.type = 'sample'" + )] + + if documents: + count = len(documents) + print(f"Found {count} document(s) matching filter:") + for doc in documents[:5]: + doc_id = doc.get("id", "N/A") + doc_type = doc.get("type", "N/A") + print(f" - id: {doc_id}, type: {doc_type}") + else: + print("No matching documents found.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_query_with_pagination(): + """Example 3: Query documents across automatically followed pages.""" + print("\n=== Example 3: Query with Automatic Pagination ===") + + if not COSMOS_DB_ACCOUNT or not DATABASE_ID or not CONTAINER_ID: + print("Set environment variables to query documents.") + return + + async with DefaultAzureCredential() as credential: + + async with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # The iterator follows continuation links until all pages are consumed. + documents = [item async for item in client.list_query_documents( + cosmos_db_account_name=COSMOS_DB_ACCOUNT, + database_id=DATABASE_ID, + container_id=CONTAINER_ID, + query_text="SELECT c.id, c.type FROM c", + max_item_count=2 + )] + + if documents: + print(f"Retrieved {len(documents)} document(s) across all pages") + for doc in documents: + print(f" - id: {doc.get('id', 'N/A')}") + else: + print("No documents found.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_query_with_partition_key(): + """Example 4: Query documents with a specific partition key.""" + print("\n=== Example 4: Query with Partition Key ===") + + partition_key = os.environ.get("DOCUMENTDB_PARTITION_KEY", "") + if not COSMOS_DB_ACCOUNT or not DATABASE_ID or not CONTAINER_ID: + print("Set environment variables to query documents.") + return + + if not partition_key: + print("Set DOCUMENTDB_PARTITION_KEY environment variable for this example.") + print("Example: $env:DOCUMENTDB_PARTITION_KEY = 'myPartitionValue'") + print("Skipping partition key example...") + return + + async with DefaultAzureCredential() as credential: + + async with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Query within a specific partition + documents = [item async for item in client.list_query_documents( + cosmos_db_account_name=COSMOS_DB_ACCOUNT, + database_id=DATABASE_ID, + container_id=CONTAINER_ID, + query_text="SELECT * FROM c", + partition_key=partition_key + )] + + if documents: + print(f"Found {len(documents)} document(s) in partition '{partition_key}':") + for doc in documents[:5]: + print(f" - id: {doc.get('id', 'N/A')}") + else: + print(f"No documents found in partition '{partition_key}'.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_query_with_consistency(): + """Example 5: Query documents with a specific consistency level.""" + print("\n=== Example 5: Query with Consistency Level ===") + + if not COSMOS_DB_ACCOUNT or not DATABASE_ID or not CONTAINER_ID: + print("Set environment variables to query documents.") + return + + async with DefaultAzureCredential() as credential: + + async with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Query with Session consistency (common for read-your-writes) + # Valid levels: Strong, BoundedStaleness, Session, Eventual + documents = [item async for item in client.list_query_documents( + cosmos_db_account_name=COSMOS_DB_ACCOUNT, + database_id=DATABASE_ID, + container_id=CONTAINER_ID, + query_text="SELECT TOP 5 c.id FROM c ORDER BY c._ts DESC", + consistency_level="Session" + )] + + if documents: + print("Query completed with Session consistency:") + print(f" Documents retrieved: {len(documents)}") + + for doc in documents: + print(f" - id: {doc.get('id', 'N/A')}") + else: + print("No documents found.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + print("Azure Cosmos DB (DocumentDB) sample usage for the Azure Connectors Python SDK") + print("=" * 60) + + if not CONNECTION_RUNTIME_URL: + print("\nWARNING: DOCUMENTDB_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL to run actual API calls.") + print("Format: https://[region].azure-apihub.net/apim/documentdb/[id]") + return + + await example_1_query_all_documents() + await example_2_query_with_filter() + await example_3_query_with_pagination() + await example_4_query_with_partition_key() + await example_5_query_with_consistency() + + print("\n" + "=" * 60) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_docusign.py b/samples/sample_connector_usage/aio/sample_connector_usage_docusign.py new file mode 100644 index 0000000..440e6dd --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_docusign.py @@ -0,0 +1,96 @@ +""" +DocuSign sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the DocuSign client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with DocuSign connection +2. DocuSign connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:DOCUSIGN_CONNECTION_URL = "https://[region].azure-apihub.net/apim/docusign/[connection-id]" + + python sample_connector_usage_docusign.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.docusign import DocusignClient + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/docusign/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("DOCUSIGN_CONNECTION_URL", "") + + +async def example_1_get_login_accounts() -> list[dict]: + """Example 1: Get available DocuSign accounts.""" + print("\n=== Example 1: Get Login Accounts ===") + + async with DefaultAzureCredential() as credential: + async with DocusignClient(CONNECTION_RUNTIME_URL, credential) as client: + accounts_response = [item async for item in client.list_login_accounts()] + accounts = accounts_response + + print(f"Found {len(accounts)} accounts") + for account in accounts[:10]: + print(f" - {account.get('accountName')} ({account.get('accountId')})") + + return accounts + + +async def example_2_search_envelopes(account_id: str) -> None: + """Example 2: Search envelopes for an account.""" + print("\n=== Example 2: Search Envelopes ===") + + async with DefaultAzureCredential() as credential: + async with DocusignClient(CONNECTION_RUNTIME_URL, credential) as client: + envelopes_response = await client.search_list_envelopes( + account_id=account_id, + top=5, + ) + + envelopes = envelopes_response + print(f"Found {len(envelopes)} envelopes") + for envelope in envelopes[:5]: + print(f" - {envelope.get('envelopeId')} ({envelope.get('status')})") + + +async def main() -> None: + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: DOCUSIGN_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("DocuSign sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + accounts = await example_1_get_login_accounts() + if accounts: + first_account_id = accounts[0].get("accountId") + if first_account_id: + await example_2_search_envelopes(first_account_id) + else: + print("No account id found in first record; skipping envelope search.") + else: + print("No accounts found; skipping account-specific examples.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_docuware.py b/samples/sample_connector_usage/aio/sample_connector_usage_docuware.py new file mode 100644 index 0000000..526f62b --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_docuware.py @@ -0,0 +1,100 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +DocuWare sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the DocuWare client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a DocuWare connection +2. DocuWare connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:DOCUWARE_CONNECTION_URL = + "https://[region].azure-apihub.net/apim/docuware/[connection-id]" + + python sample_connector_usage_docuware.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.docuware import DocuwareClient +from azure.connectors.docuware import ( + SearchForDocumentsInFileCabinetInput, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/docuware/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("DOCUWARE_CONNECTION_URL", "") + + +async def example_1_get_file_cabinets(): + """Example 1: List available file cabinets and document trays.""" + print("\n=== Example 1: Get file cabinets ===") + + async with DefaultAzureCredential() as credential: + + async with DocuwareClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_file_cabinets( + file_cabinet_type="", + )] + + print(f"File cabinets result: {items}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_search_documents(): + """Example 2: Search a file cabinet for matching documents.""" + print("\n=== Example 2: Search documents in file cabinet ===") + + async with DefaultAzureCredential() as credential: + + async with DocuwareClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + request = SearchForDocumentsInFileCabinetInput() + + result = await client.search_for_documents_in_file_cabinet( + input=request, + file_cabinet="", + search_dialog_id="", + ) + + print(f"Search result: {result}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: DOCUWARE_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_get_file_cabinets() + await example_2_search_documents() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_dropbox.py b/samples/sample_connector_usage/aio/sample_connector_usage_dropbox.py new file mode 100644 index 0000000..c421c19 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_dropbox.py @@ -0,0 +1,144 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Dropbox sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Dropbox client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Dropbox connection +2. Dropbox connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:DROPBOX_CONNECTION_URL = "https://[region].azure-apihub.net/apim/dropbox/[connection-id]" + + python sample_connector_usage_dropbox.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.dropbox import DropboxClient + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/dropbox/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "DROPBOX_CONNECTION_URL", + "", +) + + +async def example_1_list_root_folder(): + """Example 1: List items in the root folder.""" + print("\n=== Example 1: List Root Folder ===") + + async with DefaultAzureCredential() as credential: + + async with DropboxClient(CONNECTION_RUNTIME_URL, credential) as client: + items = [item async for item in client.list_root_folder()] + + if items: + print(f"Found {len(items)} items in root folder:") + for item in items[:10]: + icon = "[DIR]" if item.get("IsFolder") else "[FILE]" + print(f" {icon} {item.get('Name', 'N/A')}") + else: + print("No root-folder items returned.") + + +async def example_2_get_file_metadata_by_path(): + """Example 2: Get file metadata by path.""" + print("\n=== Example 2: Get Metadata by Path ===") + + file_path = os.environ.get("DROPBOX_TEST_FILE_PATH", "") + if not file_path: + print("Set DROPBOX_TEST_FILE_PATH, for example '/Documents/report.pdf'.") + return + + async with DefaultAzureCredential() as credential: + + async with DropboxClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + metadata = await client.get_file_metadata_by_path(path=file_path) + + if metadata: + print(f"Name: {metadata.get('Name', 'N/A')}") + print(f"Size: {metadata.get('Size', 'N/A')} bytes") + print(f"LastModified: {metadata.get('LastModified', 'N/A')}") + else: + print("No metadata returned.") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def example_3_create_file(): + """Example 3: Upload a text file.""" + print("\n=== Example 3: Create File ===") + + destination_folder = os.environ.get("DROPBOX_TEST_DEST_FOLDER", "/Documents") + destination_name = os.environ.get("DROPBOX_TEST_FILE_NAME", "sdk-sample.txt") + + async with DefaultAzureCredential() as credential: + + async with DropboxClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.create_file( + input=b"Hello from azure-connectors Dropbox sample!", + folder_path=destination_folder, + name=destination_name, + ) + + if result: + print(f"Created file id: {result.get('Id', 'N/A')}") + else: + print("Create operation completed with no response body.") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def example_4_list_folder_for_polling(): + """Example 4: List a folder as the basis for polling logic.""" + print("\n=== Example 4: List Folder for Polling ===") + + folder_id = os.environ.get("DROPBOX_TEST_FOLDER_ID", "") + if not folder_id: + print("Set DROPBOX_TEST_FOLDER_ID to test trigger polling calls.") + return + + async with DefaultAzureCredential() as credential: + + async with DropboxClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_folder(id=folder_id)] + print(f"Folder listing returned {len(items)} item(s).") + print("Persist item IDs or timestamps to implement polling with this action client.") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def main(): + """Run all Dropbox connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: DROPBOX_CONNECTION_URL environment variable is not set.") + print("Set it to your Dropbox connector runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_list_root_folder() + await example_2_get_file_metadata_by_path() + await example_3_create_file() + await example_4_list_folder_for_polling() + + print("\n=== Dropbox sample completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_dynamicsax.py b/samples/sample_connector_usage/aio/sample_connector_usage_dynamicsax.py new file mode 100644 index 0000000..2f07172 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_dynamicsax.py @@ -0,0 +1,124 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Dynamics 365 for Finance and Operations (Dynamics AX) sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Dynamics AX client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a Dynamics AX connection +2. Dynamics AX connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:DYNAMICSAX_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/dynamicsax/[connection-id]" + ) + $env:DYNAMICSAX_DATASET = "https://[your-instance].operations.dynamics.com" + + python sample_connector_usage_dynamicsax.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.dynamicsax import DynamicsaxClient +from azure.connectors.dynamicsax import ( + PostItemInput, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/dynamicsax/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "DYNAMICSAX_CONNECTION_URL", + "", +) + +# The Dynamics 365 for Finance and Operations instance URL. +DATASET = os.environ.get("DYNAMICSAX_DATASET", "") + + +async def example_1_list_instances(): + """Example 1: List accessible Dynamics 365 Fin & Ops instances.""" + print("\n=== Example 1: List Instances ===") + + async with DefaultAzureCredential() as credential: + + async with DynamicsaxClient(CONNECTION_RUNTIME_URL, credential) as client: + items = [item async for item in client.list_data_sets()] + datasets = items + + print(f"Found {len(datasets)} instance(s).") + for dataset in datasets[:10]: + print(f" - {dataset.get('name', 'N/A')}") + + +async def example_2_list_tables(): + """Example 2: List entities (tables) for an instance.""" + print("\n=== Example 2: List Tables ===") + + if not DATASET: + print("Set DYNAMICSAX_DATASET to run this example.") + return + + async with DefaultAzureCredential() as credential: + + async with DynamicsaxClient(CONNECTION_RUNTIME_URL, credential) as client: + items = [item async for item in client.list_tables(dataset=DATASET)] + tables = items + + print(f"Found {len(tables)} table(s).") + for table in tables[:10]: + print(f" - {table.get('name', 'N/A')}") + + +async def example_3_create_record(): + """Example 3: Create a new record in an entity.""" + print("\n=== Example 3: Create Record ===") + + table = os.environ.get("DYNAMICSAX_TABLE", "") + + if not (DATASET and table): + print("Set DYNAMICSAX_DATASET and DYNAMICSAX_TABLE to run this example.") + return + + async with DefaultAzureCredential() as credential: + + async with DynamicsaxClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + record = PostItemInput() + record.additional_properties = {"Name": "SDK Sample"} + result = await client.post_item( + input=record, + dataset=DATASET, + table=table, + ) + print(f"Record created: {result}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def main(): + """Run all Dynamics AX connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: DYNAMICSAX_CONNECTION_URL environment variable is not set.") + print("Set it to your Dynamics AX connector runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_list_instances() + await example_2_list_tables() + await example_3_create_record() + + print("\n=== Dynamics AX sample completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_elfsquaddata.py b/samples/sample_connector_usage/aio/sample_connector_usage_elfsquaddata.py new file mode 100644 index 0000000..a188910 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_elfsquaddata.py @@ -0,0 +1,41 @@ +"""Elfsquad Data sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.elfsquaddata import ElfsquaddataClient + + +CONNECTION_RUNTIME_URL = os.environ.get("ELFSQUADDATA_CONNECTION_URL", "") +ENTITY_NAME = os.environ.get("ELFSQUADDATA_ENTITY_NAME", "") + + +async def main() -> None: + """List entities from an Elfsquad Data entity set.""" + if not CONNECTION_RUNTIME_URL or not ENTITY_NAME: + print( + "Set ELFSQUADDATA_CONNECTION_URL and ELFSQUADDATA_ENTITY_NAME " + "to run this sample." + ) + return + + async with DefaultAzureCredential() as credential: + try: + async with ElfsquaddataClient( + CONNECTION_RUNTIME_URL, + credential, + ) as client: + entities = [item async for item in client.list_entities( + entity_name=ENTITY_NAME, + top=10, + )] + print(f"Entities: {entities}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_etsy.py b/samples/sample_connector_usage/aio/sample_connector_usage_etsy.py new file mode 100644 index 0000000..bff6312 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_etsy.py @@ -0,0 +1,31 @@ +"""Etsy sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.etsy import EtsyClient + + +CONNECTION_RUNTIME_URL = os.environ.get("ETSY_CONNECTION_URL", "") + + +async def main() -> None: + """Ping the Etsy connector.""" + if not CONNECTION_RUNTIME_URL: + print("Set ETSY_CONNECTION_URL to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with EtsyClient(CONNECTION_RUNTIME_URL, credential) as client: + result = await client.ping() + print(f"Result: {result}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_eventbrite.py b/samples/sample_connector_usage/aio/sample_connector_usage_eventbrite.py new file mode 100644 index 0000000..70c5d47 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_eventbrite.py @@ -0,0 +1,31 @@ +"""Eventbrite sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.eventbrite import EventbriteClient + + +CONNECTION_RUNTIME_URL = os.environ.get("EVENTBRITE_CONNECTION_URL", "") + + +async def main() -> None: + """List Eventbrite event categories.""" + if not CONNECTION_RUNTIME_URL: + print("Set EVENTBRITE_CONNECTION_URL to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with EventbriteClient(CONNECTION_RUNTIME_URL, credential) as client: + categories = [item async for item in client.list_categories()] + print(f"Categories: {categories}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_eventhubs.py b/samples/sample_connector_usage/aio/sample_connector_usage_eventhubs.py new file mode 100644 index 0000000..c599825 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_eventhubs.py @@ -0,0 +1,239 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure Event Hubs sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure Event Hubs client from the Azure Connectors Python SDK +to send and receive events from Azure Event Hubs. + +Prerequisites: +1. Azure subscription with Azure Event Hubs connection +2. Event Hubs connection in Connector Namespaces (with access configured) +3. Connection runtime URL from Azure Portal +4. Azure Event Hubs namespace with an event hub + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:EVENTHUBS_CONNECTION_URL = "https://...apihub.net/apim/eventhubs/..." + $env:EVENTHUBS_HUB_NAME = "" + + python sample_connector_usage_eventhubs.py +""" + +import asyncio +import json +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.eventhubs import EventhubsClient +from azure.connectors.eventhubs import ( + SendEvent, + SendEventsInput, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/eventhubs/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "EVENTHUBS_CONNECTION_URL", + "" +) + +# Event Hub name +EVENT_HUB_NAME = os.environ.get("EVENTHUBS_HUB_NAME", "") + + +async def example_1_send_event(): + """Example 1: Send a single event to Event Hub.""" + print("\n=== Example 1: Send Single Event ===") + + if not EVENT_HUB_NAME: + print("Set EVENTHUBS_HUB_NAME environment variable.") + print("Example: $env:EVENTHUBS_HUB_NAME = 'my-event-hub'") + return + + async with DefaultAzureCredential() as credential: + + async with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Create a single event + event = SendEvent( + content_data=json.dumps({ + "message": "Hello from Azure Connectors SDK for Python!", + "timestamp": "2024-01-15T10:30:00Z", + "source": "python-sdk-sample" + }), + properties={ + "eventType": "sample", + "version": "1.0" + } + ) + + await client.send_event( + input=event, + event_hub_name=EVENT_HUB_NAME + ) + + print(f"Event sent to Event Hub '{EVENT_HUB_NAME}':") + print(f" Content: {event.content_data[:50]}...") + print(f" Properties: {event.properties}") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_send_event_with_partition_key(): + """Example 2: Send an event with a specific partition key.""" + print("\n=== Example 2: Send Event with Partition Key ===") + + if not EVENT_HUB_NAME: + print("Set EVENTHUBS_HUB_NAME environment variable.") + return + + partition_key = os.environ.get("EVENTHUBS_PARTITION_KEY", "partition-1") + async with DefaultAzureCredential() as credential: + + async with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + event = SendEvent( + content_data=json.dumps({ + "orderId": "ORD-12345", + "customerId": "CUST-001", + "amount": 99.99 + }), + properties={ + "eventType": "orderCreated" + } + ) + + await client.send_event( + input=event, + event_hub_name=EVENT_HUB_NAME, + partition_key=partition_key + ) + + print(f"Event sent with partition key '{partition_key}':") + print(f" Content: {event.content_data}") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_send_batch_events(): + """Example 3: Send multiple events in a batch.""" + print("\n=== Example 3: Send Batch Events ===") + + if not EVENT_HUB_NAME: + print("Set EVENTHUBS_HUB_NAME environment variable.") + return + + async with DefaultAzureCredential() as credential: + + async with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Create batch with multiple events + batch_input = SendEventsInput( + additional_properties={ + "events": [ + { + "contentData": json.dumps({"id": 1, "name": "Event 1"}), + "properties": {"index": "1"} + }, + { + "contentData": json.dumps({"id": 2, "name": "Event 2"}), + "properties": {"index": "2"} + }, + { + "contentData": json.dumps({"id": 3, "name": "Event 3"}), + "properties": {"index": "3"} + } + ] + } + ) + + await client.send_events( + input=batch_input, + event_hub_name=EVENT_HUB_NAME, + partition_key=os.environ.get("EVENTHUBS_PARTITION_KEY", "partition-1") + ) + + events = batch_input.additional_properties.get("events", []) + print(f"Batch of {len(events)} events sent to '{EVENT_HUB_NAME}':") + for i, evt in enumerate(events, 1): + print(f" {i}. {evt.get('contentData', 'N/A')[:40]}...") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_list_event_hubs(): + """Example 4: List Event Hubs in the namespace.""" + print("\n=== Example 4: List Event Hubs ===") + + async with DefaultAzureCredential() as credential: + + async with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_event_hubs()] + print(f"Event Hubs: {items}") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_list_consumer_groups(): + """Example 5: List consumer groups for an Event Hub.""" + print("\n=== Example 5: List Consumer Groups ===") + + if not EVENT_HUB_NAME: + print("Set EVENTHUBS_HUB_NAME environment variable.") + return + + async with DefaultAzureCredential() as credential: + + async with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_consumer_groups( + event_hub_name=EVENT_HUB_NAME + )] + print(f"Consumer groups for '{EVENT_HUB_NAME}': {items}") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + print("Azure Event Hubs sample usage for the Azure Connectors Python SDK") + print("=" * 60) + + if not CONNECTION_RUNTIME_URL: + print("\nWARNING: EVENTHUBS_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL to run actual API calls.") + print("Format: https://[region].azure-apihub.net/apim/eventhubs/[id]") + return + + await example_1_send_event() + await example_2_send_event_with_partition_key() + await example_3_send_batch_events() + await example_4_list_event_hubs() + await example_5_list_consumer_groups() + + print("\n" + "=" * 60) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_excelonline.py b/samples/sample_connector_usage/aio/sample_connector_usage_excelonline.py new file mode 100644 index 0000000..10c0cac --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_excelonline.py @@ -0,0 +1,58 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Sample usage for the Excelonline connector client.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors.aio.excelonline import ExcelonlineClient +from azure.connectors.excelonline import ( + CreateWorksheetInput, + Item, +) + + +async def main() -> None: + """Run a simple Excel Online sample flow.""" + connection_url = os.getenv("EXCELONLINE_CONNECTION_URL") + if not connection_url: + raise ValueError("Set EXCELONLINE_CONNECTION_URL environment variable") + + drive_id = os.getenv("EXCELONLINE_DRIVE_ID", "drive-id") + file_id = os.getenv("EXCELONLINE_FILE_ID", "file-id") + table_name = os.getenv("EXCELONLINE_TABLE_NAME", "Table1") + + async with DefaultAzureCredential() as credential: + async with ExcelonlineClient(connection_url, credential) as client: + worksheets = [item async for item in client.list_all_worksheets( + drive=drive_id, + file=file_id, + )] + print("worksheets", worksheets) + + tables = [item async for item in client.list_tables( + drive=drive_id, + file=file_id, + )] + print("tables", tables) + + new_sheet = await client.create_worksheet( + input=CreateWorksheetInput(name="SampleSheet"), + drive=drive_id, + file=file_id, + ) + print("created worksheet", new_sheet) + + row = await client.add_row( + input=Item(dynamic_properties={"Name": "Sample Item", "Value": 100}), + drive=drive_id, + file=file_id, + table=table_name, + ) + print("added row", row) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_excelonlinebusiness.py b/samples/sample_connector_usage/aio/sample_connector_usage_excelonlinebusiness.py new file mode 100644 index 0000000..18ba6fa --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_excelonlinebusiness.py @@ -0,0 +1,300 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Excel Online (Business) sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Excel Online Business client from the Azure Connectors Python SDK +to work with Excel files stored in SharePoint document libraries. + +Prerequisites: +1. Azure subscription with Excel Online (Business) connection +2. Excel Online connection in Connector Namespaces (with OAuth consent) +3. Connection runtime URL from Azure Portal +4. SharePoint site with Excel files containing tables + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:EXCELONLINE_CONNECTION_URL = "https://...apihub.net/apim/excelonlinebusiness/..." + $env:EXCELONLINE_DRIVE_ID = "" + $env:EXCELONLINE_FILE_ID = "" + $env:EXCELONLINE_TABLE_NAME = "" + + python sample_connector_usage_excelonlinebusiness.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.excelonlinebusiness import ExcelonlinebusinessClient +from azure.connectors.excelonlinebusiness import ( + TableToCreate, + Item, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/excelonlinebusiness/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "EXCELONLINE_CONNECTION_URL", + "" +) + +# SharePoint drive ID (document library) +DRIVE_ID = os.environ.get("EXCELONLINE_DRIVE_ID", "") + +# Excel file ID or path +FILE_ID = os.environ.get("EXCELONLINE_FILE_ID", "") + +# Table name in the Excel file +TABLE_NAME = os.environ.get("EXCELONLINE_TABLE_NAME", "") + +# SharePoint site URL (source parameter) +SOURCE_URL = os.environ.get("EXCELONLINE_SOURCE_URL", "") + + +async def example_1_list_table_rows(): + """Example 1: List rows in an Excel table.""" + print("\n=== Example 1: List Table Rows ===") + + if not DRIVE_ID or not FILE_ID or not TABLE_NAME: + print("Set environment variables to list table rows:") + print(" $env:EXCELONLINE_DRIVE_ID = ''") + print(" $env:EXCELONLINE_FILE_ID = ''") + print(" $env:EXCELONLINE_TABLE_NAME = ''") + print(" $env:EXCELONLINE_SOURCE_URL = '' (optional)") + return + + async with DefaultAzureCredential() as credential: + + async with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + rows = [item async for item in client.list_items( + drive=DRIVE_ID, + file=FILE_ID, + table=TABLE_NAME, + source=SOURCE_URL if SOURCE_URL else None, + top=10, # Limit to 10 rows + )] + + if rows: + print(f"Found {len(rows)} row(s) in table '{TABLE_NAME}':") + for i, row in enumerate(rows[:5], 1): + print(f" Row {i}: {row}") + if len(rows) > 5: + print(f" ... and {len(rows) - 5} more rows") + else: + print("No rows found or empty response.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_get_specific_row(): + """Example 2: Get a specific row by key value.""" + print("\n=== Example 2: Get Specific Row ===") + + row_id = os.environ.get("EXCELONLINE_ROW_ID", "") + id_column = os.environ.get("EXCELONLINE_ID_COLUMN", "") + + if not DRIVE_ID or not FILE_ID or not TABLE_NAME or not row_id: + print("Set environment variables to get a specific row:") + print(" $env:EXCELONLINE_DRIVE_ID = ''") + print(" $env:EXCELONLINE_FILE_ID = ''") + print(" $env:EXCELONLINE_TABLE_NAME = ''") + print(" $env:EXCELONLINE_ROW_ID = ''") + print(" $env:EXCELONLINE_ID_COLUMN = '' (optional)") + return + + async with DefaultAzureCredential() as credential: + + async with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.get_item( + drive=DRIVE_ID, + file=FILE_ID, + table=TABLE_NAME, + id=row_id, + source=SOURCE_URL if SOURCE_URL else None, + id_column=id_column if id_column else None, + ) + + if result: + print(f"Row with ID '{row_id}':") + for key, value in result.items(): + if not key.startswith("@"): + print(f" {key}: {value}") + else: + print("Row not found or empty response.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_list_workbook_comments(): + """Example 3: List comments in an Excel workbook.""" + print("\n=== Example 3: List Workbook Comments ===") + + if not DRIVE_ID or not FILE_ID: + print("Set environment variables to list comments:") + print(" $env:EXCELONLINE_DRIVE_ID = ''") + print(" $env:EXCELONLINE_FILE_ID = ''") + return + + async with DefaultAzureCredential() as credential: + + async with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_comments( + drive=DRIVE_ID, + file=FILE_ID, + source=SOURCE_URL if SOURCE_URL else None, + )] + + if items: + comments = items + print(f"Found {len(comments)} comment(s):") + for comment in comments[:5]: + comment_id = comment.get("id", "N/A") + content = comment.get("content", "N/A") + print(f" [{comment_id}]: {content[:50]}...") + if len(comments) > 5: + print(f" ... and {len(comments) - 5} more comments") + else: + print("No comments found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_create_table(): + """Example 4: Create a new table in an Excel workbook.""" + print("\n=== Example 4: Create Table ===") + + new_table_name = os.environ.get("EXCELONLINE_NEW_TABLE_NAME", "") + table_range = os.environ.get("EXCELONLINE_TABLE_RANGE", "") + column_names = os.environ.get("EXCELONLINE_COLUMN_NAMES", "") + + if not DRIVE_ID or not FILE_ID or not new_table_name: + print("Set environment variables to create a table:") + print(" $env:EXCELONLINE_DRIVE_ID = ''") + print(" $env:EXCELONLINE_FILE_ID = ''") + print(" $env:EXCELONLINE_NEW_TABLE_NAME = 'NewTable'") + print(" $env:EXCELONLINE_TABLE_RANGE = 'A1:C10' (optional)") + print(" $env:EXCELONLINE_COLUMN_NAMES = 'Name;Email;Phone' (optional)") + return + + async with DefaultAzureCredential() as credential: + + async with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + table_input = TableToCreate( + table_name=new_table_name, + range=table_range if table_range else None, + columns_names=column_names if column_names else None, + ) + + result = await client.create_table( + input=table_input, + drive=DRIVE_ID, + file=FILE_ID, + source=SOURCE_URL if SOURCE_URL else None, + ) + + if result: + print("Table created:") + print(f" Name: {result.get('name', 'N/A')}") + print(f" Title: {result.get('title', 'N/A')}") + else: + print("Table created (no response returned).") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_update_row(): + """Example 5: Update a row in an Excel table.""" + print("\n=== Example 5: Update Row ===") + + row_id = os.environ.get("EXCELONLINE_ROW_ID", "") + id_column = os.environ.get("EXCELONLINE_ID_COLUMN", "") + + if not DRIVE_ID or not FILE_ID or not TABLE_NAME or not row_id: + print("Set environment variables to update a row:") + print(" $env:EXCELONLINE_DRIVE_ID = ''") + print(" $env:EXCELONLINE_FILE_ID = ''") + print(" $env:EXCELONLINE_TABLE_NAME = ''") + print(" $env:EXCELONLINE_ROW_ID = ''") + print(" $env:EXCELONLINE_ID_COLUMN = '' (optional)") + return + + async with DefaultAzureCredential() as credential: + + async with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Create an Item with the fields to update + # The dynamic_properties dict contains column-value pairs + update_data = Item( + dynamic_properties={ + "Status": "Updated via SDK", + "LastModified": "2024-01-15", + } + ) + + result = await client.patch_item( + input=update_data, + drive=DRIVE_ID, + file=FILE_ID, + table=TABLE_NAME, + id=row_id, + source=SOURCE_URL if SOURCE_URL else None, + id_column=id_column if id_column else None, + ) + + if result: + print(f"Row '{row_id}' updated:") + for key, value in result.items(): + if not key.startswith("@"): + print(f" {key}: {value}") + else: + print("Row updated (no response returned).") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + print("Excel Online (Business) sample usage for the Azure Connectors Python SDK") + print("=" * 60) + + if not CONNECTION_RUNTIME_URL: + print("\nWARNING: EXCELONLINE_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL to run actual API calls.") + print("Format: https://[region].azure-apihub.net/apim/excelonlinebusiness/[connection-id]") + return + + await example_1_list_table_rows() + await example_2_get_specific_row() + await example_3_list_workbook_comments() + await example_4_create_table() + await example_5_update_row() + + print("\n" + "=" * 60) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_formstackforms.py b/samples/sample_connector_usage/aio/sample_connector_usage_formstackforms.py new file mode 100644 index 0000000..195f3d7 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_formstackforms.py @@ -0,0 +1,34 @@ +"""Formstack Forms sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.formstackforms import FormstackformsClient + + +CONNECTION_RUNTIME_URL = os.environ.get("FORMSTACKFORMS_CONNECTION_URL", "") + + +async def main() -> None: + """List available Formstack forms.""" + if not CONNECTION_RUNTIME_URL: + print("Set FORMSTACKFORMS_CONNECTION_URL to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with FormstackformsClient( + CONNECTION_RUNTIME_URL, + credential, + ) as client: + forms = await client.get_available_forms() + print(f"Forms: {forms}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_freshservice.py b/samples/sample_connector_usage/aio/sample_connector_usage_freshservice.py new file mode 100644 index 0000000..8a71134 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_freshservice.py @@ -0,0 +1,112 @@ +""" +Freshservice sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Freshservice client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Freshservice connection +2. Freshservice connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:FRESHSERVICE_CONNECTION_URL = "https://[region].azure-apihub.net/apim/freshservice/[id]" + + python sample_connector_usage_freshservice.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.freshservice import FreshserviceClient +from azure.connectors.freshservice import ( + AddNoteRequest, + CreateTicketRequest, + UpdateTicketRequest, +) + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/freshservice/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("FRESHSERVICE_CONNECTION_URL", "") + + +async def example_1_create_ticket() -> None: + """Example 1: Create a ticket.""" + print("\n=== Example 1: Create Ticket ===") + + async with DefaultAzureCredential() as credential: + async with FreshserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + request = CreateTicketRequest( + subject="SDK sample ticket", + description="Created from the freshservice SDK sample.", + email="requester@example.com", + priority="1", + status="2", + ) + + created = await client.create_ticket(input=request) + ticket = created.get("ticket", {}) if created else {} + print(f"Created ticket: {ticket.get('id')}") + + +async def example_2_update_ticket() -> None: + """Example 2: Update an existing ticket.""" + print("\n=== Example 2: Update Ticket ===") + + async with DefaultAzureCredential() as credential: + async with FreshserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + request = UpdateTicketRequest(priority="3", status="3") + + updated = await client.update_ticket(input=request, ticket_id=1) + ticket = updated.get("ticket", {}) if updated else {} + print(f"Updated ticket: {ticket.get('id')}") + + +async def example_3_add_note() -> None: + """Example 3: Add a note to a ticket.""" + print("\n=== Example 3: Add Note ===") + + async with DefaultAzureCredential() as credential: + async with FreshserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + request = AddNoteRequest( + body="Note added from the freshservice SDK sample.", + private=True, + ) + + note = await client.add_note(input=request, ticket_id=1) + conversation = note.get("conversation", {}) if note else {} + print(f"Added note: {conversation.get('id')}") + + +async def main() -> None: + """Run Freshservice connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: FRESHSERVICE_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Freshservice sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + # Uncomment to create, update, or annotate a ticket in Freshservice. + # await example_1_create_ticket() + # await example_2_update_ticket() + # await example_3_add_note() + print("Set the example calls in main() to run against your instance.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_ftp.py b/samples/sample_connector_usage/aio/sample_connector_usage_ftp.py new file mode 100644 index 0000000..8b5d81e --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_ftp.py @@ -0,0 +1,39 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Sample usage for the FTP connector client.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors.aio.ftp import FtpClient + + +async def main() -> None: + """Run a simple FTP sample flow.""" + connection_url = os.getenv("FTP_CONNECTION_URL") + if not connection_url: + raise ValueError("Set FTP_CONNECTION_URL environment variable") + + folder_path = os.getenv("FTP_FOLDER_PATH", "/inbound") + file_name = os.getenv("FTP_FILE_NAME", "sample-from-sdk.txt") + + async with DefaultAzureCredential() as credential: + async with FtpClient(connection_url, credential) as client: + root_listing = [item async for item in client.list_root_folder()] + print("root listing", root_listing) + + created = await client.create_file( + input=b"hello from azure-connectors ftp sample", + folder_path=folder_path, + name=file_name, + ) + print("created file", created) + + folder_items = [item async for item in client.list_folder(id=folder_path)] + print("folder items available for polling", folder_items) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_github.py b/samples/sample_connector_usage/aio/sample_connector_usage_github.py new file mode 100644 index 0000000..04c9c51 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_github.py @@ -0,0 +1,111 @@ +""" +GitHub sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the GitHub client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with GitHub connection +2. GitHub connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:GITHUB_CONNECTION_URL = "https://[region].azure-apihub.net/apim/github/[connection-id]" + + python sample_connector_usage_github.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.github import GithubClient +from azure.connectors.github import IssueBasicDetailsModel + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/github/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("GITHUB_CONNECTION_URL", "") + + +async def example_1_get_authenticated_user() -> None: + """Example 1: Get authenticated GitHub user.""" + print("\n=== Example 1: Get Authenticated User ===") + + async with DefaultAzureCredential() as credential: + async with GithubClient(CONNECTION_RUNTIME_URL, credential) as client: + user = await client.get_user() + print(f"Authenticated as: {user.get('login') if user else 'unknown'}") + + +async def example_2_list_issues(repository_owner: str, repository_name: str) -> None: + """Example 2: List open issues in a repository.""" + print("\n=== Example 2: List Issues ===") + + async with DefaultAzureCredential() as credential: + async with GithubClient(CONNECTION_RUNTIME_URL, credential) as client: + issues = [item async for item in client.list_issues( + repository_owner=repository_owner, + repository_name=repository_name, + state="open", + per_page=5, + )] + + issue_list = issues + print(f"Found {len(issue_list)} issues") + for issue in issue_list[:5]: + print(f" - #{issue.get('number')}: {issue.get('title')}") + + +async def example_3_create_issue(repository_owner: str, repository_name: str) -> None: + """Example 3: Create a new issue in a repository.""" + print("\n=== Example 3: Create Issue ===") + + async with DefaultAzureCredential() as credential: + async with GithubClient(CONNECTION_RUNTIME_URL, credential) as client: + request = IssueBasicDetailsModel( + title="SDK sample issue", + body="Created from github Python SDK sample.", + ) + created = await client.create_issue( + input=request, + repository_owner=repository_owner, + repository_name=repository_name, + ) + + print(f"Created issue: #{created.get('number') if created else 'n/a'}") + + +async def main() -> None: + """Run GitHub connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: GITHUB_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + # Update to a repository you can access with your GitHub connector auth. + repository_owner = "octocat" + repository_name = "hello-world" + + print("GitHub sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + await example_1_get_authenticated_user() + await example_2_list_issues(repository_owner, repository_name) + # Uncomment after confirming write permissions. + # await example_3_create_issue(repository_owner, repository_name) + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_googlecalendar.py b/samples/sample_connector_usage/aio/sample_connector_usage_googlecalendar.py new file mode 100644 index 0000000..da60297 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_googlecalendar.py @@ -0,0 +1,150 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Google Calendar sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Google Calendar client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Google Calendar connection +2. Google Calendar connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:GOOGLECALENDAR_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/googlecalendar/[connection-id]" + ) + + python sample_connector_usage_googlecalendar.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.googlecalendar import GooglecalendarClient +from azure.connectors.googlecalendar import ( + RequestEvent, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/googlecalendar/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "GOOGLECALENDAR_CONNECTION_URL", + "", +) + + +async def example_1_list_calendars(): + """Example 1: List calendars visible to the connection account.""" + print("\n=== Example 1: List Calendars ===") + + async with DefaultAzureCredential() as credential: + + async with GooglecalendarClient(CONNECTION_RUNTIME_URL, credential) as client: + items = [item async for item in client.list_calendars(min_access_role="reader")] + + print(f"Found {len(items)} calendar(s).") + for calendar in items[:10]: + print(f" - {calendar.get('summary', 'N/A')} ({calendar.get('id', 'N/A')})") + + +async def example_2_list_events(): + """Example 2: List events for a configured calendar.""" + print("\n=== Example 2: List Events ===") + + calendar_id = os.environ.get("GOOGLECALENDAR_TEST_CALENDAR_ID", "") + if not calendar_id: + print("Set GOOGLECALENDAR_TEST_CALENDAR_ID to run this example.") + return + + async with DefaultAzureCredential() as credential: + + async with GooglecalendarClient(CONNECTION_RUNTIME_URL, credential) as client: + items = [item async for item in client.list_events(calendar_id=calendar_id)] + + events = items + print(f"Found {len(events)} event(s) in calendar '{calendar_id}'.") + for event in events[:10]: + print(f" - {event.get('summary', 'N/A')} ({event.get('id', 'N/A')})") + + +async def example_3_create_event(): + """Example 3: Create a test event in the configured calendar.""" + print("\n=== Example 3: Create Event ===") + + calendar_id = os.environ.get("GOOGLECALENDAR_TEST_CALENDAR_ID", "") + if not calendar_id: + print("Set GOOGLECALENDAR_TEST_CALENDAR_ID to run this example.") + return + + async with DefaultAzureCredential() as credential: + + async with GooglecalendarClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + payload = RequestEvent( + summary="SDK Sample Event", + start="2026-07-09T15:00:00Z", + end="2026-07-09T15:30:00Z", + description="Created by azure-connectors sample.", + location="Online", + status="confirmed", + ) + + created = await client.create_event(input=payload, calendar_id=calendar_id) + if created: + print(f"Created event id: {created.get('id', 'N/A')}") + else: + print("Create completed with no response body.") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def example_4_list_events_for_polling(): + """Example 4: List events in a time window for polling logic.""" + print("\n=== Example 4: List Events for Polling ===") + + calendar_id = os.environ.get("GOOGLECALENDAR_TEST_CALENDAR_ID", "") + if not calendar_id: + print("Set GOOGLECALENDAR_TEST_CALENDAR_ID to run this example.") + return + + async with DefaultAzureCredential() as credential: + + async with GooglecalendarClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_events( + calendar_id=calendar_id, + time_min="2026-07-09T00:00:00Z", + time_max="2026-07-10T00:00:00Z", + )] + print(f"Time-window query returned {len(items)} event(s).") + print("Persist event IDs and update times to implement change polling.") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def main(): + """Run all Google Calendar connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: GOOGLECALENDAR_CONNECTION_URL environment variable is not set.") + print("Set it to your Google Calendar connector runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_list_calendars() + await example_2_list_events() + await example_3_create_event() + await example_4_list_events_for_polling() + + print("\n=== Google Calendar sample completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_googledrive.py b/samples/sample_connector_usage/aio/sample_connector_usage_googledrive.py new file mode 100644 index 0000000..ef2341e --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_googledrive.py @@ -0,0 +1,151 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Google Drive sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Google Drive client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Google Drive connection +2. Google Drive connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:GOOGLEDRIVE_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/googledrive/[connection-id]" + ) + + python sample_connector_usage_googledrive.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.googledrive import GoogledriveClient + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/googledrive/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "GOOGLEDRIVE_CONNECTION_URL", + "", +) + + +async def example_1_list_root_folder(): + """Example 1: List items in the root folder.""" + print("\n=== Example 1: List Root Folder ===") + + async with DefaultAzureCredential() as credential: + + async with GoogledriveClient(CONNECTION_RUNTIME_URL, credential) as client: + items = [item async for item in client.list_root_folder()] + + if items: + print(f"Found {len(items)} items in root folder:") + for item in items[:10]: + icon = "[DIR]" if item.get("IsFolder") else "[FILE]" + print(f" {icon} {item.get('Name', 'N/A')}") + else: + print("No root-folder items returned.") + + +async def example_2_get_file_metadata_by_path(): + """Example 2: Retrieve file metadata by path.""" + print("\n=== Example 2: Get Metadata by Path ===") + + file_path = os.environ.get("GOOGLEDRIVE_TEST_FILE_PATH", "") + if not file_path: + print("Set GOOGLEDRIVE_TEST_FILE_PATH, for example '/Documents/report.pdf'.") + return + + async with DefaultAzureCredential() as credential: + + async with GoogledriveClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + metadata = await client.get_file_metadata_by_path(path=file_path) + + if metadata: + print(f"Name: {metadata.get('Name', 'N/A')}") + print(f"Size: {metadata.get('Size', 'N/A')} bytes") + print(f"LastModified: {metadata.get('LastModified', 'N/A')}") + else: + print("No metadata returned.") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def example_3_create_file(): + """Example 3: Upload a text file.""" + print("\n=== Example 3: Create File ===") + + destination_folder = os.environ.get("GOOGLEDRIVE_TEST_DEST_FOLDER", "/Documents") + destination_name = os.environ.get("GOOGLEDRIVE_TEST_FILE_NAME", "sdk-sample.txt") + + async with DefaultAzureCredential() as credential: + + async with GoogledriveClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.create_file( + input=b"Hello from azure-connectors Google Drive sample!", + folder_id=destination_folder, + name=destination_name, + ) + + if result: + print(f"Created file id: {result.get('Id', 'N/A')}") + else: + print("Create operation completed with no response body.") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def example_4_list_drive_items_for_sheet_selection(): + """Example 4: List Drive items to locate a Google Sheet file.""" + print("\n=== Example 4: Find Google Sheet Files ===") + + folder_id = os.environ.get("GOOGLEDRIVE_TEST_SHEET_FOLDER", "") + if not folder_id: + print("Set GOOGLEDRIVE_TEST_SHEET_FOLDER to a Drive folder id.") + return + + async with DefaultAzureCredential() as credential: + + async with GoogledriveClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_folder(id=folder_id)] + + if items: + print(f"Found {len(items)} Drive item(s):") + for item in items: + print(f" - {item.get('Name', 'N/A')}") + else: + print("No Drive items returned.") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def main(): + """Run all Google Drive connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: GOOGLEDRIVE_CONNECTION_URL environment variable is not set.") + print("Set it to your Google Drive connector runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_list_root_folder() + await example_2_get_file_metadata_by_path() + await example_3_create_file() + await example_4_list_drive_items_for_sheet_selection() + + print("\n=== Google Drive sample completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_googletasks.py b/samples/sample_connector_usage/aio/sample_connector_usage_googletasks.py new file mode 100644 index 0000000..6bbbf9c --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_googletasks.py @@ -0,0 +1,117 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Google Tasks sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Google Tasks client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Google Tasks connection +2. Google Tasks connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:GOOGLETASKS_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/googletasks/[connection-id]" + ) + + python sample_connector_usage_googletasks.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.googletasks import GoogletasksClient +from azure.connectors.googletasks import ( + TRIGGER_OPERATIONS, + TaskCreate, + TaskListCreate, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/googletasks/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "GOOGLETASKS_CONNECTION_URL", + "", +) + + +async def example_1_list_task_lists(): + """Example 1: List task lists.""" + print("\n=== Example 1: List Task Lists ===") + + async with DefaultAzureCredential() as credential: + + async with GoogletasksClient(CONNECTION_RUNTIME_URL, credential) as client: + items = [item async for item in client.list_task_lists()] + + print(f"Found {len(items)} task list(s).") + for task_list in items[:10]: + print(f" - {task_list.get('title', 'N/A')} ({task_list.get('id', 'N/A')})") + + +async def example_2_create_task_list_and_task(): + """Example 2: Create a task list and task.""" + print("\n=== Example 2: Create Task List and Task ===") + + async with DefaultAzureCredential() as credential: + + async with GoogletasksClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + list_result = await client.create_task_list( + input=TaskListCreate(title="SDK Sample List"), + ) + task_list_id = list_result.get("id") if list_result else None + + if not task_list_id: + print("Task list creation returned no id.") + return + + task_result = await client.create_task( + input=TaskCreate( + title="Follow up sample", + notes="Created by azure-connectors sample.", + due="2026-07-10T12:00:00Z", + ), + task_list_id=task_list_id, + ) + + print(f"Created list id: {task_list_id}") + print(f"Created task id: {(task_result or {}).get('id', 'N/A')}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +def example_3_list_triggers(): + """Example 3: List trigger operations available for registration.""" + print("\n=== Example 3: Trigger Operations ===") + + for operation_id, metadata in TRIGGER_OPERATIONS.items(): + parameters = ", ".join(metadata["required_parameters"]) or "none" + print(f"{operation_id}: required parameters: {parameters}") + + +async def main(): + """Run all Google Tasks connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: GOOGLETASKS_CONNECTION_URL environment variable is not set.") + print("Set it to your Google Tasks connector runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_list_task_lists() + await example_2_create_task_list_and_task() + example_3_list_triggers() + + print("\n=== Google Tasks sample completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_impexium.py b/samples/sample_connector_usage/aio/sample_connector_usage_impexium.py new file mode 100644 index 0000000..3414e25 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_impexium.py @@ -0,0 +1,34 @@ +"""Impexium sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.impexium import ImpexiumClient + + +CONNECTION_RUNTIME_URL = os.environ.get("IMPEXIUM_CONNECTION_URL", "") + + +async def main() -> None: + """List countries from Impexium.""" + if not CONNECTION_RUNTIME_URL: + print("Set IMPEXIUM_CONNECTION_URL to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with ImpexiumClient(CONNECTION_RUNTIME_URL, credential) as client: + countries = [ + country + async for country in client.list_all_countries(page_number=1) + ] + print(f"Countries: {countries}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_infusionsoft.py b/samples/sample_connector_usage/aio/sample_connector_usage_infusionsoft.py new file mode 100644 index 0000000..9608531 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_infusionsoft.py @@ -0,0 +1,104 @@ +""" +Infusionsoft (Keap) sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Infusionsoft client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Infusionsoft connection +2. Infusionsoft connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:INFUSIONSOFT_CONNECTION_URL = "https://[region].azure-apihub.net/apim/infusionsoft/[id]" + + python sample_connector_usage_infusionsoft.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.infusionsoft import InfusionsoftClient +from azure.connectors.infusionsoft import CreateTaskRequest + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/infusionsoft/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("INFUSIONSOFT_CONNECTION_URL", "") + + +async def example_1_list_tasks() -> None: + """Example 1: List tasks ordered by due date.""" + print("\n=== Example 1: List Tasks ===") + + async with DefaultAzureCredential() as credential: + async with InfusionsoftClient(CONNECTION_RUNTIME_URL, credential) as client: + response = [item async for item in client.list_tasks()] + tasks = response + + print(f"Found {len(tasks)} tasks") + for task in tasks[:5]: + print(f" - {task.get('id')}: {task.get('title')}") + + +async def example_2_create_task() -> None: + """Example 2: Create a task.""" + print("\n=== Example 2: Create Task ===") + + async with DefaultAzureCredential() as credential: + async with InfusionsoftClient(CONNECTION_RUNTIME_URL, credential) as client: + request = CreateTaskRequest( + title="SDK sample task", + description="Created from the infusionsoft SDK sample.", + priority=1, + ) + + created = await client.create_task(input=request) + print(f"Created task: {created.get('id') if created else 'n/a'}") + + +async def example_3_update_task() -> None: + """Example 3: Update an existing task.""" + print("\n=== Example 3: Update Task ===") + + async with DefaultAzureCredential() as credential: + async with InfusionsoftClient(CONNECTION_RUNTIME_URL, credential) as client: + request = CreateTaskRequest( + title="Updated SDK sample task", + description="Updated from the infusionsoft SDK sample.", + ) + + updated = await client.update_task(input=request, id=1) + print(f"Updated task: {updated.get('id') if updated else 'n/a'}") + + +async def main() -> None: + """Run Infusionsoft connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: INFUSIONSOFT_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Infusionsoft (Keap) sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + await example_1_list_tasks() + # Uncomment to create or update a task in your Infusionsoft instance. + # await example_2_create_task() + # await example_3_update_task() + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_insightly.py b/samples/sample_connector_usage/aio/sample_connector_usage_insightly.py new file mode 100644 index 0000000..cdd1c5c --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_insightly.py @@ -0,0 +1,107 @@ +""" +Insightly sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Insightly client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Insightly connection +2. Insightly connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:INSIGHTLY_CONNECTION_URL = "https://[region].azure-apihub.net/apim/insightly/[conn-id]" + + python sample_connector_usage_insightly.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.insightly import InsightlyClient +from azure.connectors.insightly import TaskRequest + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/insightly/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("INSIGHTLY_CONNECTION_URL", "") + + +async def example_1_list_tasks() -> None: + """Example 1: List tasks.""" + print("\n=== Example 1: List Tasks ===") + + async with DefaultAzureCredential() as credential: + async with InsightlyClient(CONNECTION_RUNTIME_URL, credential) as client: + response = [item async for item in client.list_tasks()] + tasks = response + + print(f"Found {len(tasks)} tasks") + for task in tasks[:5]: + print(f" - {task.get('TASK_ID')}: {task.get('TITLE')}") + + +async def example_2_list_contacts() -> None: + """Example 2: List contacts.""" + print("\n=== Example 2: List Contacts ===") + + async with DefaultAzureCredential() as credential: + async with InsightlyClient(CONNECTION_RUNTIME_URL, credential) as client: + response = [item async for item in client.list_contacts()] + contacts = response + + print(f"Found {len(contacts)} contacts") + for contact in contacts[:5]: + first = contact.get("FIRST_NAME", "") + last = contact.get("LAST_NAME", "") + print(f" - {contact.get('CONTACT_ID')}: {first} {last}".rstrip()) + + +async def example_3_add_task() -> None: + """Example 3: Add a task.""" + print("\n=== Example 3: Add Task ===") + + async with DefaultAzureCredential() as credential: + async with InsightlyClient(CONNECTION_RUNTIME_URL, credential) as client: + request = TaskRequest( + t_i_t_l_e="SDK sample task", + d_e_t_a_i_l_s="Created from insightly SDK sample.", + s_t_a_t_u_s="NOT STARTED", + c_o_m_p_l_e_t_e_d=False, + p_u_b_l_i_c_l_y_v_i_s_i_b_l_e=False, + ) + + created = await client.add_task(input=request) + print(f"Created task: {created.get('TASK_ID') if created else 'n/a'}") + + +async def main() -> None: + """Run Insightly connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: INSIGHTLY_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Insightly sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + await example_1_list_tasks() + await example_2_list_contacts() + # Uncomment to create a task in your Insightly instance. + # await example_3_add_task() + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_jedoxodatahub.py b/samples/sample_connector_usage/aio/sample_connector_usage_jedoxodatahub.py new file mode 100644 index 0000000..7b1612e --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_jedoxodatahub.py @@ -0,0 +1,34 @@ +"""Jedox OData Hub sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.jedoxodatahub import JedoxodatahubClient + + +CONNECTION_RUNTIME_URL = os.environ.get("JEDOXODATAHUB_CONNECTION_URL", "") + + +async def main() -> None: + """List Jedox databases.""" + if not CONNECTION_RUNTIME_URL: + print("Set JEDOXODATAHUB_CONNECTION_URL to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with JedoxodatahubClient( + CONNECTION_RUNTIME_URL, + credential, + ) as client: + databases = [item async for item in client.list_databases()] + print(f"Databases: {databases}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_jira.py b/samples/sample_connector_usage/aio/sample_connector_usage_jira.py new file mode 100644 index 0000000..4fa8426 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_jira.py @@ -0,0 +1,136 @@ +""" +Jira sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Jira client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Jira connection +2. Jira connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:JIRA_CONNECTION_URL = "https://[region].azure-apihub.net/apim/jira/[connection-id]" + + python sample_connector_usage_jira.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.jira import JiraClient +from azure.connectors.jira import CreateIssueInput + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/jira/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("JIRA_CONNECTION_URL", "") + + +async def example_1_list_resources() -> list[dict]: + """Example 1: List accessible Jira cloud resources.""" + print("\n=== Example 1: List Resources ===") + + async with DefaultAzureCredential() as credential: + async with JiraClient(CONNECTION_RUNTIME_URL, credential) as client: + resources_response = [item async for item in client.list_resources()] + resources = resources_response + + print(f"Found {len(resources)} resources") + for resource in resources[:5]: + print(f" - {resource.get('name')} ({resource.get('id')})") + + return resources + + +async def example_2_list_issues(cloud_id: str) -> None: + """Example 2: List issues in a Jira site.""" + print("\n=== Example 2: List Issues ===") + + async with DefaultAzureCredential() as credential: + async with JiraClient(CONNECTION_RUNTIME_URL, credential) as client: + del cloud_id + + issues_response = [item async for item in client.list_issues()] + + issues = issues_response + print(f"Found {len(issues)} issues") + for issue in issues[:5]: + print(f" - {issue.get('key')}: {issue.get('fields', {}).get('summary')}") + + +async def example_3_create_issue(cloud_id: str) -> None: + """Example 3: Create an issue (requires valid project + issue type).""" + print("\n=== Example 3: Create Issue ===") + + async with DefaultAzureCredential() as credential: + async with JiraClient(CONNECTION_RUNTIME_URL, credential) as client: + del cloud_id + + request = CreateIssueInput( + additional_properties={ + "fields": { + "project": {"key": "PROJ"}, + "summary": "SDK sample issue", + "issuetype": {"name": "Task"}, + "description": { + "type": "doc", + "version": 1, + "content": [{ + "type": "paragraph", + "content": [{ + "type": "text", + "text": "Created from jira SDK sample.", + }], + }], + }, + } + } + ) + + created = await client.create_issue( + input=request, + project_key="PROJ", + issue_type_ids="10001", + ) + print(f"Created issue: {created.get('key') if created else 'n/a'}") + + +async def main() -> None: + """Run Jira connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: JIRA_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Jira sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + resources = await example_1_list_resources() + + if resources: + cloud_id = resources[0].get("id") + if cloud_id: + await example_2_list_issues(cloud_id) + # Uncomment after setting valid project/issuetype in example_3_create_issue. + # await example_3_create_issue(cloud_id) + else: + print("No cloud id found in first resource; skipping issue examples.") + else: + print("No resources returned; skipping issue examples.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_keyvault.py b/samples/sample_connector_usage/aio/sample_connector_usage_keyvault.py new file mode 100644 index 0000000..bf9d688 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_keyvault.py @@ -0,0 +1,241 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure Key Vault sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure Key Vault client from the Azure Connectors Python SDK to +manage keys and secrets. + +Prerequisites: +1. Azure subscription with Azure Key Vault connection +2. Key Vault connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:KEYVAULT_CONNECTION_URL = "https://[region].azure-apihub.net/apim/keyvault/[connection-id]" + + python sample_connector_usage_keyvault.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.keyvault import KeyvaultClient +from azure.connectors.keyvault import ( + KeyEncryptInput, + KeyDecryptInput, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/keyvault/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "KEYVAULT_CONNECTION_URL", + "" +) + +# Sample key and secret names (replace with your own) +KEY_NAME = os.environ.get("KEYVAULT_KEY_NAME", "my-encryption-key") +SECRET_NAME = os.environ.get("KEYVAULT_SECRET_NAME", "my-secret") + + +async def example_1_list_keys(): + """Example 1: List all keys in the vault.""" + print("\n=== Example 1: List Keys ===") + + async with DefaultAzureCredential() as credential: + + async with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + keys = [key async for key in client.list_keys()] + + if keys: + print(f"Found {len(keys)} keys:") + for key in keys: + print(f" - {key.get('name')} (enabled: {key.get('is_enabled')})") + else: + print("No keys found") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_get_key_metadata(): + """Example 2: Get metadata for a specific key.""" + print("\n=== Example 2: Get Key Metadata ===") + + async with DefaultAzureCredential() as credential: + + async with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.get_key_metadata(key_name=KEY_NAME) + + if result: + print(f"Key Name: {result.get('name')}") + print(f"Version: {result.get('version')}") + print(f"Key Type: {result.get('key_type')}") + print(f"Enabled: {result.get('is_enabled')}") + print(f"Created: {result.get('created_time')}") + if result.get('allowed_operations'): + print(f"Allowed Operations: {', '.join(result['allowed_operations'])}") + else: + print(f"Key '{KEY_NAME}' not found") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_encrypt_decrypt(): + """Example 3: Encrypt and decrypt data using a key.""" + print("\n=== Example 3: Encrypt and Decrypt Data ===") + + async with DefaultAzureCredential() as credential: + + async with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Encrypt data + plaintext = "Hello, Azure Key Vault!" + print(f"Original text: {plaintext}") + + encrypt_input = KeyEncryptInput( + algorithm="RSA-OAEP", + raw_data=plaintext + ) + encrypt_result = await client.encrypt_data( + input=encrypt_input, + key_name=KEY_NAME + ) + + if encrypt_result: + encrypted = encrypt_result.get("encrypted_data") + print(f"Encrypted: {encrypted[:50]}..." if encrypted else "No result") + + # Decrypt data + decrypt_input = KeyDecryptInput( + algorithm="RSA-OAEP", + encrypted_data=encrypted + ) + decrypt_result = await client.decrypt_data( + input=decrypt_input, + key_name=KEY_NAME + ) + + if decrypt_result: + decrypted = decrypt_result.get("raw_data") + print(f"Decrypted: {decrypted}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_list_secrets(): + """Example 4: List all secrets in the vault.""" + print("\n=== Example 4: List Secrets ===") + + async with DefaultAzureCredential() as credential: + + async with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + secrets = [secret async for secret in client.list_secrets()] + + if secrets: + print(f"Found {len(secrets)} secrets:") + for _ in secrets: + print(" - [REDACTED]") + else: + print("No secrets found") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_get_secret(): + """Example 5: Get a secret value.""" + print("\n=== Example 5: Get Secret ===") + + async with DefaultAzureCredential() as credential: + + async with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.get_secret(secret_name=SECRET_NAME) + + if result: + print(f"Secret Name: {result.get('name')}") + print(f"Content Type: {result.get('content_type')}") + # Note: Be careful with secret values in logs + value = result.get("value", "") + masked = value[:3] + "***" if len(value) > 3 else "***" + print(f"Value (masked): {masked}") + else: + print("Secret not found") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_6_get_secret_metadata(): + """Example 6: Get secret metadata without the value.""" + print("\n=== Example 6: Get Secret Metadata ===") + + async with DefaultAzureCredential() as credential: + + async with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.get_secret_metadata( + secret_name=SECRET_NAME + ) + + if result: + print(f"Secret Name: {result.get('name')}") + print(f"Version: {result.get('version')}") + print(f"Content Type: {result.get('content_type')}") + print(f"Enabled: {result.get('is_enabled')}") + print(f"Created: {result.get('created_time')}") + print(f"Updated: {result.get('last_updated_time')}") + else: + print("Secret not found") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: KEYVAULT_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + # Run read-only examples by default + await example_1_list_keys() + await example_2_get_key_metadata() + await example_4_list_secrets() + await example_5_get_secret() + await example_6_get_secret_metadata() + + # Uncomment to run encryption/decryption example: + # await example_3_encrypt_decrypt() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_kusto.py b/samples/sample_connector_usage/aio/sample_connector_usage_kusto.py new file mode 100644 index 0000000..315ce4f --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_kusto.py @@ -0,0 +1,393 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Kusto (Azure Data Explorer) sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Kusto client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Kusto (Azure Data Explorer) cluster +2. Kusto connection in Connector Namespaces +3. Connection runtime URL from Azure Portal +4. Kusto cluster URL and database name + +Installation: + pip install azure-workflows-connectors-sdk + +Usage: + Set environment variables: + $env:KUSTO_CONNECTION_URL = "https://[region].azure-apihub.net/apim/kusto/[connection-id]" + $env:KUSTO_CLUSTER_URL = "https://[cluster-name].[region].kusto.windows.net" + $env:KUSTO_DATABASE = "[database-name]" + + python sample_connector_usage_kusto.py +""" + +import asyncio +import os + +try: + from azure.identity.aio import DefaultAzureCredential + from azure.connectors import ConnectorException + from azure.connectors.aio.kusto import KustoClient + from azure.connectors.kusto import ( + QueryAndListSchema, + ControlCommandAndListSchema, + QueryAndVisualizeSchema, + ) + IMPORTS_AVAILABLE = True +except ImportError as import_error: + IMPORTS_AVAILABLE = False + IMPORT_ERROR = str(import_error) + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/kusto/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "KUSTO_CONNECTION_URL", + "" +) + +# Kusto cluster URL format: +# https://[cluster-name].[region].kusto.windows.net +KUSTO_CLUSTER_URL = os.environ.get( + "KUSTO_CLUSTER_URL", + "https://help.kusto.windows.net" +) + +KUSTO_DATABASE = os.environ.get( + "KUSTO_DATABASE", + "Samples" +) + +KUSTO_TABLE = os.environ.get( + "KUSTO_TABLE", + "StormEvents" +) + + +async def example_1_simple_kql_query(): + """Example 1: Run a simple KQL query.""" + print("\n=== Example 1: Simple KQL Query ===") + + async with DefaultAzureCredential() as credential: + + async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + query = f"{KUSTO_TABLE} | take 5" + + query_request = QueryAndListSchema( + cluster=KUSTO_CLUSTER_URL, + db=KUSTO_DATABASE, + csl=query, + ) + + poller = await client.begin_list_kusto_results(input=query_request) + results = await poller.result() + + if results and 'value' in results: + print(f"Query executed successfully. Found {len(results['value'])} rows:") + for i, row in enumerate(results['value'][:5], 1): + print(f" Row {i}: {row}") + else: + print("Query executed but returned no data.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_aggregation_query(): + """Example 2: Run a KQL query with aggregation.""" + print("\n=== Example 2: Aggregation Query ===") + + async with DefaultAzureCredential() as credential: + + async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + query = f""" + {KUSTO_TABLE} + | summarize EventCount = count() by State + | top 5 by EventCount desc + """ + + query_request = QueryAndListSchema( + cluster=KUSTO_CLUSTER_URL, + db=KUSTO_DATABASE, + csl=query, + ) + + poller = await client.begin_list_kusto_results(input=query_request) + results = await poller.result() + + if results and 'value' in results: + print("Top 5 states by event count:") + for row in results['value']: + state = row.get('State', 'Unknown') + count = row.get('EventCount', 0) + print(f" {state}: {count} events") + else: + print("Query returned no results.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_time_based_filtering(): + """Example 3: Query with time-based filtering.""" + print("\n=== Example 3: Time-Based Filtering ===") + + async with DefaultAzureCredential() as credential: + + async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + query = f""" + {KUSTO_TABLE} + | where StartTime > ago(365d) + | summarize count() by EventType + | order by count_ desc + | take 5 + """ + + query_request = QueryAndListSchema( + cluster=KUSTO_CLUSTER_URL, + db=KUSTO_DATABASE, + csl=query, + ) + + poller = await client.begin_list_kusto_results(input=query_request) + results = await poller.result() + + if results and 'value' in results: + print("Top 5 event types in the last year:") + for row in results['value']: + event_type = row.get('EventType', 'Unknown') + count = row.get('count_', 0) + print(f" {event_type}: {count} events") + else: + print("Query returned no results.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_visualize_results(): + """Example 4: Query and visualize results as a chart.""" + print("\n=== Example 4: Visualize Query Results ===") + + async with DefaultAzureCredential() as credential: + + async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + query = f""" + {KUSTO_TABLE} + | summarize EventCount = count() by bin(StartTime, 30d) + | order by StartTime asc + """ + + visualize_request = QueryAndVisualizeSchema( + cluster=KUSTO_CLUSTER_URL, + db=KUSTO_DATABASE, + csl=query, + chart_type="Time Chart", + ) + + poller = await client.begin_run_kusto_query_and_visualize_results( + input=visualize_request + ) + chart = await poller.result() + + if chart: + print("Chart data generated successfully") + if isinstance(chart, dict): + if 'value' in chart: + print(f" Data points: {len(chart['value'])}") + print(" Chart type: timechart") + else: + print(" Chart object returned") + else: + print("Visualization completed but no chart data returned.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_control_command(): + """Example 5: Run a control command to show database schema.""" + print("\n=== Example 5: Control Command (Show Tables) ===") + + async with DefaultAzureCredential() as credential: + + async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + command = ".show tables" + + command_request = ControlCommandAndListSchema( + cluster=KUSTO_CLUSTER_URL, + db=KUSTO_DATABASE, + csl=command, + ) + + poller = await client.begin_list_kusto_show_command_results( + input=command_request + ) + results = await poller.result() + + if results and 'value' in results: + print(f"Found {len(results['value'])} tables in database '{KUSTO_DATABASE}':") + for row in results['value'][:10]: + table_name = row.get('TableName', 'Unknown') + folder = row.get('Folder', '') + print(f" - {table_name}" + (f" (Folder: {folder})" if folder else "")) + else: + print("Command executed but returned no results.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_6_table_schema(): + """Example 6: Get schema information for a specific table.""" + print("\n=== Example 6: Show Table Schema ===") + + async with DefaultAzureCredential() as credential: + + async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + command = f".show table {KUSTO_TABLE} schema as json" + + command_request = ControlCommandAndListSchema( + cluster=KUSTO_CLUSTER_URL, + db=KUSTO_DATABASE, + csl=command, + ) + + poller = await client.begin_list_kusto_show_command_results( + input=command_request + ) + results = await poller.result() + + if results and 'value' in results and len(results['value']) > 0: + print(f"Schema for table '{KUSTO_TABLE}':") + schema_row = results['value'][0] + if 'Schema' in schema_row: + import json + schema_json = json.loads(schema_row['Schema']) + if 'OrderedColumns' in schema_json: + for col in schema_json['OrderedColumns'][:10]: + col_name = col.get('Name', 'Unknown') + col_type = col.get('Type', 'Unknown') + print(f" - {col_name}: {col_type}") + else: + print(f" Schema data: {schema_row}") + else: + print("Command executed but returned no schema.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_7_statistical_analysis(): + """Example 7: Statistical analysis with percentiles.""" + print("\n=== Example 7: Statistical Analysis ===") + + async with DefaultAzureCredential() as credential: + + async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + query = f""" + {KUSTO_TABLE} + | where isnotnull(DamageProperty) + | summarize + p50 = percentile(DamageProperty, 50), + p95 = percentile(DamageProperty, 95), + p99 = percentile(DamageProperty, 99), + max = max(DamageProperty) + """ + + query_request = QueryAndListSchema( + cluster=KUSTO_CLUSTER_URL, + db=KUSTO_DATABASE, + csl=query, + ) + + poller = await client.begin_list_kusto_results(input=query_request) + results = await poller.result() + + if results and 'value' in results and len(results['value']) > 0: + stats = results['value'][0] + print("Property damage statistics:") + print(f" 50th percentile (median): ${stats.get('p50', 0):,.2f}") + print(f" 95th percentile: ${stats.get('p95', 0):,.2f}") + print(f" 99th percentile: ${stats.get('p99', 0):,.2f}") + print(f" Maximum: ${stats.get('max', 0):,.2f}") + else: + print("Query returned no statistics.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_8_error_handling(): + """Example 8: Demonstrate error handling with invalid query.""" + print("\n=== Example 8: Error Handling ===") + + async with DefaultAzureCredential() as credential: + + async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Intentionally use an invalid table name + query = "NonExistentTable | take 10" + + query_request = QueryAndListSchema( + cluster=KUSTO_CLUSTER_URL, + db=KUSTO_DATABASE, + csl=query, + ) + + poller = await client.begin_list_kusto_results(input=query_request) + results = await poller.result() + print(f"Unexpected success: {results}") + + except ConnectorException as ex: + print("Expected error caught:") + print(f" Message: {ex}") + except Exception as ex: + print(f"Unexpected error type: {type(ex).__name__}") + print(f" Message: {ex}") + + +async def main(): + """Run all examples.""" + print("Kusto (Azure Data Explorer) sample usage for the Azure Connectors Python SDK") + print("=" * 60) + print() + + await example_1_simple_kql_query() + await example_2_aggregation_query() + await example_3_time_based_filtering() + await example_4_visualize_results() + await example_5_control_command() + await example_6_table_schema() + await example_7_statistical_analysis() + await example_8_error_handling() + + print("\n" + "=" * 60) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_mailchimp.py b/samples/sample_connector_usage/aio/sample_connector_usage_mailchimp.py new file mode 100644 index 0000000..f145b3e --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_mailchimp.py @@ -0,0 +1,133 @@ +""" +Mailchimp sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Mailchimp client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a Mailchimp connection +2. Mailchimp connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:MAILCHIMP_CONNECTION_URL = "https://[region].azure-apihub.net/apim/mailchimp/[id]" + + python sample_connector_usage_mailchimp.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.mailchimp import MailchimpClient +from azure.connectors.mailchimp import ( + CampaignDefaults, + Contact, + NewListRequest, + NewMemberInListRequest, +) + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/mailchimp/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("MAILCHIMP_CONNECTION_URL", "") + + +async def example_1_list_campaigns() -> None: + """Example 1: List campaigns in the account.""" + print("\n=== Example 1: List Campaigns ===") + + async with DefaultAzureCredential() as credential: + async with MailchimpClient(CONNECTION_RUNTIME_URL, credential) as client: + campaigns = [item async for item in client.list_campaigns()] + print(f"Campaigns: {campaigns}") + + +async def example_2_get_lists() -> None: + """Example 2: Get all audience lists.""" + print("\n=== Example 2: Get Lists ===") + + async with DefaultAzureCredential() as credential: + async with MailchimpClient(CONNECTION_RUNTIME_URL, credential) as client: + lists = await client.get_lists(count=10, offset=0) + print(f"Lists: {lists}") + + +async def example_3_new_list() -> None: + """Example 3: Create a new audience list.""" + print("\n=== Example 3: New List ===") + + async with DefaultAzureCredential() as credential: + async with MailchimpClient(CONNECTION_RUNTIME_URL, credential) as client: + new_list = await client.newlist( + input=NewListRequest( + name="SDK sample list", + permission_reminder="You signed up via the SDK sample.", + contact=Contact( + company="Contoso", + address1="1 Microsoft Way", + city="Redmond", + state="WA", + zip="98052", + country="US", + phone="425-555-0100", + ), + campaign_defaults=CampaignDefaults( + from_name="SDK Sample", + from_email="sample@example.com", + subject="Welcome", + language="en", + ), + email_type_option=True, + ), + ) + print(f"Created list: {new_list}") + + +async def example_4_add_member() -> None: + """Example 4: Add a member to an audience list.""" + print("\n=== Example 4: Add Member ===") + + async with DefaultAzureCredential() as credential: + async with MailchimpClient(CONNECTION_RUNTIME_URL, credential) as client: + member = await client.addmember( + input=NewMemberInListRequest( + email_address="sample.user@example.com", + status="subscribed", + ), + list_id="123456", + ) + print(f"Added member: {member}") + + +async def main() -> None: + """Run Mailchimp connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: MAILCHIMP_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Mailchimp sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + # Uncomment to list campaigns/lists, create lists, or add members. + # await example_1_list_campaigns() + # await example_2_get_lists() + # await example_3_new_list() + # await example_4_add_member() + print("Set the example calls in main() to run against your instance.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_meetingroommap.py b/samples/sample_connector_usage/aio/sample_connector_usage_meetingroommap.py new file mode 100644 index 0000000..5c80d46 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_meetingroommap.py @@ -0,0 +1,34 @@ +"""Meeting Room Map sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.meetingroommap import MeetingroommapClient + + +CONNECTION_RUNTIME_URL = os.environ.get("MEETINGROOMMAP_CONNECTION_URL", "") + + +async def main() -> None: + """List Meeting Room Map location categories.""" + if not CONNECTION_RUNTIME_URL: + print("Set MEETINGROOMMAP_CONNECTION_URL to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with MeetingroommapClient( + CONNECTION_RUNTIME_URL, + credential, + ) as client: + categories = [item async for item in client.list_categories()] + print(f"Categories: {categories}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_microsoftbookings.py b/samples/sample_connector_usage/aio/sample_connector_usage_microsoftbookings.py new file mode 100644 index 0000000..b3d70de --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_microsoftbookings.py @@ -0,0 +1,133 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Microsoft Bookings sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Microsoft Bookings client from the Azure Connectors Python SDK to +manage booking businesses and appointment webhooks. + +Prerequisites: +1. Azure subscription with Microsoft Bookings connection +2. Microsoft Bookings connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:MICROSOFTBOOKINGS_CONNECTION_URL = "" + + python sample_connector_usage_microsoftbookings.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.microsoftbookings import MicrosoftbookingsClient +from azure.connectors.microsoftbookings import ( + CreateAppointmentInput, + UpdateAppointmentInput, + CancelAppointmentInput, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/microsoftbookings/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "MICROSOFTBOOKINGS_CONNECTION_URL", + "" +) + +# Sample booking business SMTP address (replace with your own) +BOOKING_SMTP_ADDRESS = os.environ.get( + "BOOKING_SMTP_ADDRESS", + "bookings@contoso.com" +) + +# Webhook callback URL for trigger events +WEBHOOK_CALLBACK_URL = os.environ.get( + "WEBHOOK_CALLBACK_URL", + "https://your-function-app.azurewebsites.net/api/BookingsCallback" +) + + +async def example_1_list_booking_businesses(): + """Example 1: List booking businesses where user is an admin.""" + print("\n=== Example 1: List Booking Businesses ===") + + async with DefaultAzureCredential() as credential: + + async with MicrosoftbookingsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_bookings_business_user_as_admin()] + + if items: + mailboxes = items + print(f"Found {len(mailboxes)} booking business(es):") + for mailbox in mailboxes: + print(f" - {mailbox.get('display_name')}") + print(f" Email: {mailbox.get('email')}") + else: + print("No booking businesses found where you are an admin") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_build_create_webhook(): + """Example 2: Build an appointment-created webhook payload.""" + print("\n=== Example 2: Build Create Appointment Webhook ===") + + webhook_input = CreateAppointmentInput( + webhook={"callbackUrl": WEBHOOK_CALLBACK_URL} + ) + print(f"Business: {BOOKING_SMTP_ADDRESS}") + print(f"Create webhook payload: {webhook_input.webhook}") + + +async def example_3_build_update_webhook(): + """Example 3: Build an appointment-updated webhook payload.""" + print("\n=== Example 3: Build Update Appointment Webhook ===") + + webhook_input = UpdateAppointmentInput( + webhook={"callbackUrl": WEBHOOK_CALLBACK_URL} + ) + print(f"Update webhook payload: {webhook_input.webhook}") + + +async def example_4_build_cancel_webhook(): + """Example 4: Build an appointment-cancelled webhook payload.""" + print("\n=== Example 4: Build Cancel Appointment Webhook ===") + + webhook_input = CancelAppointmentInput( + webhook={"callbackUrl": WEBHOOK_CALLBACK_URL} + ) + print(f"Cancel webhook payload: {webhook_input.webhook}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: MICROSOFTBOOKINGS_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + # Run read-only example by default + await example_1_list_booking_businesses() + + # The current generated action client exposes payload models but not the + # webhook registration trigger operations. + await example_2_build_create_webhook() + await example_3_build_update_webhook() + await example_4_build_cancel_webhook() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_microsoftforms.py b/samples/sample_connector_usage/aio/sample_connector_usage_microsoftforms.py new file mode 100644 index 0000000..6f98e9a --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_microsoftforms.py @@ -0,0 +1,110 @@ +""" +Microsoft Forms sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Microsoft Forms client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Microsoft Forms connection +2. Microsoft Forms connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:MICROSOFTFORMS_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/microsoftforms/[connection-id]" + ) + + python sample_connector_usage_microsoftforms.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.microsoftforms import MicrosoftformsClient + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/microsoftforms/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("MICROSOFTFORMS_CONNECTION_URL", "") + + +async def example_1_list_forms() -> list[dict]: + """Example 1: List available forms.""" + print("\n=== Example 1: List Forms ===") + + async with DefaultAzureCredential() as credential: + async with MicrosoftformsClient(CONNECTION_RUNTIME_URL, credential) as client: + forms = [form async for form in client.list_forms()] + + print(f"Found {len(forms)} forms") + for form in forms[:5]: + print(f" - {form.get('title')} ({form.get('id')})") + + return forms + + +async def example_2_get_form_details(form_id: str) -> None: + """Example 2: Get details for one form.""" + print("\n=== Example 2: Get Form Details ===") + + async with DefaultAzureCredential() as credential: + async with MicrosoftformsClient(CONNECTION_RUNTIME_URL, credential) as client: + details = await client.get_form_details_by_id(form_id=form_id) + + if not details: + print("No details returned") + return + + print(f"Title: {details.get('title')}") + print(f"Status: {details.get('status')}") + print(f"Created: {details.get('createdDate')}") + print(f"Last Modified: {details.get('modifiedDate')}") + + +async def example_3_get_questions(form_id: str) -> None: + """Example 3: Get form questions.""" + print("\n=== Example 3: Get Questions ===") + + async with DefaultAzureCredential() as credential: + async with MicrosoftformsClient(CONNECTION_RUNTIME_URL, credential) as client: + await client.get_questions(form_id=form_id) + print("Question metadata request completed.") + + +async def main() -> None: + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: MICROSOFTFORMS_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Microsoft Forms sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + forms = await example_1_list_forms() + + if forms: + first_form_id = forms[0].get("id") + if first_form_id: + await example_2_get_form_details(first_form_id) + await example_3_get_questions(first_form_id) + else: + print("No form id found in first record; skipping detail examples.") + else: + print("No forms returned from the API.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_monday.py b/samples/sample_connector_usage/aio/sample_connector_usage_monday.py new file mode 100644 index 0000000..c6ed321 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_monday.py @@ -0,0 +1,131 @@ +""" +Monday.com sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Monday.com client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a Monday.com connection +2. Monday.com connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:MONDAY_CONNECTION_URL = "https://[region].azure-apihub.net/apim/monday/[id]" + + python sample_connector_usage_monday.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.monday import MondayClient +from azure.connectors.monday import ( + CreateBoardInput, + CreateItemInput, + DynamicResponseGetSingleColumnSchema, + UpdateItemColumnInput, +) + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/monday/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("MONDAY_CONNECTION_URL", "") + + +async def example_1_create_board() -> None: + """Example 1: Create a board.""" + print("\n=== Example 1: Create Board ===") + + async with DefaultAzureCredential() as credential: + async with MondayClient(CONNECTION_RUNTIME_URL, credential) as client: + board = await client.create_board( + input=CreateBoardInput( + workspace_id="123456", + board_name="SDK sample board", + ) + ) + data = board.get("data", {}) if board else {} + print(f"Created board: {data}") + + +async def example_2_create_item() -> None: + """Example 2: Create an item in a board and group.""" + print("\n=== Example 2: Create Item ===") + + async with DefaultAzureCredential() as credential: + async with MondayClient(CONNECTION_RUNTIME_URL, credential) as client: + item = await client.create_item( + input=CreateItemInput( + workspace_id="123456", + board_id="789012", + group_id="topics", + item_name="SDK sample item", + ) + ) + data = item.get("data", {}) if item else {} + print(f"Created item: {data}") + + +async def example_3_update_item_column() -> None: + """Example 3: Update a column value on an item.""" + print("\n=== Example 3: Update Item Column ===") + + async with DefaultAzureCredential() as credential: + async with MondayClient(CONNECTION_RUNTIME_URL, credential) as client: + updated = await client.update_item_column( + input=UpdateItemColumnInput( + workspace_id="123456", + board_id="789012", + item_id="345678", + column_id="status", + column_values=DynamicResponseGetSingleColumnSchema( + additional_properties={"label": "Done"}, + ), + ) + ) + data = updated.get("data", {}) if updated else {} + print(f"Updated item column: {data}") + + +async def example_4_list_workspaces() -> None: + """Example 4: List the available workspaces.""" + print("\n=== Example 4: List Workspaces ===") + + async with DefaultAzureCredential() as credential: + async with MondayClient(CONNECTION_RUNTIME_URL, credential) as client: + workspaces = await client.get_workspaces() + print(f"Workspaces: {workspaces}") + + +async def main() -> None: + """Run Monday.com connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: MONDAY_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Monday.com sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + # Uncomment to create boards or items in Monday.com. + # await example_1_create_board() + # await example_2_create_item() + # await example_3_update_item_column() + # await example_4_list_workspaces() + print("Set the example calls in main() to run against your instance.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_mq.py b/samples/sample_connector_usage/aio/sample_connector_usage_mq.py new file mode 100644 index 0000000..4f2266a --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_mq.py @@ -0,0 +1,227 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +IBM MQ sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the IBM MQ client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with IBM MQ connection +2. IBM MQ connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Note: IBM MQ uses parameter-based auth (server, queue manager, channel, credentials). +The connection must be created with parameterValues — no OAuth consent flow. + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:MQ_CONNECTION_URL = "https://[region].azure-apihub.net/apim/mq/[connection-id]" + + python sample_connector_usage_mq.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.mq import MqClient +from azure.connectors.mq import ( + SendValidDataOptions, + SingleGetValidOptions, + MultipleGetValidOptions, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/mq/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "MQ_CONNECTION_URL", + "" +) + +# Optional: Override queue name (otherwise uses connection default) +DEFAULT_QUEUE = os.environ.get("TEST_MQ_QUEUE", None) + + +async def example_1_send_message(): + """Example 1: Send a message to an IBM MQ queue.""" + print("\n=== Example 1: Send Message ===") + + message_content = os.environ.get( + "TEST_MQ_MESSAGE", + "Hello from Azure Connectors SDK for Python!" + ) + + async with DefaultAzureCredential() as credential: + + async with MqClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + options = SendValidDataOptions( + message=message_content, + queue=DEFAULT_QUEUE, + ) + + result = await client.send(input=options) + + if result: + print("Message sent successfully:") + print(f" Message ID: {result.get('messageId', 'N/A')}") + print(f" Correlation ID: {result.get('correlationId', 'N/A')}") + else: + print("Message sent (no response returned).") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_browse_message(): + """Example 2: Browse (peek) a single message without removing it.""" + print("\n=== Example 2: Browse Message ===") + + async with DefaultAzureCredential() as credential: + + async with MqClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + options = SingleGetValidOptions( + queue=DEFAULT_QUEUE, + include_info="true", + ) + + result = await client.read(input=options) + + if result: + print("Browsed message:") + print(f" Message ID: {result.get('messageId', 'N/A')}") + print(f" Correlation ID: {result.get('correlationId', 'N/A')}") + message_data = result.get("messageData", "") + preview = message_data[:100] if message_data else "(empty)" + print(f" Data preview: {preview}") + else: + print("No message available in queue.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_browse_messages_batch(): + """Example 3: Browse multiple messages without removing them.""" + print("\n=== Example 3: Browse Messages (Batch) ===") + + batch_size = int(os.environ.get("TEST_MQ_BATCH_SIZE", "10")) + + async with DefaultAzureCredential() as credential: + + async with MqClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + options = MultipleGetValidOptions( + queue=DEFAULT_QUEUE, + batch_size=batch_size, + include_info="true", + ) + + result = await client.read_all(input=options) + items = result.get("value", []) if result else [] + + if items: + print(f"Browsed {len(items)} messages:") + for i, msg in enumerate(items[:5]): # Show first 5 + msg_id = msg.get("messageId", "N/A") + data = msg.get("messageData", "") + preview = data[:50] if data else "(empty)" + print(f" {i + 1}. ID: {msg_id}, Data: {preview}...") + else: + print("No messages available in queue.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_receive_message(): + """Example 4: Receive (destructive get) a single message from the queue.""" + print("\n=== Example 4: Receive Message (Destructive) ===") + + async with DefaultAzureCredential() as credential: + + async with MqClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + options = SingleGetValidOptions( + queue=DEFAULT_QUEUE, + include_info="true", + ) + + result = await client.receive(input=options) + + if result: + print("Received message (removed from queue):") + print(f" Message ID: {result.get('messageId', 'N/A')}") + print(f" Correlation ID: {result.get('correlationId', 'N/A')}") + message_data = result.get("messageData", "") + preview = message_data[:100] if message_data else "(empty)" + print(f" Data preview: {preview}") + else: + print("No message available in queue.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_delete_message(): + """Example 5: Delete a single message from the queue.""" + print("\n=== Example 5: Delete Message ===") + + async with DefaultAzureCredential() as credential: + + async with MqClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + options = SingleGetValidOptions( + queue=DEFAULT_QUEUE, + ) + + result = await client.delete(input=options) + + if result: + print("Deleted message:") + print(f" Message ID: {result.get('messageId', 'N/A')}") + print(" Success: True") + else: + print("No message available to delete.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + print("IBM MQ sample usage for the Azure Connectors Python SDK") + print("=" * 60) + + if not CONNECTION_RUNTIME_URL: + print("\nWARNING: MQ_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL to run actual API calls.") + print("Format: https://[region].azure-apihub.net/apim/mq/[connection-id]") + return + + await example_1_send_message() + await example_2_browse_message() + await example_3_browse_messages_batch() + await example_4_receive_message() + await example_5_delete_message() + + print("\n" + "=" * 60) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_msgraphgroupsanduser.py b/samples/sample_connector_usage/aio/sample_connector_usage_msgraphgroupsanduser.py new file mode 100644 index 0000000..c58e430 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_msgraphgroupsanduser.py @@ -0,0 +1,217 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +MS Graph Groups & Users sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the MS Graph Groups & Users client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with MS Graph Groups & Users connection +2. MS Graph connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:MSGRAPH_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/msgraphgroupsanduser/[connection-id]" + ) + + python sample_connector_usage_msgraphgroupsanduser.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.msgraphgroupsanduser import MsgraphgroupsanduserClient + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/msgraphgroupsanduser/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "MSGRAPH_CONNECTION_URL", + "" +) + + +async def example_1_list_users(): + """Example 1: List users in the tenant.""" + print("\n=== Example 1: List Users ===") + + async with DefaultAzureCredential() as credential: + + async with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + users = [user async for user in client.list_users()] + + if users: + print(f"Found {len(users)} users:") + for user in users[:5]: # Show first 5 + display_name = user.get("displayName", "Unknown") + user_principal = user.get("userPrincipalName", "N/A") + print(f" - {display_name} ({user_principal})") + else: + print("No users found or unexpected response format.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_list_groups(): + """Example 2: Search for groups by display name.""" + print("\n=== Example 2: List Groups (Search) ===") + + search_term = os.environ.get("TEST_GROUP_SEARCH", None) + + async with DefaultAzureCredential() as credential: + + async with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + groups = [ + group + async for group in client.list_groups_by_display_name_search( + search=search_term, + ) + ] + + search_display = search_term or "(all)" + if groups: + print(f"Search: {search_display}") + print(f"Found {len(groups)} groups:") + for group in groups[:5]: # Show first 5 + display_name = group.get("displayName", "Unknown") + group_id = group.get("id", "N/A") + mail = group.get("mail", "No email") + print(f" - {display_name}") + print(f" ID: {group_id}") + print(f" Mail: {mail}") + else: + print(f"No groups found for search: {search_display}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_get_group_properties(): + """Example 3: Get properties of a specific group.""" + print("\n=== Example 3: Get Group Properties ===") + + group_id = os.environ.get("TEST_GROUP_ID", "") + if not group_id: + print("Set TEST_GROUP_ID environment variable to test this example.") + print("You can get a group ID from Example 2 output.") + return + + async with DefaultAzureCredential() as credential: + + async with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + group = await client.get_group_properties(group_id=group_id) + + if group: + print(f"Group properties for '{group.get('displayName', 'Unknown')}':") + print(f" ID: {group.get('id', 'N/A')}") + print(f" Description: {group.get('description', 'N/A')}") + print(f" Mail: {group.get('mail', 'N/A')}") + print(f" Mail Enabled: {group.get('mailEnabled', 'N/A')}") + print(f" Security Enabled: {group.get('securityEnabled', 'N/A')}") + print(f" Visibility: {group.get('visibility', 'N/A')}") + else: + print(f"Group not found: {group_id}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_list_group_members(): + """Example 4: List direct members of a group.""" + print("\n=== Example 4: List Group Members ===") + + group_id = os.environ.get("TEST_GROUP_ID", "") + if not group_id: + print("Set TEST_GROUP_ID environment variable to test this example.") + print("You can get a group ID from Example 2 output.") + return + + async with DefaultAzureCredential() as credential: + + async with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + members = [ + member + async for member in client.list_direct_group_members( + group_id=group_id, + ) + ] + + if members: + print(f"Found {len(members)} members:") + for member in members[:5]: # Show first 5 + display_name = member.get("displayName", "Unknown") + member_type = member.get("@odata.type", "Unknown type") + print(f" - {display_name} ({member_type})") + else: + print("No members found or unexpected response format.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_list_subscribed_skus(): + """Example 5: List organization's subscribed license SKUs.""" + print("\n=== Example 5: List Subscribed SKUs ===") + + async with DefaultAzureCredential() as credential: + + async with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + skus = [sku async for sku in client.list_subscribed_skus()] + + if skus: + print(f"Found {len(skus)} subscribed SKUs:") + for sku in skus[:5]: # Show first 5 + sku_part_number = sku.get("skuPartNumber", "Unknown") + consumed = sku.get("consumedUnits", 0) + print(f" - {sku_part_number} (Consumed: {consumed} units)") + else: + print("No subscribed SKUs found or unexpected response format.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + print("MS Graph Groups & Users sample usage for the Azure Connectors Python SDK") + print("=" * 60) + + if not CONNECTION_RUNTIME_URL: + print("\nWARNING: MSGRAPH_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL to run actual API calls.") + print("Format: https://[region].azure-apihub.net/apim/msgraphgroupsanduser/[connection-id]") + return + + await example_1_list_users() + await example_2_list_groups() + await example_3_get_group_properties() + await example_4_list_group_members() + await example_5_list_subscribed_skus() + + print("\n" + "=" * 60) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_office365.py b/samples/sample_connector_usage/aio/sample_connector_usage_office365.py new file mode 100644 index 0000000..89455c6 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_office365.py @@ -0,0 +1,197 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Office365 sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Office365 client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Office365 connection +2. Office365 connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:OFFICE365_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/office365/[connection-id]" + ) + + python sample_connector_usage_office365.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.office365 import Office365Client +from azure.connectors.office365 import ( + DraftEmailInput, + SendEmailInput, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/office365/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "OFFICE365_CONNECTION_URL", + "" +) + + +async def example_1_get_outlook_categories(): + """Example 1: Get Outlook category names.""" + print("\n=== Example 1: Get Outlook Category Names ===") + + async with DefaultAzureCredential() as credential: + + async with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: + try: + categories = [item async for item in client.list_outlook_category_names()] + + if categories and 'value' in categories: + print(f"Found {len(categories['value'])} Outlook categories:") + for category in categories['value'][:5]: + display_name = category.get('DisplayName', 'Unknown') + color = category.get('Color', 'N/A') + print(f" - {display_name} (Color: {color})") + else: + print("No categories found or unexpected response format.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_send_email(): + """Example 2: Send an HTML email.""" + print("\n=== Example 2: Send Email ===") + + to_address = os.environ.get("TEST_EMAIL_TO", "@microsoft.com") + + async with DefaultAzureCredential() as credential: + + async with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: + try: + email = SendEmailInput( + to=to_address, + subject="Test Email from the Azure Connectors Python SDK", + body=( + "

This is a test email sent from the " + "Azure Connectors Python SDK.

" + ), + ) + + await client.send_email(email) + print(f"Email sent successfully to {to_address}") + print("Note: Set TEST_EMAIL_TO environment variable to send to a real address") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_get_emails(): + """Example 3: Get emails from inbox.""" + print("\n=== Example 3: Get Emails from Inbox ===") + + async with DefaultAzureCredential() as credential: + + async with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: + try: + emails = [item async for item in client.list_emails()] + + if emails and 'value' in emails: + print(f"Found {len(emails['value'])} emails:") + for email in emails['value']: + subject = email.get('Subject', 'No Subject') + from_addr = email.get('From', 'Unknown') + received = email.get('DateTimeReceived', 'Unknown') + print(f" - {subject}") + print(f" From: {from_addr}") + print(f" Received: {received}") + else: + print("No emails found or unexpected response format.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_draft_and_send_email(): + """Example 4: Draft an email and then send it.""" + print("\n=== Example 4: Draft and Send Email ===") + + to_address = os.environ.get("TEST_EMAIL_TO", "@microsoft.com") + + async with DefaultAzureCredential() as credential: + + async with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: + try: + draft = DraftEmailInput( + to=to_address, + subject="Draft Email from SDK", + body="

This email was created as a draft first.

", + ) + + draft_response = await client.draft_email(draft) + print("Draft created successfully") + + if draft_response and 'Id' in draft_response: + message_id = draft_response['Id'] + print(f"Draft message ID: {message_id}") + + await client.send_draft_email(message_id=message_id) + print(f"Draft email sent successfully to {to_address}") + else: + print("Draft created but no ID returned.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_error_handling(): + """Example 5: Demonstrate error handling.""" + print("\n=== Example 5: Error Handling ===") + + async with DefaultAzureCredential() as credential: + + async with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Attempt to get an email with an invalid ID + invalid_message_id = "invalid-message-id-12345" + email = await client.get_email(message_id=invalid_message_id) + print(f"Unexpected success: {email}") + + except ConnectorException as ex: + print("Expected error caught:") + print(f" Message: {ex}") + except Exception as ex: + print(f"Unexpected error type: {type(ex).__name__}") + print(f" Message: {ex}") + + +async def main(): + """Run all examples.""" + print("Office365 sample usage for the Azure Connectors Python SDK") + print("=" * 50) + print() + + await example_1_get_outlook_categories() + await example_2_send_email() + await example_3_get_emails() + await example_4_draft_and_send_email() + await example_5_error_handling() + + print("\n" + "=" * 50) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_office365groups.py b/samples/sample_connector_usage/aio/sample_connector_usage_office365groups.py new file mode 100644 index 0000000..9326cae --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_office365groups.py @@ -0,0 +1,238 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Office 365 Groups sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Office 365 Groups client from the Azure Connectors Python SDK +for group management and calendar operations. + +Prerequisites: +1. Azure subscription with Office 365 Groups connection +2. Office 365 Groups connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:OFFICE365GROUPS_CONNECTION_URL = "" + + python sample_connector_usage_office365groups.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.office365groups import Office365groupsClient +from azure.connectors.office365groups import ( + UpdateCalendarEventHTMLRequest, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/office365groups/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "OFFICE365GROUPS_CONNECTION_URL", + "" +) + + +async def example_1_list_groups(): + """Example 1: List all groups in the organization.""" + print("\n=== Example 1: List Groups ===") + + async with DefaultAzureCredential() as credential: + + async with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + groups = [item async for item in client.list_groups(top=10)] + + if groups: + print(f"Found {len(groups)} groups:") + for group in groups[:5]: + print(f" - {group.get('displayName', 'N/A')} ({group.get('id', 'N/A')})") + else: + print("No groups found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_list_group_members(): + """Example 2: List members of a specific group.""" + print("\n=== Example 2: List Group Members ===") + + # Replace with your actual group ID + GROUP_ID = "your-group-id-here" + + async with DefaultAzureCredential() as credential: + + async with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + members = [ + item async for item in client.list_group_members( + group_id=GROUP_ID + ) + ] + + if members: + print(f"Found {len(members)} members:") + for member in members[:5]: + print(f" - {member.get('displayName', 'N/A')}") + else: + print("No members found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_list_owned_groups(): + """Example 3: List groups that I own and belong to.""" + print("\n=== Example 3: List My Groups ===") + + async with DefaultAzureCredential() as credential: + + async with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + groups = [group async for group in client.list_owned_groups()] + + if groups: + print(f"You own or belong to {len(groups)} groups:") + for group in groups[:5]: + print(f" - {group.get('displayName', 'N/A')}") + else: + print("No groups found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_create_group_event(): + """Example 4: Create a calendar event in a group.""" + print("\n=== Example 4: Create Group Event ===") + + # Replace with your actual group ID + GROUP_ID = "your-group-id-here" + + async with DefaultAzureCredential() as credential: + + async with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + event_input = UpdateCalendarEventHTMLRequest( + subject="Team Standup", + is_all_day=False, + is_reminder_on=True, + reminder_minutes_before_start=15, + importance="Normal", + start={ + "dateTime": "2026-06-15T09:00:00", + "timeZone": "Pacific Standard Time" + }, + end={ + "dateTime": "2026-06-15T09:30:00", + "timeZone": "Pacific Standard Time" + }, + body={ + "contentType": "HTML", + "content": "

Daily standup meeting

" + } + ) + + result = await client.create_calendar_event( + input=event_input, + group_id=GROUP_ID + ) + + if result: + print("Event created successfully!") + print(f"Event ID: {result.get('id')}") + print(f"Subject: {result.get('subject')}") + else: + print("Event creation completed (no response body)") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_add_member_to_group(): + """Example 5: Add a member to a group.""" + print("\n=== Example 5: Add Member to Group ===") + + # Replace with your actual values + GROUP_ID = "your-group-id-here" + USER_UPN = "user@contoso.com" + + async with DefaultAzureCredential() as credential: + + async with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + await client.add_member_to_group( + group_id=GROUP_ID, + user_upn=USER_UPN + ) + + print(f"Member {USER_UPN} added to group successfully!") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_6_list_deleted_groups(): + """Example 6: List deleted groups that can be restored.""" + print("\n=== Example 6: List Deleted Groups ===") + + async with DefaultAzureCredential() as credential: + + async with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + groups = [ + item async for item in client.list_deleted_groups() + ] + + if groups: + print(f"Found {len(groups)} deleted groups:") + for group in groups[:5]: + print(f" - {group.get('displayName', 'N/A')} ({group.get('id', 'N/A')})") + else: + print("No deleted groups found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: OFFICE365GROUPS_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_list_groups() + await example_3_list_owned_groups() + await example_6_list_deleted_groups() + + # The following examples require valid IDs: + # await example_2_list_group_members() + # await example_4_create_group_event() + # await example_5_add_member_to_group() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_office365groupsmail.py b/samples/sample_connector_usage/aio/sample_connector_usage_office365groupsmail.py new file mode 100644 index 0000000..c9ef8e3 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_office365groupsmail.py @@ -0,0 +1,40 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Sample usage for the Office 365 Groups Mail connector client.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors.aio.office365groupsmail import Office365groupsmailClient + + +async def main() -> None: + """Run a simple Office 365 Groups Mail sample flow.""" + connection_url = os.getenv("OFFICE365GROUPSMAIL_CONNECTION_URL") + if not connection_url: + raise ValueError("Set OFFICE365GROUPSMAIL_CONNECTION_URL environment variable") + + group_id = os.getenv("OFFICE365GROUPSMAIL_GROUP_ID") + if not group_id: + raise ValueError("Set OFFICE365GROUPSMAIL_GROUP_ID environment variable") + + async with DefaultAzureCredential() as credential: + async with Office365groupsmailClient(connection_url, credential) as client: + conversations = [ + conversation + async for conversation in client.list_conversations( + group_id=group_id + ) + ] + conversation_count = len(conversations) + print(f"Found {conversation_count} conversation(s) in group '{group_id}'.") + + groups = [group async for group in client.list_groups()] + group_count = len(groups) + print(f"Current user is in {group_count} Office 365 group(s).") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_office365users.py b/samples/sample_connector_usage/aio/sample_connector_usage_office365users.py new file mode 100644 index 0000000..97c7844 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_office365users.py @@ -0,0 +1,216 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Office 365 Users sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Office 365 Users client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Office 365 Users connection +2. Office 365 Users connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:OFFICE365USERS_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/office365users/[connection-id]" + ) + + python sample_connector_usage_office365users.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.office365users import Office365usersClient + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/office365users/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "OFFICE365USERS_CONNECTION_URL", + "" +) + + +async def example_1_get_my_profile(): + """Example 1: Get the current user's profile.""" + print("\n=== Example 1: Get My Profile ===") + + async with DefaultAzureCredential() as credential: + + async with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + profile = await client.my_profile() + + if profile: + print("My Profile:") + print(f" Display Name: {profile.get('displayName', 'N/A')}") + print(f" Email: {profile.get('mail', 'N/A')}") + print(f" Job Title: {profile.get('jobTitle', 'N/A')}") + print(f" Department: {profile.get('department', 'N/A')}") + print(f" Office: {profile.get('officeLocation', 'N/A')}") + else: + print("No profile returned.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_get_user_profile(): + """Example 2: Get a specific user's profile.""" + print("\n=== Example 2: Get User Profile ===") + + user_id = os.environ.get("TEST_USER_ID", "") + if not user_id: + print("Set TEST_USER_ID environment variable to a user's ID or UPN.") + print("Example: $env:TEST_USER_ID = 'john.doe@contoso.com'") + return + + async with DefaultAzureCredential() as credential: + + async with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + profile = await client.user_profile(id=user_id) + + if profile: + print(f"User Profile for '{user_id}':") + print(f" Display Name: {profile.get('displayName', 'N/A')}") + print(f" Email: {profile.get('mail', 'N/A')}") + print(f" Job Title: {profile.get('jobTitle', 'N/A')}") + print(f" Department: {profile.get('department', 'N/A')}") + print(f" Office: {profile.get('officeLocation', 'N/A')}") + else: + print(f"User not found: {user_id}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_get_manager(): + """Example 3: Get a user's manager.""" + print("\n=== Example 3: Get Manager ===") + + user_id = os.environ.get("TEST_USER_ID", "") + if not user_id: + print("Set TEST_USER_ID environment variable to a user's ID or UPN.") + print("Example: $env:TEST_USER_ID = 'john.doe@contoso.com'") + return + + async with DefaultAzureCredential() as credential: + + async with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + manager = await client.manager(id=user_id) + + if manager: + print(f"Manager for '{user_id}':") + print(f" Display Name: {manager.get('displayName', 'N/A')}") + print(f" Email: {manager.get('mail', 'N/A')}") + print(f" Job Title: {manager.get('jobTitle', 'N/A')}") + else: + print(f"No manager found for: {user_id}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_get_direct_reports(): + """Example 4: Get a user's direct reports.""" + print("\n=== Example 4: Get Direct Reports ===") + + user_id = os.environ.get("TEST_USER_ID", "") + if not user_id: + print("Set TEST_USER_ID environment variable to a user's ID or UPN.") + print("Example: $env:TEST_USER_ID = 'john.doe@contoso.com'") + return + + async with DefaultAzureCredential() as credential: + + async with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + reports = [item async for item in client.list_direct_reports(id=user_id)] + + if reports and "value" in reports: + print(f"Direct reports for '{user_id}':") + print(f" Found {len(reports['value'])} reports") + for report in reports["value"][:5]: # Show first 5 + display_name = report.get("displayName", "N/A") + job_title = report.get("jobTitle", "N/A") + print(f" - {display_name} ({job_title})") + else: + print(f"No direct reports found for: {user_id}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_search_users(): + """Example 5: Search for users.""" + print("\n=== Example 5: Search Users ===") + + search_term = os.environ.get("TEST_SEARCH_TERM", "") + if not search_term: + print("Set TEST_SEARCH_TERM environment variable to search for users.") + print("Example: $env:TEST_SEARCH_TERM = 'John'") + return + + async with DefaultAzureCredential() as credential: + + async with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + results = [item async for item in client.list_search_user( + search_term=search_term, + top=10, + )] + + if results: + print(f"Search results for '{search_term}':") + print(f" Found {len(results)} users") + for user in results[:5]: # Show first 5 + display_name = user.get("DisplayName", "N/A") + mail = user.get("Mail", "N/A") + print(f" - {display_name} ({mail})") + else: + print(f"No users found matching: {search_term}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + print("Office 365 Users sample usage for the Azure Connectors Python SDK") + print("=" * 60) + + if not CONNECTION_RUNTIME_URL: + print("\nWARNING: OFFICE365USERS_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL to run actual API calls.") + print("Format: https://[region].azure-apihub.net/apim/office365users/[connection-id]") + return + + await example_1_get_my_profile() + await example_2_get_user_profile() + await example_3_get_manager() + await example_4_get_direct_reports() + await example_5_search_users() + + print("\n" + "=" * 60) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_onedrive.py b/samples/sample_connector_usage/aio/sample_connector_usage_onedrive.py new file mode 100644 index 0000000..752d0e6 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_onedrive.py @@ -0,0 +1,302 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +OneDrive sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the OneDrive client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with OneDrive connection +2. OneDrive connection in Connector Namespaces (with OAuth consent) +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:ONEDRIVE_CONNECTION_URL = "https://[region].azure-apihub.net/apim/onedrive/[connection-id]" + + python sample_connector_usage_onedrive.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.onedrive import OnedriveClient + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/onedrive/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "ONEDRIVE_CONNECTION_URL", + "" +) + + +async def example_1_list_root_folder(): + """Example 1: List files in root folder.""" + print("\n=== Example 1: List Root Folder ===") + + async with DefaultAzureCredential() as credential: + + async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + items = [item async for item in client.list_root_folder()] + + if items: + print(f"Found {len(items)} items in root folder:") + for item in items[:10]: # Show first 10 + item_type = "📁" if item.get("IsFolder") else "📄" + print(f" {item_type} {item.get('Name', 'N/A')}") + else: + print("No items found in root folder.") + + +async def example_2_get_file_metadata(): + """Example 2: Get file metadata by path.""" + print("\n=== Example 2: Get File Metadata ===") + + file_path = os.environ.get("TEST_FILE_PATH", "") + if not file_path: + print("Set TEST_FILE_PATH environment variable to a file path.") + print("Example: $env:TEST_FILE_PATH = '/Documents/report.docx'") + return + + async with DefaultAzureCredential() as credential: + + async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + metadata = await client.get_file_metadata_by_path(path=file_path) + + if metadata: + print(f"File Metadata for '{file_path}':") + print(f" ID: {metadata.get('Id', 'N/A')}") + print(f" Name: {metadata.get('Name', 'N/A')}") + print(f" Size: {metadata.get('Size', 'N/A')} bytes") + print(f" Last Modified: {metadata.get('LastModified', 'N/A')}") + print(f" Media Type: {metadata.get('MediaType', 'N/A')}") + else: + print(f"No metadata returned for: {file_path}") + except ConnectorException as e: + print(f"Error getting file metadata: {e}") + + +async def example_3_download_file(): + """Example 3: Download file content.""" + print("\n=== Example 3: Download File Content ===") + + file_path = os.environ.get("TEST_FILE_PATH", "") + if not file_path: + print("Set TEST_FILE_PATH environment variable to a file path.") + return + + async with DefaultAzureCredential() as credential: + + async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + content = await client.get_file_content_by_path(path=file_path) + + if content: + print(f"Downloaded {len(content)} bytes") + # Show first 100 characters if text-like + try: + preview = content[:100].decode('utf-8') + print(f"Content preview: {preview}...") + except UnicodeDecodeError: + print("Content is binary data.") + else: + print("No content returned.") + except ConnectorException as e: + print(f"Error downloading file: {e}") + + +async def example_4_list_folder(): + """Example 4: List files in a specific folder.""" + print("\n=== Example 4: List Folder Contents ===") + + folder_id = os.environ.get("TEST_FOLDER_ID", "") + if not folder_id: + print("Set TEST_FOLDER_ID environment variable to a folder ID.") + print("You can get folder IDs from list_root_folder results.") + return + + async with DefaultAzureCredential() as credential: + + async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + entries = [ + item async for item in client.list_folder(id=folder_id) + ] + + if entries: + print(f"Found {len(entries)} items:") + for item in entries[:10]: + item_type = "📁" if item.get("IsFolder") else "📄" + size = item.get("Size", 0) + print(f" {item_type} {item.get('Name', 'N/A')} ({size} bytes)") + else: + print("No items found in folder.") + except ConnectorException as e: + print(f"Error listing folder: {e}") + + +async def example_5_search_files(): + """Example 5: Search for files in a folder.""" + print("\n=== Example 5: Search Files ===") + + folder_id = os.environ.get("TEST_FOLDER_ID", "") + search_query = os.environ.get("TEST_SEARCH_QUERY", "report") + + if not folder_id: + print("Set TEST_FOLDER_ID environment variable to search in a folder.") + return + + async with DefaultAzureCredential() as credential: + + async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_find_files( + id=folder_id, + query=search_query, + find_mode="search" + )] + + if items: + print(f"Found {len(items)} files matching '{search_query}':") + for item in items: + print(f" 📄 {item.get('Name', 'N/A')}") + else: + print(f"No files found matching '{search_query}'.") + except ConnectorException as e: + print(f"Error searching files: {e}") + + +async def example_6_create_share_link(): + """Example 6: Create a share link for a file.""" + print("\n=== Example 6: Create Share Link ===") + + file_id = os.environ.get("TEST_FILE_ID", "") + if not file_id: + print("Set TEST_FILE_ID environment variable to create a share link.") + return + + async with DefaultAzureCredential() as credential: + + async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.create_share_link( + id=file_id, + type_="view" # "view" or "edit" + ) + + if result and "webUrl" in result: + print("Share link created:") + print(f" URL: {result['webUrl']}") + else: + print("Failed to create share link.") + except ConnectorException as e: + print(f"Error creating share link: {e}") + + +async def example_7_file_tags(): + """Example 7: Manage file tags.""" + print("\n=== Example 7: Manage File Tags ===") + + file_id = os.environ.get("TEST_FILE_ID", "") + if not file_id: + print("Set TEST_FILE_ID environment variable to manage tags.") + return + + async with DefaultAzureCredential() as credential: + + async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Get existing tags + tags_items = [item async for item in client.list_file_tags(id=file_id)] + + if tags_items: + print(f"Current tags: {tags_items}") + else: + print("No tags found on file.") + + # Add a new tag + print("Adding tag 'sdk-sample'...") + added_tags = await client.add_file_tag(id=file_id, tag="sdk-sample") + if added_tags: + print(f"Add tag result: {added_tags}") + + # Get updated tags + tags_items = [item async for item in client.list_file_tags(id=file_id)] + if tags_items: + print(f"Updated tags: {tags_items}") + except ConnectorException as e: + print(f"Error managing tags: {e}") + + +async def example_8_copy_file(): + """Example 8: Copy a file within OneDrive.""" + print("\n=== Example 8: Copy File ===") + + file_id = os.environ.get("TEST_FILE_ID", "") + dest_folder = os.environ.get("TEST_DEST_FOLDER", "/Documents/Copies") + + if not file_id: + print("Set TEST_FILE_ID environment variable to copy a file.") + return + + async with DefaultAzureCredential() as credential: + + async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.copy_drive_file( + id=file_id, + destination=dest_folder, + overwrite=False + ) + + if result: + print("File copied successfully:") + print(f" New ID: {result.get('Id', 'N/A')}") + print(f" New Name: {result.get('Name', 'N/A')}") + else: + print("Copy operation returned no result.") + except ConnectorException as e: + print(f"Error copying file: {e}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("ERROR: ONEDRIVE_CONNECTION_URL environment variable not set.") + print("\nTo get your connection URL:") + print("1. Go to Azure Portal > Connector Namespaces") + print("2. Create or select a OneDrive connection") + print("3. Copy the 'Connection Runtime URL'") + print("\nExample:") + url_example = "https://eastus.azure-apihub.net/apim/onedrive/abc123" + print(f"$env:ONEDRIVE_CONNECTION_URL = '{url_example}'") + return + + print("OneDrive sample for the Azure Connectors Python SDK") + print("=" * 50) + print(f"Connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + try: + await example_1_list_root_folder() + await example_2_get_file_metadata() + await example_3_download_file() + await example_4_list_folder() + await example_5_search_files() + await example_6_create_share_link() + await example_7_file_tags() + await example_8_copy_file() + except Exception as e: + print(f"\nUnexpected error: {e}") + raise + + print("\n" + "=" * 50) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_onedriveforbusiness.py b/samples/sample_connector_usage/aio/sample_connector_usage_onedriveforbusiness.py new file mode 100644 index 0000000..10e4518 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_onedriveforbusiness.py @@ -0,0 +1,72 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""OneDrive for Business sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.connectors import ConnectorException +from azure.connectors.aio.onedriveforbusiness import OnedriveforbusinessClient +from azure.identity.aio import DefaultAzureCredential + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/onedriveforbusiness/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("ONEDRIVEFORBUSINESS_CONNECTION_URL", "") + + +async def example_list_root_folder() -> None: + """List files in the root folder.""" + async with DefaultAzureCredential() as credential: + + async with OnedriveforbusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + items = [item async for item in client.list_root_folder()] + values = items + print(f"Found {len(values)} items in root folder.") + + +async def example_get_file_metadata() -> None: + """Get file metadata by path.""" + file_path = os.environ.get("TEST_FILE_PATH", "/Documents/report.docx") + async with DefaultAzureCredential() as credential: + + async with OnedriveforbusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + metadata = await client.get_file_metadata_by_path(path=file_path) + if metadata: + print(f"Name: {metadata.get('name')}, Size: {metadata.get('size')} bytes") + else: + print("No metadata was returned.") + + +async def example_create_share_link() -> None: + """Create a share link for a file ID.""" + file_id = os.environ.get("TEST_FILE_ID") + if not file_id: + print("Set TEST_FILE_ID to run the share-link example.") + return + + async with DefaultAzureCredential() as credential: + + async with OnedriveforbusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + result = await client.create_share_link(id=file_id, type_="view") + if result: + print(f"Share URL: {result.get('webUrl')}") + else: + print("No share link was returned.") + + +async def main() -> None: + """Run sample operations.""" + if not CONNECTION_RUNTIME_URL: + print("Set ONEDRIVEFORBUSINESS_CONNECTION_URL before running this sample.") + return + + try: + await example_list_root_folder() + await example_get_file_metadata() + await example_create_share_link() + except ConnectorException as ex: + print(f"Connector error ({ex.status_code}): {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_onenote.py b/samples/sample_connector_usage/aio/sample_connector_usage_onenote.py new file mode 100644 index 0000000..f2fe7eb --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_onenote.py @@ -0,0 +1,237 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +OneNote sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the OneNote client from the Azure Connectors Python SDK +for notebook, section, and page operations. + +Prerequisites: +1. Azure subscription with OneNote connection +2. OneNote connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:ONENOTE_CONNECTION_URL = "" + + python sample_connector_usage_onenote.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.onenote import OnenoteClient +from azure.connectors.onenote import ( + CreateSectionRequest, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/onenote/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "ONENOTE_CONNECTION_URL", + "" +) + + +async def example_1_list_notebooks(): + """Example 1: List recent notebooks.""" + print("\n=== Example 1: List Notebooks ===") + + async with DefaultAzureCredential() as credential: + + async with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_notebooks()] + + if items: + notebooks = items + print(f"Found {len(notebooks)} notebooks:") + for nb in notebooks[:5]: + print(f" - {nb.get('fileName', 'N/A')} (key: {nb.get('key', 'N/A')})") + else: + print("No notebooks found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_list_sections(): + """Example 2: List sections in a notebook.""" + print("\n=== Example 2: List Sections ===") + + # Replace with your actual notebook key + NOTEBOOK_KEY = "your-notebook-key-here" + + async with DefaultAzureCredential() as credential: + + async with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_sections_in_notebook( + notebook_key=NOTEBOOK_KEY + )] + + if items: + sections = items + print(f"Found {len(sections)} sections:") + for section in sections[:5]: + print(f" - {section.get('name', 'N/A')} (id: {section.get('id', 'N/A')})") + else: + print("No sections found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_get_pages_in_section(): + """Example 3: Get pages in a section.""" + print("\n=== Example 3: Get Pages ===") + + # Replace with your actual values + NOTEBOOK_KEY = "your-notebook-key-here" + SECTION_ID = "your-section-id-here" + + async with DefaultAzureCredential() as credential: + + async with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + pages = [item async for item in client.list_pages_in_section( + notebook_key=NOTEBOOK_KEY, + section_id=SECTION_ID + )] + + if pages: + print(f"Found {len(pages)} pages:") + for page in pages[:5]: + print(f" - {page.get('title', 'Untitled')} (id: {page.get('id', 'N/A')})") + else: + print("No pages found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_create_section(): + """Example 4: Create a new section in a notebook.""" + print("\n=== Example 4: Create Section ===") + + # Replace with your actual notebook key + NOTEBOOK_KEY = "your-notebook-key-here" + + async with DefaultAzureCredential() as credential: + + async with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + section_request = CreateSectionRequest(name="SDK Test Section") + + result = await client.create_section_in_notebook( + input=section_request, + notebook_key=NOTEBOOK_KEY + ) + + if result: + print("Section created successfully!") + print(f"Section ID: {result.get('id')}") + print(f"Section Name: {result.get('name')}") + else: + print("Section creation completed (no response body)") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_create_quick_note(): + """Example 5: Create a page in Quick Notes.""" + print("\n=== Example 5: Create Quick Note ===") + + async with DefaultAzureCredential() as credential: + + async with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + page_input = ( + "Quick Note" + "

Created via Azure Connectors Python SDK

" + ) + + result = await client.create_page_in_quick_notes(input=page_input) + + if result: + print("Quick note created successfully!") + print(f"Page ID: {result.get('id')}") + print(f"Title: {result.get('title')}") + else: + print("Quick note creation completed (no response body)") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_6_get_page_content(): + """Example 6: Get page content.""" + print("\n=== Example 6: Get Page Content ===") + + # Replace with your actual values + NOTEBOOK_KEY = "your-notebook-key-here" + SECTION_ID = "your-section-id-here" + PAGE_ID = "your-page-id-here" + + async with DefaultAzureCredential() as credential: + + async with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.get_page_content( + notebook_key=NOTEBOOK_KEY, + section_id=SECTION_ID, + page_id=PAGE_ID, + ) + + if result: + print("Page content retrieved successfully!") + content = str(result)[:200] + print(f"Content preview: {content}...") + else: + print("No content returned.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: ONENOTE_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_list_notebooks() + + # The following examples require valid IDs: + # await example_2_list_sections() + # await example_3_get_pages_in_section() + # await example_4_create_section() + # await example_5_create_quick_note() + # await example_6_get_page_content() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_orderful.py b/samples/sample_connector_usage/aio/sample_connector_usage_orderful.py new file mode 100644 index 0000000..dca8c0c --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_orderful.py @@ -0,0 +1,31 @@ +"""Orderful sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.orderful import OrderfulClient + + +CONNECTION_RUNTIME_URL = os.environ.get("ORDERFUL_CONNECTION_URL", "") + + +async def main() -> None: + """List Orderful transactions.""" + if not CONNECTION_RUNTIME_URL: + print("Set ORDERFUL_CONNECTION_URL to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with OrderfulClient(CONNECTION_RUNTIME_URL, credential) as client: + await client.list_transactions() + print("Transactions requested.") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_outlook.py b/samples/sample_connector_usage/aio/sample_connector_usage_outlook.py new file mode 100644 index 0000000..92b99b2 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_outlook.py @@ -0,0 +1,233 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Outlook.com sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Outlook client from the Azure Connectors Python SDK +to interact with Outlook.com calendars, contacts, and email. + +Note: This connector is for Outlook.com (personal Microsoft accounts). +For Office 365/work accounts, see the Office 365 Outlook connector. + +Prerequisites: +1. Azure subscription with Outlook connection +2. Outlook connection in Connector Namespaces (with access configured) +3. Connection runtime URL from Azure Portal +4. Microsoft account (Outlook.com/Hotmail/Live) + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:OUTLOOK_CONNECTION_URL = "https://...apihub.net/apim/outlook/..." + + python sample_connector_usage_outlook.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.outlook import OutlookClient +from azure.connectors.outlook import ( + ClientSendHtmlMessage, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/outlook/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "OUTLOOK_CONNECTION_URL", + "" +) + + +async def example_1_list_calendars(): + """Example 1: List available calendars.""" + print("\n=== Example 1: List Calendars ===") + + async with DefaultAzureCredential() as credential: + + async with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_calendar_get_tables()] + + if items: + calendars = items + print(f"Found {len(calendars)} calendar(s):") + for cal in calendars: + name = cal.get("Name", cal.get("name", "N/A")) + cal_id = cal.get("Id", cal.get("id", "N/A")) + print(f" - {name}") + cal_id_str = str(cal_id) + if len(cal_id_str) > 40: + print(f" ID: {cal_id_str[:40]}...") + else: + print(f" ID: {cal_id_str}") + else: + print("No calendars found.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_list_contact_folders(): + """Example 2: List available contact folders.""" + print("\n=== Example 2: List Contact Folders ===") + + async with DefaultAzureCredential() as credential: + + async with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_contact_get_tables()] + + if items: + folders = items + print(f"Found {len(folders)} contact folder(s):") + for folder in folders: + name = folder.get("Name", folder.get("name", "N/A")) + folder_id = folder.get("Id", folder.get("id", "N/A")) + print(f" - {name}") + if len(str(folder_id)) > 40: + print(f" ID: {folder_id[:40]}...") + else: + print(f" ID: {folder_id}") + else: + print("No contact folders found.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_get_calendar_events(): + """Example 3: Get calendar events.""" + print("\n=== Example 3: Get Calendar Events ===") + + # Calendar ID - use 'Calendar' for default calendar or get ID from Example 1 + calendar_id = os.environ.get("OUTLOOK_CALENDAR_ID", "Calendar") + + async with DefaultAzureCredential() as credential: + + async with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_calendar_get_items( + table=calendar_id, + top=5 # Get up to 5 events + )] + + if items: + events = items + print(f"Found {len(events)} event(s) in calendar:") + for event in events[:5]: + subject = event.get("Subject", event.get("subject", "N/A")) + start = event.get("Start", event.get("start", "N/A")) + print(f" - {subject}") + print(f" Start: {start}") + else: + print("No events found.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_get_contacts(): + """Example 4: Get contacts from a contact folder.""" + print("\n=== Example 4: Get Contacts ===") + + # Contact folder ID - use 'Contacts' for default folder or get ID from Example 2 + folder_id = os.environ.get("OUTLOOK_CONTACTS_FOLDER_ID", "Contacts") + + async with DefaultAzureCredential() as credential: + + async with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_contact_get_items( + table=folder_id, + top=10 # Get up to 10 contacts + )] + + if items: + contacts = items + print(f"Found {len(contacts)} contact(s):") + for contact in contacts[:5]: + display_name = contact.get("DisplayName", "N/A") + email = contact.get("EmailAddresses", []) + email_str = email[0].get("Address", "N/A") if email else "N/A" + print(f" - {display_name}") + print(f" Email: {email_str}") + if len(contacts) > 5: + print(f" ... and {len(contacts) - 5} more contacts") + else: + print("No contacts found.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_send_email(): + """Example 5: Send an email.""" + print("\n=== Example 5: Send Email ===") + + recipient = os.environ.get("OUTLOOK_RECIPIENT_EMAIL", "") + if not recipient: + print("Set OUTLOOK_RECIPIENT_EMAIL environment variable to send email.") + print("Example: $env:OUTLOOK_RECIPIENT_EMAIL = 'recipient@example.com'") + print("Skipping email send example...") + return + + async with DefaultAzureCredential() as credential: + + async with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + email = ClientSendHtmlMessage( + to=recipient, + subject="Test from Azure Connectors SDK for Python", + body="

Hello!

" + "

This email was sent using the Azure Connectors SDK.

" + "", + importance="Normal" + ) + + await client.send_email(input=email) + + print("Email sent successfully!") + print(f" To: {recipient}") + print(f" Subject: {email.subject}") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + print("Outlook.com sample usage for the Azure Connectors Python SDK") + print("=" * 60) + + if not CONNECTION_RUNTIME_URL: + print("\nWARNING: OUTLOOK_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL to run actual API calls.") + print("Format: https://[region].azure-apihub.net/apim/outlook/[id]") + return + + await example_1_list_calendars() + await example_2_list_contact_folders() + await example_3_get_calendar_events() + await example_4_get_contacts() + await example_5_send_email() + + print("\n" + "=" * 60) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_pdfco.py b/samples/sample_connector_usage/aio/sample_connector_usage_pdfco.py new file mode 100644 index 0000000..25f65c3 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_pdfco.py @@ -0,0 +1,101 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +PDF.co sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the PDF.co client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a PDF.co connection +2. PDF.co connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:PDFCO_CONNECTION_URL = + "https://[region].azure-apihub.net/apim/pdfco/[connection-id]" + + python sample_connector_usage_pdfco.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.pdfco import PdfcoClient +from azure.connectors.pdfco import ( + HtmlToPdfInput, + UrlToPdfInput, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/pdfco/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("PDFCO_CONNECTION_URL", "") + + +async def example_1_html_to_pdf(): + """Example 1: Convert an HTML snippet to a PDF.""" + print("\n=== Example 1: HTML to PDF ===") + + async with DefaultAzureCredential() as credential: + + async with PdfcoClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + request = HtmlToPdfInput( + html="

Hello from PDF.co

", + ) + + result = await client.html_to_pdf(input=request) + + print(f"HTML to PDF result: {result}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_url_to_pdf(): + """Example 2: Create a PDF from a public URL.""" + print("\n=== Example 2: URL to PDF ===") + + async with DefaultAzureCredential() as credential: + + async with PdfcoClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + request = UrlToPdfInput( + url="https://example.com", + ) + + result = await client.url_to_pdf(input=request) + + print(f"URL to PDF result: {result}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: PDFCO_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_html_to_pdf() + await example_2_url_to_pdf() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_pipedrive.py b/samples/sample_connector_usage/aio/sample_connector_usage_pipedrive.py new file mode 100644 index 0000000..2cb4b15 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_pipedrive.py @@ -0,0 +1,115 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Pipedrive sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Pipedrive client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a Pipedrive connection +2. Pipedrive connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:PIPEDRIVE_CONNECTION_URL = "" + + python sample_connector_usage_pipedrive.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.pipedrive import PipedriveClient +from azure.connectors.pipedrive import ( + AddDealRequest, + ) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/pipedrive/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "PIPEDRIVE_CONNECTION_URL", + "", +) + + +async def example_1_list_deals(): + """Example 1: List deals for the authorized account.""" + print("\n=== Example 1: List Deals ===") + + async with DefaultAzureCredential() as credential: + + async with PipedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_deals()] + + deals = items + print(f"Found {len(deals)} deal(s).") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_get_deal(): + """Example 2: Retrieve a single deal by id.""" + print("\n=== Example 2: Get Deal ===") + + async with DefaultAzureCredential() as credential: + + async with PipedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.get_deal(deal_id=1) + print(f"Deal: {result}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_add_deal(): + """Example 3: Create a new deal for the authorized account.""" + print("\n=== Example 3: Add Deal ===") + + async with DefaultAzureCredential() as credential: + + async with PipedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + new_deal = AddDealRequest( + title="Sample deal", + ) + + result = await client.add_deal(input=new_deal) + print(f"Created deal: {result}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: PIPEDRIVE_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_list_deals() + await example_2_get_deal() + await example_3_add_deal() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_planner.py b/samples/sample_connector_usage/aio/sample_connector_usage_planner.py new file mode 100644 index 0000000..8ee0802 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_planner.py @@ -0,0 +1,236 @@ +""" +Microsoft Planner sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Planner client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Planner connection +2. Planner connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:PLANNER_CONNECTION_URL = "https://[region].azure-apihub.net/apim/planner/[connection-id]" + + python sample_connector_usage_planner.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors.aio.planner import PlannerClient +from azure.connectors.planner import ( + CreateTaskRequest, + CreateBucketInput, + UpdateTaskRequest, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/planner/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "PLANNER_CONNECTION_URL", + "" +) + + +async def example_1_list_my_tasks(): + """Example 1: List all tasks assigned to me""" + print("\n=== Example 1: List My Tasks ===") + + async with DefaultAzureCredential() as credential: + client = PlannerClient(CONNECTION_RUNTIME_URL, credential) + + try: + tasks = [ + task async for task in client.list_my_tasks() + ] + + if tasks: + print(f"Found {len(tasks)} tasks assigned to me") + for task in tasks[:5]: # Show first 5 + print(f" - {task.get('title')} ({task.get('percentComplete')}% complete)") + else: + print("No tasks assigned to me") + + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_list_group_plans(group_id: str): + """Example 2: List all plans in a group""" + print("\n=== Example 2: List Group Plans ===") + + async with DefaultAzureCredential() as credential: + client = PlannerClient(CONNECTION_RUNTIME_URL, credential) + + try: + plans = [plan async for plan in client.list_group_plans(group_id=group_id)] + + if plans: + print(f"Found {len(plans)} plans in group") + for plan in plans[:5]: # Show first 5 + print(f" - {plan.get('title')} ({plan.get('id')})") + else: + print("No plans found in group") + + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_get_task_details(task_id: str): + """Example 3: Get task and task details""" + print("\n=== Example 3: Get Task Details ===") + + async with DefaultAzureCredential() as credential: + client = PlannerClient(CONNECTION_RUNTIME_URL, credential) + + try: + # Get basic task info + task = await client.get_task(id=task_id) + if task: + print(f"Task: {task.get('title')}") + print(f" - Percent Complete: {task.get('percentComplete')}%") + print(f" - Created: {task.get('createdDateTime')}") + + # Get detailed task info + details = await client.get_task_details(id=task_id) + if details: + print(f" - Description: {details.get('description', 'No description')}") + + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_create_bucket(group_id: str, plan_id: str): + """Example 4: Create a new bucket in a plan""" + print("\n=== Example 4: Create Bucket ===") + + async with DefaultAzureCredential() as credential: + client = PlannerClient(CONNECTION_RUNTIME_URL, credential) + + try: + bucket_input = CreateBucketInput( + name="New Bucket", + group_id=group_id, + plan_id=plan_id + ) + + bucket = await client.create_bucket(input=bucket_input) + + if bucket: + print(f"Created bucket: {bucket.get('name')} ({bucket.get('id')})") + + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_create_and_update_task(group_id: str, plan_id: str, bucket_id: str): + """Example 5: Create and update a task""" + print("\n=== Example 5: Create and Update Task ===") + + async with DefaultAzureCredential() as credential: + client = PlannerClient(CONNECTION_RUNTIME_URL, credential) + + try: + # Create a new task + task_input = CreateTaskRequest( + group_id=group_id, + plan_id=plan_id, + bucket_id=bucket_id, + title="Sample Task from SDK", + priority=5, # Medium priority + ) + + task = await client.create_task(input=task_input) + + if task: + task_id = task.get('id') + print(f"Created task: {task.get('title')} ({task_id})") + + # Update the task + update_input = UpdateTaskRequest( + title="Updated Sample Task", + percent_complete=50, + ) + + updated = await client.update_task(input=update_input, id=task_id) + + if updated: + print("Updated task to 50% complete") + + # Clean up - delete the task + await client.delete_task(id=task_id) + print("Deleted task") + + except Exception as ex: + print(f"Error: {ex}") + + +async def example_6_get_plan_details(plan_id: str): + """Example 6: Get plan details""" + print("\n=== Example 6: Get Plan Details ===") + + async with DefaultAzureCredential() as credential: + client = PlannerClient(CONNECTION_RUNTIME_URL, credential) + + try: + details = await client.get_plan_details(id=plan_id) + + if details: + print(f"Plan ID: {details.get('id')}") + categories = details.get('categoryDescriptions', {}) + if categories: + print("Categories:") + for key, value in categories.items(): + if value: + print(f" - {key}: {value}") + + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples""" + print("Planner sample usage for the Azure Connectors Python SDK") + print("=" * 50) + print() + + # Example 1: List my tasks (no parameters needed) + await example_1_list_my_tasks() + + # Examples 2-6 require IDs from your Planner + # Replace these with actual values from your environment + group_id = "" # Microsoft 365 Group ID + plan_id = "" # Plan ID + task_id = "" # Task ID + + if group_id: + await example_2_list_group_plans(group_id) + + if task_id: + await example_3_get_task_details(task_id) + + if plan_id: + await example_6_get_plan_details(plan_id) + + # NOTE: Examples 4 and 5 create resources + # Uncomment to run them with valid IDs: + # bucket_id = "" # Bucket ID + # if group_id and plan_id: + # await example_4_create_bucket(group_id, plan_id) + # if group_id and plan_id and bucket_id: + # await example_5_create_and_update_task(group_id, plan_id, bucket_id) + + print("\n" + "=" * 50) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_plivo.py b/samples/sample_connector_usage/aio/sample_connector_usage_plivo.py new file mode 100644 index 0000000..d9d2fd3 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_plivo.py @@ -0,0 +1,56 @@ +"""Plivo sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.plivo import PlivoClient +from azure.connectors.plivo import SMS + + +CONNECTION_RUNTIME_URL = os.environ.get("PLIVO_CONNECTION_URL", "") + + +async def send_sms() -> None: + """Send an SMS message.""" + async with DefaultAzureCredential() as credential: + async with PlivoClient(CONNECTION_RUNTIME_URL, credential) as client: + result = await client.send_sms( + input=SMS( + src="15550000000", + dst="15551111111", + text="Hello from the Azure Connectors Python SDK.", + ), + auth_id="PLIVO_AUTH_ID", + ) + print(f"Send result: {result}") + + +async def list_messages() -> None: + """List messages for an account.""" + async with DefaultAzureCredential() as credential: + async with PlivoClient(CONNECTION_RUNTIME_URL, credential) as client: + messages = [ + message + async for message in client.list_messages(auth_id="PLIVO_AUTH_ID") + ] + print(f"Messages: {messages}") + + +async def main() -> None: + """Run Plivo connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Set PLIVO_CONNECTION_URL to run this sample.") + return + + try: + await list_messages() + await send_sms() + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_plumsail.py b/samples/sample_connector_usage/aio/sample_connector_usage_plumsail.py new file mode 100644 index 0000000..d7912d8 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_plumsail.py @@ -0,0 +1,100 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Plumsail sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Plumsail client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a Plumsail connection +2. Plumsail connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:PLUMSAIL_CONNECTION_URL = + "https://[region].azure-apihub.net/apim/plumsail/[connection-id]" + + python sample_connector_usage_plumsail.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.plumsail import PlumsailClient +from azure.connectors.plumsail import ( + Pdf2TextRequest, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/plumsail/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("PLUMSAIL_CONNECTION_URL", "") + + +async def example_1_get_profile(): + """Example 1: Get the current account profile.""" + print("\n=== Example 1: Get current profile ===") + + async with DefaultAzureCredential() as credential: + + async with PlumsailClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.profiles_me_get() + + print(f"Profile result: {result}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_extract_text_from_pdf(): + """Example 2: Extract text content from a PDF document.""" + print("\n=== Example 2: Extract text from PDF ===") + + async with DefaultAzureCredential() as credential: + + async with PlumsailClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + request = Pdf2TextRequest( + document_content="", + result_type="Raw", + ) + + poller = await client.begin_flow_v1_documents_jobs_extract_text_from_pdf( + input=request, + ) + result = await poller.result() + + print(f"Extracted text result: {result}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: PLUMSAIL_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_get_profile() + await example_2_extract_text_from_pdf() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_powerbi.py b/samples/sample_connector_usage/aio/sample_connector_usage_powerbi.py new file mode 100644 index 0000000..98471e6 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_powerbi.py @@ -0,0 +1,112 @@ +""" +Power BI sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Power BI client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Power BI connection +2. Power BI connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:POWERBI_CONNECTION_URL = "https://[region].azure-apihub.net/apim/powerbi/[connection-id]" + + python sample_connector_usage_powerbi.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.powerbi import PowerbiClient + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/powerbi/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("POWERBI_CONNECTION_URL", "") + + +async def example_1_list_groups() -> list[dict]: + """Example 1: List Power BI workspaces (groups).""" + print("\n=== Example 1: List Groups ===") + + async with DefaultAzureCredential() as credential: + async with PowerbiClient(CONNECTION_RUNTIME_URL, credential) as client: + groups_response = [item async for item in client.list_groups()] + groups = groups_response + + print(f"Found {len(groups)} groups") + for group in groups[:5]: + print(f" - {group.get('name')} ({group.get('id')})") + + return groups + + +async def example_2_list_datasets(group_id: str) -> list[dict]: + """Example 2: List datasets in a specific workspace.""" + print("\n=== Example 2: List Datasets ===") + + async with DefaultAzureCredential() as credential: + async with PowerbiClient(CONNECTION_RUNTIME_URL, credential) as client: + datasets_response = [item async for item in client.list_datasets(groupid=group_id)] + datasets = datasets_response + + print(f"Found {len(datasets)} datasets in group '{group_id}'") + for dataset in datasets[:5]: + print(f" - {dataset.get('name')} ({dataset.get('id')})") + + return datasets + + +async def example_3_refresh_dataset(group_id: str, dataset_id: str) -> None: + """Example 3: Trigger dataset refresh.""" + print("\n=== Example 3: Refresh Dataset ===") + + async with DefaultAzureCredential() as credential: + async with PowerbiClient(CONNECTION_RUNTIME_URL, credential) as client: + await client.refresh_dataset(groupid=group_id, datasetid=dataset_id) + print(f"Refresh requested for dataset '{dataset_id}'") + + +async def main() -> None: + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: POWERBI_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Power BI sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + groups = await example_1_list_groups() + + if groups: + first_group_id = groups[0].get("id") + if first_group_id: + datasets = await example_2_list_datasets(first_group_id) + + # Optional: trigger a refresh if at least one dataset exists. + if datasets: + first_dataset_id = datasets[0].get("id") + if first_dataset_id: + await example_3_refresh_dataset(first_group_id, first_dataset_id) + else: + print("No group id found in first group record; skipping dataset examples.") + else: + print("No groups found; skipping dataset examples.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_projectplace.py b/samples/sample_connector_usage/aio/sample_connector_usage_projectplace.py new file mode 100644 index 0000000..acfabb3 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_projectplace.py @@ -0,0 +1,103 @@ +""" +Projectplace sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Projectplace client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a Projectplace connection +2. Projectplace connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:PROJECTPLACE_CONNECTION_URL = "https://[region].azure-apihub.net/apim/projectplace/[id]" + + python sample_connector_usage_projectplace.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.projectplace import ProjectplaceClient +from azure.connectors.projectplace import ( + CreateCardInput, + MoveCardInput, + ) + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/projectplace/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("PROJECTPLACE_CONNECTION_URL", "") + + +async def example_1_list_boards() -> None: + """Example 1: List the boards the user has access to.""" + print("\n=== Example 1: List Boards ===") + + async with DefaultAzureCredential() as credential: + async with ProjectplaceClient(CONNECTION_RUNTIME_URL, credential) as client: + boards = [item async for item in client.list_boards()] + print(f"Boards: {boards}") + + +async def example_2_create_card() -> None: + """Example 2: Create a card on a board.""" + print("\n=== Example 2: Create Card ===") + + async with DefaultAzureCredential() as credential: + async with ProjectplaceClient(CONNECTION_RUNTIME_URL, credential) as client: + card = await client.create_card( + input=CreateCardInput( + column_id=123456, + title="SDK sample card", + description="Created from the projectplace SDK sample.", + ), + board_id=789012, + ) + print(f"Created card: {card}") + + +async def example_3_move_card() -> None: + """Example 3: Move a card to another column.""" + print("\n=== Example 3: Move Card ===") + + async with DefaultAzureCredential() as credential: + async with ProjectplaceClient(CONNECTION_RUNTIME_URL, credential) as client: + card = await client.move_card( + input=MoveCardInput(card_id=123456, column_id=654321), + board_id=789012, + ) + print(f"Moved card: {card}") + + +async def main() -> None: + """Run Projectplace connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: PROJECTPLACE_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Projectplace sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + # Uncomment to list boards, create cards, or move cards in Projectplace. + # await example_1_list_boards() + # await example_2_create_card() + # await example_3_move_card() + print("Set the example calls in main() to run against your instance.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_replicon.py b/samples/sample_connector_usage/aio/sample_connector_usage_replicon.py new file mode 100644 index 0000000..dd612c2 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_replicon.py @@ -0,0 +1,31 @@ +"""Replicon sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.replicon import RepliconClient + + +CONNECTION_RUNTIME_URL = os.environ.get("REPLICON_CONNECTION_URL", "") + + +async def main() -> None: + """Get Replicon tenant endpoint details.""" + if not CONNECTION_RUNTIME_URL: + print("Set REPLICON_CONNECTION_URL to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with RepliconClient(CONNECTION_RUNTIME_URL, credential) as client: + endpoint = await client.get_my_tenant_endpoint_details() + print(f"Tenant endpoint: {endpoint}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_revai.py b/samples/sample_connector_usage/aio/sample_connector_usage_revai.py new file mode 100644 index 0000000..64f0aa4 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_revai.py @@ -0,0 +1,52 @@ +"""Rev.ai sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.revai import RevaiClient +from azure.connectors.revai import TranscriptionInput + + +CONNECTION_RUNTIME_URL = os.environ.get("REVAI_CONNECTION_URL", "") + + +async def get_account() -> None: + """Get account information.""" + async with DefaultAzureCredential() as credential: + async with RevaiClient(CONNECTION_RUNTIME_URL, credential) as client: + account = await client.account_get() + print(f"Account: {account}") + + +async def submit_transcription() -> None: + """Submit an audio file for transcription.""" + async with DefaultAzureCredential() as credential: + async with RevaiClient(CONNECTION_RUNTIME_URL, credential) as client: + job = await client.transcription( + input=TranscriptionInput( + source_config={"url": "https://example.com/audio.wav"}, + metadata="connector-sdk-sample", + notification_config={"url": "https://example.com/webhook"}, + ), + ) + print(f"Transcription job: {job}") + + +async def main() -> None: + """Run Rev.ai connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Set REVAI_CONNECTION_URL to run this sample.") + return + + try: + await get_account() + await submit_transcription() + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_rss.py b/samples/sample_connector_usage/aio/sample_connector_usage_rss.py new file mode 100644 index 0000000..228400f --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_rss.py @@ -0,0 +1,38 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Sample usage for the RSS connector client.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors.aio.rss import RssClient + + +async def main() -> None: + """Run a simple RSS sample flow.""" + connection_url = os.getenv("RSS_CONNECTION_URL") + if not connection_url: + raise ValueError("Set RSS_CONNECTION_URL environment variable") + + feed_url = os.getenv("RSS_FEED_URL", "https://devblogs.microsoft.com/python/feed/") + + async with DefaultAzureCredential() as credential: + async with RssClient(connection_url, credential) as client: + items = [item async for item in client.list_feed_items( + feed_url=feed_url, + since_property="PublishDate", + )] + print(f"Retrieved {len(items or [])} item(s) from '{feed_url}'.") + + latest_items = [item async for item in client.list_feed_items( + feed_url=feed_url, + since_property="PublishDate", + )] + values = (latest_items or {}).get("value", []) + print(f"Polling query returned {len(values)} item(s).") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_salesforce.py b/samples/sample_connector_usage/aio/sample_connector_usage_salesforce.py new file mode 100644 index 0000000..69a8565 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_salesforce.py @@ -0,0 +1,140 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Salesforce sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Salesforce client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Salesforce connection +2. Salesforce connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:SALESFORCE_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/salesforce/[connection-id]" + ) + + python sample_connector_usage_salesforce.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.salesforce import SalesforceClient +from azure.connectors.salesforce import ExecuteSoqlQueryParameters + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/salesforce/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "SALESFORCE_CONNECTION_URL", + "", +) + + +async def example_1_get_tables(): + """Example 1: List Salesforce object types.""" + print("\n=== Example 1: Get Tables ===") + + async with DefaultAzureCredential() as credential: + + async with SalesforceClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + tables = [item async for item in client.list_tables()] + + if tables: + print(f"Found {len(tables)} table(s):") + for table in tables[:10]: + print( + f" - {table.get('name')}" + f" ({table.get('displayName', 'no display name')})" + ) + else: + print("No tables found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_get_records(): + """Example 2: Read records from Account table.""" + print("\n=== Example 2: Get Account Records ===") + + async with DefaultAzureCredential() as credential: + + async with SalesforceClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + records = [item async for item in client.list_items( + table="account", + top=5, + select="Id,Name,Phone", + )] + + if records: + print(f"Found {len(records)} account record(s):") + for record in records: + print( + f" - {record.get('Name', 'Unknown')}" + f" (Id: {record.get('Id')})" + ) + else: + print("No account records found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_execute_soql(): + """Example 3: Execute a SOQL query.""" + print("\n=== Example 3: Execute SOQL Query ===") + + async with DefaultAzureCredential() as credential: + + async with SalesforceClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + query_input = ExecuteSoqlQueryParameters( + query="SELECT Id, Name FROM Account LIMIT 5", + ) + result = await client.execute_soql_query(input=query_input) + + if result: + records = result.get("records", []) + print(f"SOQL returned {len(records)} record(s).") + for record in records: + print(f" - {record.get('Name', 'Unknown')} ({record.get('Id')})") + else: + print("SOQL returned no data.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: SALESFORCE_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_get_tables() + await example_2_get_records() + await example_3_execute_soql() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_seismicplanner.py b/samples/sample_connector_usage/aio/sample_connector_usage_seismicplanner.py new file mode 100644 index 0000000..d4dba0c --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_seismicplanner.py @@ -0,0 +1,38 @@ +"""Seismic Planner sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.seismicplanner import SeismicplannerClient + + +CONNECTION_RUNTIME_URL = os.environ.get("SEISMICPLANNER_CONNECTION_URL", "") +SPACE_ID = os.environ.get("SEISMICPLANNER_SPACE_ID", "") + + +async def main() -> None: + """List projects in a Seismic Planner space.""" + if not CONNECTION_RUNTIME_URL or not SPACE_ID: + print("Set SEISMICPLANNER_CONNECTION_URL and SEISMICPLANNER_SPACE_ID to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with SeismicplannerClient( + CONNECTION_RUNTIME_URL, + credential, + ) as client: + projects = [ + project + async for project in client.list_projects(space_id=SPACE_ID) + ] + print(f"Projects: {projects}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_sendgrid.py b/samples/sample_connector_usage/aio/sample_connector_usage_sendgrid.py new file mode 100644 index 0000000..a3f1caa --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_sendgrid.py @@ -0,0 +1,111 @@ +""" +SendGrid sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the SendGrid client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a SendGrid connection +2. SendGrid connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:SENDGRID_CONNECTION_URL = "https://[region].azure-apihub.net/apim/sendgrid/[id]" + + python sample_connector_usage_sendgrid.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.sendgrid import SendgridClient +from azure.connectors.sendgrid import ( + EmailRequest, + ) + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/sendgrid/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("SENDGRID_CONNECTION_URL", "") + + +async def example_1_send_email() -> None: + """Example 1: Send an email.""" + print("\n=== Example 1: Send Email ===") + + async with DefaultAzureCredential() as credential: + async with SendgridClient(CONNECTION_RUNTIME_URL, credential) as client: + result = await client.send_email( + input=EmailRequest( + from_="sender@example.com", + to="recipient@example.com", + subject="Hello from the SDK sample", + text="This message was sent via the SendGrid client from the Azure Connectors Python SDK.", + ishtml=False, + ), + ) + print(f"Send result: {result}") + + +async def example_2_list_recipient_lists() -> None: + """Example 2: List recipient lists.""" + print("\n=== Example 2: List Recipient Lists ===") + + async with DefaultAzureCredential() as credential: + async with SendgridClient(CONNECTION_RUNTIME_URL, credential) as client: + lists = [item async for item in client.list_recipient_lists()] + print(f"Recipient lists: {lists}") + + +async def example_3_list_recipients() -> None: + """Example 3: List recipients.""" + print("\n=== Example 3: List Recipients ===") + + async with DefaultAzureCredential() as credential: + async with SendgridClient(CONNECTION_RUNTIME_URL, credential) as client: + recipients = [item async for item in client.list_recipients()] + print(f"Recipients: {recipients}") + + +async def example_4_get_bounce() -> None: + """Example 4: Get a bounce record for an email address.""" + print("\n=== Example 4: Get Bounce ===") + + async with DefaultAzureCredential() as credential: + async with SendgridClient(CONNECTION_RUNTIME_URL, credential) as client: + bounce = [item async for item in client.list_bounce(email="recipient@example.com")] + print(f"Bounce: {bounce}") + + +async def main() -> None: + """Run SendGrid connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: SENDGRID_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("SendGrid sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + # Uncomment to send email, list recipient lists/recipients, or get bounces. + # await example_1_send_email() + # await example_2_list_recipient_lists() + # await example_3_list_recipients() + # await example_4_get_bounce() + print("Set the example calls in main() to run against your instance.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_servicebus.py b/samples/sample_connector_usage/aio/sample_connector_usage_servicebus.py new file mode 100644 index 0000000..4ae000d --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_servicebus.py @@ -0,0 +1,385 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Azure Service Bus sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Azure Service Bus client from the Azure Connectors Python SDK +to send and receive messages from Azure Service Bus queues and topics. + +Prerequisites: +1. Azure subscription with Azure Service Bus connection +2. Service Bus connection in Connector Namespaces (with access configured) +3. Connection runtime URL from Azure Portal +4. Azure Service Bus namespace with queues and/or topics + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:SERVICEBUS_CONNECTION_URL = "https://...apihub.net/apim/servicebus/..." + $env:SERVICEBUS_QUEUE_NAME = "" + $env:SERVICEBUS_TOPIC_NAME = "" + $env:SERVICEBUS_SUBSCRIPTION_NAME = "" + + python sample_connector_usage_servicebus.py +""" + +import asyncio +import json +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.servicebus import ServicebusClient +from azure.connectors.servicebus import ( + ServiceBusMessage, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/servicebus/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "SERVICEBUS_CONNECTION_URL", + "" +) + +# Service Bus entity names +QUEUE_NAME = os.environ.get("SERVICEBUS_QUEUE_NAME", "") +TOPIC_NAME = os.environ.get("SERVICEBUS_TOPIC_NAME", "") +SUBSCRIPTION_NAME = os.environ.get("SERVICEBUS_SUBSCRIPTION_NAME", "") + + +async def example_1_send_message_to_queue(): + """Example 1: Send a single message to a Service Bus queue.""" + print("\n=== Example 1: Send Message to Queue ===") + + if not QUEUE_NAME: + print("Set SERVICEBUS_QUEUE_NAME environment variable.") + print("Example: $env:SERVICEBUS_QUEUE_NAME = 'my-queue'") + return + + async with DefaultAzureCredential() as credential: + + async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Create a message + message = ServiceBusMessage( + content_data=json.dumps({ + "orderId": "ORD-12345", + "customerId": "CUST-001", + "amount": 99.99, + "timestamp": "2024-01-15T10:30:00Z" + }), + content_type="application/json", + label="order-created", + correlation_id="corr-abc-123" + ) + + await client.send_message( + input=message, + entity_name=QUEUE_NAME + ) + + print(f"Message sent to queue '{QUEUE_NAME}':") + print(f" Content: {message.content_data[:50]}...") + print(f" Label: {message.label}") + print(f" Correlation ID: {message.correlation_id}") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_receive_message_from_queue(): + """Example 2: Receive one queue message with a peek lock.""" + print("\n=== Example 2: Receive Message from Queue ===") + + if not QUEUE_NAME: + print("Set SERVICEBUS_QUEUE_NAME environment variable.") + return + + async with DefaultAzureCredential() as credential: + + async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_messages_from_queue_with_peek_lock( + queue_name=QUEUE_NAME, + max_message_count=1, + )] + messages = items + + if messages: + message = messages[0] + print(f"Message received from queue '{QUEUE_NAME}':") + print(f" Message ID: {message.get('messageId', 'N/A')}") + print(f" Content: {message.get('contentData', 'N/A')}") + print(f" Content Type: {message.get('contentType', 'N/A')}") + print(" Complete or abandon the message by using its lock token.") + else: + print(f"No messages available in queue '{QUEUE_NAME}'.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_receive_with_peek_lock(): + """Example 3: Receive a message with peek-lock and complete it.""" + print("\n=== Example 3: Receive with Peek-Lock and Complete ===") + + if not QUEUE_NAME: + print("Set SERVICEBUS_QUEUE_NAME environment variable.") + return + + async with DefaultAzureCredential() as credential: + + async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Receive message with peek-lock (message is locked, not removed) + items = [item async for item in client.list_messages_from_queue_with_peek_lock( + queue_name=QUEUE_NAME, + max_message_count=1, + )] + messages = items + + if messages: + message = messages[0] + lock_token = message.get("lockToken") + print("Message received with peek-lock:") + print(f" Lock Token: {lock_token}") + print(f" Content: {message.get('contentData', 'N/A')}") + + # Process the message... + print(" Processing message...") + + # Complete the message (remove from queue) + if lock_token: + await client.complete_message_in_queue( + queue_name=QUEUE_NAME, + lock_token=lock_token, + ) + print(" Message completed successfully.") + else: + print(f"No messages available in queue '{QUEUE_NAME}'.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_receive_and_abandon(): + """Example 4: Receive a message and abandon it (return to queue).""" + print("\n=== Example 4: Receive and Abandon Message ===") + + if not QUEUE_NAME: + print("Set SERVICEBUS_QUEUE_NAME environment variable.") + return + + async with DefaultAzureCredential() as credential: + + async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_messages_from_queue_with_peek_lock( + queue_name=QUEUE_NAME, + max_message_count=1, + )] + messages = items + + if messages: + message = messages[0] + lock_token = message.get("lockToken") + print("Message received with peek-lock:") + print(f" Content: {message.get('contentData', 'N/A')}") + + # Abandon the message (return to queue for retry) + if lock_token: + await client.abandon_message_in_queue( + queue_name=QUEUE_NAME, + lock_token=lock_token, + ) + print(" Message abandoned and returned to queue.") + else: + print(f"No messages available in queue '{QUEUE_NAME}'.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_send_message_to_topic(): + """Example 5: Send a message to a Service Bus topic.""" + print("\n=== Example 5: Send Message to Topic ===") + + if not TOPIC_NAME: + print("Set SERVICEBUS_TOPIC_NAME environment variable.") + print("Example: $env:SERVICEBUS_TOPIC_NAME = 'my-topic'") + return + + async with DefaultAzureCredential() as credential: + + async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + message = ServiceBusMessage( + content_data=json.dumps({ + "eventType": "user.created", + "userId": "USR-789", + "email": "user@example.com" + }), + content_type="application/json", + label="user-event" + ) + + await client.send_message( + input=message, + entity_name=TOPIC_NAME + ) + + print(f"Message sent to topic '{TOPIC_NAME}':") + print(f" Content: {message.content_data}") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_6_receive_from_topic_subscription(): + """Example 6: Receive a message from a topic subscription.""" + print("\n=== Example 6: Receive from Topic Subscription ===") + + if not TOPIC_NAME or not SUBSCRIPTION_NAME: + print("Set SERVICEBUS_TOPIC_NAME and SERVICEBUS_SUBSCRIPTION_NAME.") + return + + async with DefaultAzureCredential() as credential: + + async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_messages_from_topic_with_peek_lock( + topic_name=TOPIC_NAME, + subscription_name=SUBSCRIPTION_NAME, + max_message_count=1, + )] + messages = items + + if messages: + message = messages[0] + print(f"Message received from '{TOPIC_NAME}/{SUBSCRIPTION_NAME}':") + print(f" Message ID: {message.get('messageId', 'N/A')}") + print(f" Content: {message.get('contentData', 'N/A')}") + else: + print(f"No messages in subscription '{SUBSCRIPTION_NAME}'.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_7_dead_letter_message(): + """Example 7: Move a message to the dead-letter queue.""" + print("\n=== Example 7: Dead-Letter a Message ===") + + if not QUEUE_NAME: + print("Set SERVICEBUS_QUEUE_NAME environment variable.") + return + + async with DefaultAzureCredential() as credential: + + async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_messages_from_queue_with_peek_lock( + queue_name=QUEUE_NAME, + max_message_count=1, + )] + messages = items + + if messages: + message = messages[0] + lock_token = message.get("lockToken") + print("Message received:") + print(f" Content: {message.get('contentData', 'N/A')}") + + # Move to dead-letter queue + if lock_token: + await client.dead_letter_message_in_queue( + queue_name=QUEUE_NAME, + lock_token=lock_token, + dead_letter_reason="Processing failed", + dead_letter_error_description="Max retries exceeded", + ) + print(" Message moved to dead-letter queue.") + else: + print(f"No messages available in queue '{QUEUE_NAME}'.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_8_batch_receive(): + """Example 8: Receive multiple messages in batch.""" + print("\n=== Example 8: Batch Receive Messages ===") + + if not QUEUE_NAME: + print("Set SERVICEBUS_QUEUE_NAME environment variable.") + return + + async with DefaultAzureCredential() as credential: + + async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_messages_from_queue_with_peek_lock( + queue_name=QUEUE_NAME, + max_message_count=5, + )] + messages = items + + if messages: + print(f"Received {len(messages)} messages from '{QUEUE_NAME}':") + for i, msg in enumerate(messages, 1): + print(f" {i}. {msg.get('contentData', 'N/A')[:50]}...") + else: + print(f"No messages available in queue '{QUEUE_NAME}'.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: SERVICEBUS_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + print("\nExample:") + print('$env:SERVICEBUS_CONNECTION_URL = ') + print(' "https://[region].azure-apihub.net/apim/servicebus/[id]"') + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + # Queue operations + await example_1_send_message_to_queue() + await example_2_receive_message_from_queue() + await example_3_receive_with_peek_lock() + await example_4_receive_and_abandon() + + # Topic operations + await example_5_send_message_to_topic() + await example_6_receive_from_topic_subscription() + + # Advanced operations + await example_7_dead_letter_message() + await example_8_batch_receive() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_sharepoint.py b/samples/sample_connector_usage/aio/sample_connector_usage_sharepoint.py new file mode 100644 index 0000000..7ebdcd3 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_sharepoint.py @@ -0,0 +1,379 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +SharePoint Online sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the SharePoint Online client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with SharePoint Online connection +2. SharePoint Online connection in Connector Namespaces +3. Connection runtime URL from Azure Portal +4. SharePoint site URL + +Installation: + pip install azure-connectors + +Usage: + Set environment variables: + $env:SHAREPOINT_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/sharepointonline/[connection-id]" + ) + $env:SHAREPOINT_SITE_URL = "https://[tenant].sharepoint.com/sites/[site-name]" + + python sample_connector_usage_sharepoint.py +""" + +import asyncio +import os + +try: + from azure.identity.aio import DefaultAzureCredential + from azure.connectors import ConnectorException + from azure.connectors.aio.sharepointonline import SharepointonlineClient + from azure.connectors.sharepointonline import ( + PatchItemInput, + PostItemInput, + ) + IMPORTS_AVAILABLE = True +except ImportError as import_error: + IMPORTS_AVAILABLE = False + IMPORT_ERROR = str(import_error) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/sharepointonline/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "SHAREPOINT_CONNECTION_URL", + "" +) + +# SharePoint site URL format: +# https://[tenant].sharepoint.com/sites/[site-name] +SHAREPOINT_SITE_URL = os.environ.get( + "SHAREPOINT_SITE_URL", + "" +) + + +async def example_1_get_lists(): + """Example 1: Get all lists and libraries from a SharePoint site.""" + print("\n=== Example 1: Get Lists and Libraries ===") + + async with DefaultAzureCredential() as credential: + + async with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + lists = [item async for item in client.list_tables(dataset=SHAREPOINT_SITE_URL)] + + if lists and 'value' in lists: + print(f"Found {len(lists['value'])} lists and libraries:") + for list_item in lists['value'][:5]: + display_name = list_item.get('DisplayName', 'Unknown') + name = list_item.get('Name', 'Unknown') + print(f" - {display_name} ({name})") + else: + print("No lists found or unexpected response format.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + print(f"Status code: {ex.status_code}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_get_list_items(): + """Example 2: Get items from a SharePoint list.""" + print("\n=== Example 2: Get List Items ===") + + list_name = os.environ.get("TEST_LIST_NAME", "18050732-97a3-4509-b510-a094a5a35947") + + async with DefaultAzureCredential() as credential: + + async with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_items( + dataset=SHAREPOINT_SITE_URL, + table=list_name, + )] + + if items: + print(f"Found {len(items)} items in '{list_name}' list:") + for item in items: + title = item.get('Title', 'No Title') + item_id = item.get('Id', 'Unknown') + print(f" - [{item_id}] {title}") + else: + print(f"No items found in '{list_name}' list.") + print("Note: Set TEST_LIST_NAME environment variable to query a different list") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + print(f"Status code: {ex.status_code}") + if ex.status_code == 404: + print(f"Hint: List '{list_name}' may not exist. Check the list name.") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_create_list_item(): + """Example 3: Create a new item in a SharePoint list.""" + print("\n=== Example 3: Create List Item ===") + + list_name = os.environ.get("TEST_LIST_NAME", "Tasks") + + async with DefaultAzureCredential() as credential: + + async with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + new_item = PostItemInput( + additional_properties={'Title': 'Test Task from Python SDK'}, + ) + + created = await client.post_item( + dataset=SHAREPOINT_SITE_URL, + table=list_name, + input=new_item, + ) + + if created and 'Id' in created: + item_id = created['Id'] + print(f"Created item successfully with ID: {item_id}") + print(f"Title: {created.get('Title', 'N/A')}") + + # Clean up: delete the item we just created + await client.delete_item( + dataset=SHAREPOINT_SITE_URL, + table=list_name, + id=int(item_id), + ) + print(f"Cleaned up: Deleted test item {item_id}") + else: + print("Item created but no ID returned.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + if ex.status_code == 404: + print(f"Hint: List '{list_name}' may not exist.") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_update_list_item(): + """Example 4: Create, update, and delete a list item.""" + print("\n=== Example 4: Update List Item (Full CRUD) ===") + + list_name = os.environ.get("TEST_LIST_NAME", "Tasks") + + async with DefaultAzureCredential() as credential: + + async with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # CREATE + print("Creating item...") + new_item = PostItemInput( + additional_properties={'Title': 'Task to Update'}, + ) + created = await client.post_item( + dataset=SHAREPOINT_SITE_URL, + table=list_name, + input=new_item, + ) + item_id = created['Id'] + print(f" Created item {item_id}: {created.get('Title')}") + + # READ + print("Reading item...") + item = await client.get_item( + dataset=SHAREPOINT_SITE_URL, + table=list_name, + id=int(item_id), + ) + print(f" Read item {item_id}: {item.get('Title')}") + + # UPDATE + print("Updating item...") + updates = PatchItemInput( + additional_properties={'Title': 'Updated Task Title'}, + ) + await client.patch_item( + dataset=SHAREPOINT_SITE_URL, + table=list_name, + id=int(item_id), + input=updates, + ) + + # Verify update + updated_item = await client.get_item( + dataset=SHAREPOINT_SITE_URL, + table=list_name, + id=int(item_id), + ) + print(f" Updated item {item_id}: {updated_item.get('Title')}") + + # DELETE + print("Deleting item...") + await client.delete_item( + dataset=SHAREPOINT_SITE_URL, + table=list_name, + id=int(item_id), + ) + print(f" Deleted item {item_id}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + print(f"Status code: {ex.status_code}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_query_with_filters(): + """Example 5: Query list items with OData filters.""" + print("\n=== Example 5: Query with Filters ===") + + list_name = os.environ.get("TEST_LIST_NAME", "Tasks") + + async with DefaultAzureCredential() as credential: + + async with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Create some test items first + print("Creating test items...") + for i in range(3): + await client.post_item( + dataset=SHAREPOINT_SITE_URL, + table=list_name, + input=PostItemInput( + additional_properties={'Title': f'Test Item {i + 1}'}, + ), + ) + print(" Created 3 test items") + + # Query with filters + print("\nQuerying items (ordered by creation date, top 5)...") + items = [item async for item in client.list_items( + dataset=SHAREPOINT_SITE_URL, + table=list_name, + filter=None, + orderby='Created desc', + top=5, + )] + + if items: + print(f"Found {len(items)} items:") + for item in items: + title = item.get('Title', 'No Title') + created = item.get('Created', 'Unknown') + print(f" - {title} (Created: {created})") + + # Clean up test items + print("\nCleaning up test items...") + for item in items[:3]: + if 'Test Item' in item.get('Title', ''): + await client.delete_item( + dataset=SHAREPOINT_SITE_URL, + table=list_name, + id=int(item['Id']), + ) + print(" Cleaned up test items") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + print(f"Status code: {ex.status_code}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_6_file_operations(): + """Example 6: File operations - list folders and get file metadata.""" + print("\n=== Example 6: File Operations ===") + + async with DefaultAzureCredential() as credential: + + async with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # List root folder + print("Listing root folder...") + root_folder = [item async for item in client.list_root_folder(dataset=SHAREPOINT_SITE_URL)] + + if root_folder and 'value' in root_folder: + print(f"Found {len(root_folder['value'])} items in root folder:") + for item in root_folder['value'][:5]: + name = item.get('Name', 'Unknown') + is_folder = item.get('IsFolder', False) + item_type = 'Folder' if is_folder else 'File' + print(f" - {name} ({item_type})") + else: + print("Root folder is empty or unexpected response format.") + + # List a specific folder (Shared Documents is common) + print("\nListing 'Shared Documents' folder...") + folder = [item async for item in client.list_folder( + dataset=SHAREPOINT_SITE_URL, + id='/Shared Documents', + )] + + if folder and 'value' in folder: + print(f"Found {len(folder['value'])} items in Shared Documents:") + for item in folder['value'][:5]: + name = item.get('Name', 'Unknown') + is_folder = item.get('IsFolder', False) + size = item.get('Size', 0) + item_type = 'Folder' if is_folder else 'File' + print(f" - {name} ({item_type}, {size} bytes)") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + print(f"Status code: {ex.status_code}") + if ex.status_code == 404: + print("Hint: The folder may not exist or you may not have access.") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_7_error_handling(): + """Example 7: Demonstrate error handling.""" + print("\n=== Example 7: Error Handling ===") + + async with DefaultAzureCredential() as credential: + + async with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Attempt to get an item with an invalid ID + invalid_item_id = 99999 + list_name = os.environ.get("TEST_LIST_NAME", "Tasks") + + item = await client.get_item( + dataset=SHAREPOINT_SITE_URL, + table=list_name, + id=invalid_item_id, + ) + print(f"Unexpected success: {item}") + + except ConnectorException as ex: + print("Expected error caught:") + print(f" Message: {ex}") + except Exception as ex: + print(f"Unexpected error type: {type(ex).__name__}") + print(f" Message: {ex}") + + +async def main(): + """Run all examples.""" + print("SharePoint Online sample usage for the Azure Connectors Python SDK") + print("=" * 50) + print() + + await example_1_get_lists() + await example_2_get_list_items() + await example_3_create_list_item() + await example_4_update_list_item() + await example_5_query_with_filters() + await example_6_file_operations() + await example_7_error_handling() + + print("\n" + "=" * 50) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_shifts.py b/samples/sample_connector_usage/aio/sample_connector_usage_shifts.py new file mode 100644 index 0000000..fbf34a8 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_shifts.py @@ -0,0 +1,110 @@ +""" +Shifts sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Shifts client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Shifts connection +2. Shifts connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:SHIFTS_CONNECTION_URL = "https://[region].azure-apihub.net/apim/shifts/[connection-id]" + + python sample_connector_usage_shifts.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.shifts import ShiftsClient + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/shifts/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("SHIFTS_CONNECTION_URL", "") + + +async def example_1_list_teams() -> list[dict]: + """Example 1: List joined teams.""" + print("\n=== Example 1: List Teams ===") + + async with DefaultAzureCredential() as credential: + async with ShiftsClient(CONNECTION_RUNTIME_URL, credential) as client: + teams = [team async for team in client.list_all_teams()] + + print(f"Found {len(teams)} teams") + for team in teams[:10]: + print(f" - {team.get('displayName')} ({team.get('id')})") + + return teams + + +async def example_2_get_schedule(team_id: str) -> None: + """Example 2: Get a team's schedule.""" + print("\n=== Example 2: Get Schedule ===") + + async with DefaultAzureCredential() as credential: + async with ShiftsClient(CONNECTION_RUNTIME_URL, credential) as client: + schedule = await client.get_schedule(team_id=team_id) + + if not schedule: + print("No schedule returned") + return + + print(f"Schedule ID: {schedule.get('id')}") + print(f"Time Zone: {schedule.get('timeZone')}") + print(f"Provision Status: {schedule.get('provisionStatus')}") + + +async def example_3_list_shifts(team_id: str) -> None: + """Example 3: List shifts for a team.""" + print("\n=== Example 3: List Shifts ===") + + async with DefaultAzureCredential() as credential: + async with ShiftsClient(CONNECTION_RUNTIME_URL, credential) as client: + shifts_response = [item async for item in client.list_shifts(team_id=team_id, top=10)] + shifts = shifts_response if shifts_response else [] + + print(f"Found {len(shifts)} shifts") + for shift in shifts[:10]: + print(f" - {shift.get('id')} assigned to {shift.get('userId')}") + + +async def main() -> None: + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: SHIFTS_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Shifts sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + teams = await example_1_list_teams() + if teams: + first_team_id = teams[0].get("id") + if first_team_id: + await example_2_get_schedule(first_team_id) + await example_3_list_shifts(first_team_id) + else: + print("No team id found in first record; skipping team-specific examples.") + else: + print("No teams found; skipping team-specific examples.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_signinghub.py b/samples/sample_connector_usage/aio/sample_connector_usage_signinghub.py new file mode 100644 index 0000000..81c20e2 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_signinghub.py @@ -0,0 +1,132 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +SigningHub sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the SigningHub client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a SigningHub connection +2. SigningHub connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:SIGNINGHUB_CONNECTION_URL = + "https://[region].azure-apihub.net/apim/signinghub/[connection-id]" + + python sample_connector_usage_signinghub.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.signinghub import SigninghubClient +from azure.connectors.signinghub import ( + CheckBoxFieldRequest, + FieldDimension, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/signinghub/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("SIGNINGHUB_CONNECTION_URL", "") + + +async def example_1_get_contacts(): + """Example 1: Retrieve contacts for the current user.""" + print("\n=== Example 1: Get Contacts ===") + + async with DefaultAzureCredential() as credential: + + async with SigninghubClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_contacts_get( + record_per_page=10, + page_no=1, + )] + + print(f"Contacts result: {items}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_add_check_box_field(): + """Example 2: Add a checkbox field to a document in a package.""" + print("\n=== Example 2: Add CheckBox Field ===") + + async with DefaultAzureCredential() as credential: + + async with SigninghubClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + request = CheckBoxFieldRequest( + order=1, + page_no=1, + dimensions=FieldDimension(x=120.0, y=220.0, width=18.0, height=18.0), + field_name="Approve", + value="false", + validation_rule="none", + ) + + result = await client.checkbox_add_check_box( + input=request, + package_id=12345, + document_id=67890, + ) + + print(f"Add checkbox result: {result}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_delete_attachment(): + """Example 3: Delete an attachment from a document.""" + print("\n=== Example 3: Delete Attachment ===") + + async with DefaultAzureCredential() as credential: + + async with SigninghubClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + await client.attachment_delete_attachment( + package_id=12345, + document_id=67890, + attachment_id=13579, + ) + + print("Attachment deleted successfully") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: SIGNINGHUB_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_get_contacts() + await example_2_add_check_box_field() + await example_3_delete_attachment() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_slack.py b/samples/sample_connector_usage/aio/sample_connector_usage_slack.py new file mode 100644 index 0000000..dd1c7e9 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_slack.py @@ -0,0 +1,104 @@ +""" +Slack sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Slack client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Slack connection +2. Slack connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:SLACK_CONNECTION_URL = "https://[region].azure-apihub.net/apim/slack/[connection-id]" + + python sample_connector_usage_slack.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.slack import SlackClient +from azure.connectors.slack import PostMessageRequest + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/slack/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("SLACK_CONNECTION_URL", "") + + +async def example_1_list_channels() -> None: + """Example 1: List channels.""" + print("\n=== Example 1: List Channels ===") + + async with DefaultAzureCredential() as credential: + async with SlackClient(CONNECTION_RUNTIME_URL, credential) as client: + channels_response = [item async for item in client.list_channels()] + channels = channels_response if channels_response else [] + + print(f"Found {len(channels)} channels") + for channel in channels[:5]: + print(f" - {channel.get('name')} ({channel.get('id')})") + + +async def example_2_create_channel() -> None: + """Example 2: Create a channel.""" + print("\n=== Example 2: Create Channel ===") + + async with DefaultAzureCredential() as credential: + async with SlackClient(CONNECTION_RUNTIME_URL, credential) as client: + created = await client.create_channel( + name="sdk-sample-channel", + is_private=False, + ) + channel = created.get("channel", {}) if created else {} + print(f"Created channel: {channel.get('name')} ({channel.get('id')})") + + +async def example_3_post_message() -> None: + """Example 3: Post a message to a channel.""" + print("\n=== Example 3: Post Message ===") + + async with DefaultAzureCredential() as credential: + async with SlackClient(CONNECTION_RUNTIME_URL, credential) as client: + payload = PostMessageRequest( + channel="#general", + text="Hello from Slack Python SDK sample", + ) + posted = await client.post_message(input=payload) + print( + f"Posted result: {posted}; " + f"ts={posted.get('ts') if posted else None}" + ) + + +async def main() -> None: + """Run Slack connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: SLACK_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Slack sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + await example_1_list_channels() + # Uncomment after confirming your app has channel-create permission. + # await example_2_create_channel() + await example_3_post_message() + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_smtp.py b/samples/sample_connector_usage/aio/sample_connector_usage_smtp.py new file mode 100644 index 0000000..695f356 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_smtp.py @@ -0,0 +1,297 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +SMTP sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the SMTP client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with SMTP connection +2. SMTP connection in Connector Namespaces (with credentials configured) +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:SMTP_CONNECTION_URL = "https://[region].azure-apihub.net/apim/smtp/[connection-id]" + + python sample_connector_usage_smtp.py +""" + +import asyncio +import base64 +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.smtp import SmtpClient +from azure.connectors.smtp import ( + Email, + Attachment, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/smtp/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "SMTP_CONNECTION_URL", + "" +) + + +async def example_1_send_basic_email(): + """Example 1: Send a basic email.""" + print("\n=== Example 1: Send Basic Email ===") + + sender = os.environ.get("TEST_SMTP_FROM", "") + recipient = os.environ.get("TEST_SMTP_TO", "") + + if not sender or not recipient: + print("Set environment variables to send an email:") + print(" $env:TEST_SMTP_FROM = 'sender@yourdomain.com'") + print(" $env:TEST_SMTP_TO = 'recipient@example.com'") + return + + async with DefaultAzureCredential() as credential: + + async with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + email = Email( + from_=sender, + to=recipient, + subject="Test Email from Azure Connectors SDK", + body="Hello! This is a test email sent via the Azure Connectors SDK for Python.", + ) + + await client.send_email(input=email) + + print("Email sent successfully:") + print(f" From: {sender}") + print(f" To: {recipient}") + print(f" Subject: {email.subject}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_send_email_with_cc_bcc(): + """Example 2: Send an email with CC and BCC recipients.""" + print("\n=== Example 2: Send Email with CC/BCC ===") + + sender = os.environ.get("TEST_SMTP_FROM", "") + recipient = os.environ.get("TEST_SMTP_TO", "") + cc_recipient = os.environ.get("TEST_SMTP_CC", "") + bcc_recipient = os.environ.get("TEST_SMTP_BCC", "") + + if not sender or not recipient: + print("Set environment variables to send an email:") + print(" $env:TEST_SMTP_FROM = 'sender@yourdomain.com'") + print(" $env:TEST_SMTP_TO = 'recipient@example.com'") + print(" $env:TEST_SMTP_CC = 'cc@example.com' (optional)") + print(" $env:TEST_SMTP_BCC = 'bcc@example.com' (optional)") + return + + async with DefaultAzureCredential() as credential: + + async with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + email = Email( + from_=sender, + to=recipient, + c_c=cc_recipient if cc_recipient else None, + bcc=bcc_recipient if bcc_recipient else None, + subject="Test Email with CC/BCC", + body="This email demonstrates CC and BCC functionality.", + ) + + await client.send_email(input=email) + + print("Email sent successfully:") + print(f" From: {sender}") + print(f" To: {recipient}") + if cc_recipient: + print(f" CC: {cc_recipient}") + if bcc_recipient: + print(f" BCC: {bcc_recipient}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_send_html_email(): + """Example 3: Send an HTML-formatted email.""" + print("\n=== Example 3: Send HTML Email ===") + + sender = os.environ.get("TEST_SMTP_FROM", "") + recipient = os.environ.get("TEST_SMTP_TO", "") + + if not sender or not recipient: + print("Set environment variables to send an email:") + print(" $env:TEST_SMTP_FROM = 'sender@yourdomain.com'") + print(" $env:TEST_SMTP_TO = 'recipient@example.com'") + return + + async with DefaultAzureCredential() as credential: + + async with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + html_body = """ + + + + + +

Azure Connectors SDK

+
+

This is an HTML-formatted email.

+
    +
  • Feature 1: Easy to use
  • +
  • Feature 2: Async support
  • +
  • Feature 3: Type safety
  • +
+
+ + + """ + + email = Email( + from_=sender, + to=recipient, + subject="HTML Email from Azure Connectors SDK", + body=html_body.strip(), + ) + + await client.send_email(input=email) + + print("HTML email sent successfully:") + print(f" From: {sender}") + print(f" To: {recipient}") + print(f" Subject: {email.subject}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_send_email_with_attachment(): + """Example 4: Send an email with an attachment.""" + print("\n=== Example 4: Send Email with Attachment ===") + + sender = os.environ.get("TEST_SMTP_FROM", "") + recipient = os.environ.get("TEST_SMTP_TO", "") + + if not sender or not recipient: + print("Set environment variables to send an email:") + print(" $env:TEST_SMTP_FROM = 'sender@yourdomain.com'") + print(" $env:TEST_SMTP_TO = 'recipient@example.com'") + return + + async with DefaultAzureCredential() as credential: + + async with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Create a sample text file content + file_content = "This is a sample attachment created by Azure Connectors SDK." + encoded_content = base64.b64encode(file_content.encode()).decode() + + attachment = Attachment( + file_name="sample.txt", + content_data=encoded_content, + content_type="text/plain", + ) + + email = Email( + from_=sender, + to=recipient, + subject="Email with Attachment", + body="Please find the attached file.", + attachments=[attachment], + ) + + await client.send_email(input=email) + + print("Email with attachment sent successfully:") + print(f" From: {sender}") + print(f" To: {recipient}") + print(f" Attachment: {attachment.file_name}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_send_email_with_options(): + """Example 5: Send an email with importance and receipts.""" + print("\n=== Example 5: Send Email with Options ===") + + sender = os.environ.get("TEST_SMTP_FROM", "") + recipient = os.environ.get("TEST_SMTP_TO", "") + + if not sender or not recipient: + print("Set environment variables to send an email:") + print(" $env:TEST_SMTP_FROM = 'sender@yourdomain.com'") + print(" $env:TEST_SMTP_TO = 'recipient@example.com'") + return + + async with DefaultAzureCredential() as credential: + + async with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + email = Email( + from_=sender, + to=recipient, + subject="High Importance Email", + body="This is a high-importance email with read receipt requested.", + importance="High", + read_receipt=sender, + delivery_receipt=sender, + ) + + await client.send_email(input=email) + + print("Email with options sent successfully:") + print(f" From: {sender}") + print(f" To: {recipient}") + print(f" Importance: {email.importance}") + print(f" Read Receipt: {email.read_receipt}") + print(f" Delivery Receipt: {email.delivery_receipt}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + print("SMTP sample usage for the Azure Connectors Python SDK") + print("=" * 60) + + if not CONNECTION_RUNTIME_URL: + print("\nWARNING: SMTP_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL to run actual API calls.") + print("Format: https://[region].azure-apihub.net/apim/smtp/[connection-id]") + return + + await example_1_send_basic_email() + await example_2_send_email_with_cc_bcc() + await example_3_send_html_email() + await example_4_send_email_with_attachment() + await example_5_send_email_with_options() + + print("\n" + "=" * 60) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_sql.py b/samples/sample_connector_usage/aio/sample_connector_usage_sql.py new file mode 100644 index 0000000..bb9fe58 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_sql.py @@ -0,0 +1,215 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +SQL Server sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the SQL Server client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a SQL Server connection +2. SQL Server connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:SQL_CONNECTION_URL = ( + "https://[region].azure-apihub.net/apim/sql/[connection-id]" + ) + + python sample_connector_usage_sql.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.sql import SqlClient +from azure.connectors.sql import ( + ExecuteProcedureInput, + PatchItemInput, + PostItemInput, + SqlPassThroughNativeQueryBody, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/sql/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "SQL_CONNECTION_URL", + "", +) + +# Target server/database/table used by the data examples. +SERVER = os.environ.get("SQL_SERVER", "") +DATABASE = os.environ.get("SQL_DATABASE", "") +TABLE = os.environ.get("SQL_TABLE", "") + + +async def example_1_list_servers_and_databases(): + """Example 1: Discover servers, databases, and tables.""" + print("\n=== Example 1: List Servers, Databases, and Tables ===") + + async with DefaultAzureCredential() as credential: + + async with SqlClient(CONNECTION_RUNTIME_URL, credential) as client: + servers = [item async for item in client.list_servers()] + server_values = servers + print(f"Found {len(server_values)} server(s).") + + if not SERVER: + print("Set SQL_SERVER to list databases and tables.") + return + + databases = [item async for item in client.list_databases(server=SERVER)] + database_values = databases + print(f"Found {len(database_values)} database(s) on '{SERVER}'.") + + if not DATABASE: + print("Set SQL_DATABASE to list tables.") + return + + table_values = [ + table + async for table in client.list_tables( + server=SERVER, + database=DATABASE, + ) + ] + print(f"Found {len(table_values)} table(s) in '{DATABASE}'.") + for table in table_values[:10]: + print(f" - {table.get('DisplayName', table.get('Name', 'N/A'))}") + + +async def example_2_read_rows(): + """Example 2: Read rows from a table.""" + print("\n=== Example 2: Get Rows ===") + + if not (SERVER and DATABASE and TABLE): + print("Set SQL_SERVER, SQL_DATABASE, and SQL_TABLE to run this example.") + return + + async with DefaultAzureCredential() as credential: + + async with SqlClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + rows = [item async for item in client.list_items( + server=SERVER, + database=DATABASE, + table=TABLE, + top=5, + orderby="Id desc", + )] + print(f"Retrieved {len(rows)} row(s) from '{TABLE}'.") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def example_3_insert_update_delete_row(): + """Example 3: Insert, update, and delete a row.""" + print("\n=== Example 3: Insert, Update, and Delete a Row ===") + + if not (SERVER and DATABASE and TABLE): + print("Set SQL_SERVER, SQL_DATABASE, and SQL_TABLE to run this example.") + return + + async with DefaultAzureCredential() as credential: + + async with SqlClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + inserted = await client.post_item( + input=PostItemInput( + additional_properties={"Name": "Contoso", "Status": "Active"}, + ), + server=SERVER, + database=DATABASE, + table=TABLE, + ) + row_id = str((inserted or {}).get("Id", "")) if inserted else "" + print(f"Inserted row id: {row_id or 'N/A'}") + + if not row_id: + return + + await client.patch_item( + input=PatchItemInput(additional_properties={"Status": "Updated"}), + server=SERVER, + database=DATABASE, + table=TABLE, + id=row_id, + ) + print(f"Updated row id: {row_id}") + + await client.delete_item( + server=SERVER, + database=DATABASE, + table=TABLE, + id=row_id, + ) + print(f"Deleted row id: {row_id}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def example_4_query_and_procedures(): + """Example 4: Execute a pass-through query and stored procedures.""" + print("\n=== Example 4: Query and Stored Procedures ===") + + if not (SERVER and DATABASE): + print("Set SQL_SERVER and SQL_DATABASE to run this example.") + return + + async with DefaultAzureCredential() as credential: + + async with SqlClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + query_result = await client.execute_pass_through_native_query( + input=SqlPassThroughNativeQueryBody(query="SELECT TOP 1 * FROM sys.tables"), + server=SERVER, + database=DATABASE, + ) + result_sets = (query_result or {}).get("resultSets", {}) + print(f"Query returned {len(result_sets)} result set(s).") + + procedures = [item async for item in client.list_procedures_v2( + server=SERVER, + database=DATABASE, + )] + procedure_values = procedures + print(f"Found {len(procedure_values)} stored procedure(s).") + + if procedure_values: + procedure_name = procedure_values[0].get("Name") + if procedure_name: + await client.execute_procedure( + input=ExecuteProcedureInput(), + server=SERVER, + database=DATABASE, + procedure=procedure_name, + ) + print(f"Executed stored procedure '{procedure_name}'.") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +async def main(): + """Run all SQL Server connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: SQL_CONNECTION_URL environment variable is not set.") + print("Set it to your SQL Server connector runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_list_servers_and_databases() + await example_2_read_rows() + await example_3_insert_update_delete_row() + await example_4_query_and_procedures() + + print("\n=== SQL Server sample completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_starmind.py b/samples/sample_connector_usage/aio/sample_connector_usage_starmind.py new file mode 100644 index 0000000..3da9526 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_starmind.py @@ -0,0 +1,51 @@ +"""Starmind sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.starmind import StarmindClient +from azure.connectors.starmind import FindExpertsInput + + +CONNECTION_RUNTIME_URL = os.environ.get("STARMIND_CONNECTION_URL", "") + + +async def find_questions() -> None: + """Find questions matching a query.""" + async with DefaultAzureCredential() as credential: + async with StarmindClient(CONNECTION_RUNTIME_URL, credential) as client: + questions = await client.find_questions( + query="distributed systems", + limit=10, + ) + print(f"Questions: {questions}") + + +async def find_experts() -> None: + """Find experts for a topic.""" + async with DefaultAzureCredential() as credential: + async with StarmindClient(CONNECTION_RUNTIME_URL, credential) as client: + experts = await client.find_experts( + input=FindExpertsInput(text_query="distributed systems"), + ) + print(f"Experts: {experts}") + + +async def main() -> None: + """Run Starmind connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Set STARMIND_CONNECTION_URL to run this sample.") + return + + try: + await find_questions() + await find_experts() + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_starrezrestv1.py b/samples/sample_connector_usage/aio/sample_connector_usage_starrezrestv1.py new file mode 100644 index 0000000..db9138f --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_starrezrestv1.py @@ -0,0 +1,41 @@ +"""StarRez REST V1 sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.starrezrestv1 import Starrezrestv1Client +from azure.connectors.starrezrestv1 import SelectBookingInput + + +CONNECTION_RUNTIME_URL = os.environ.get("STARREZRESTV1_CONNECTION_URL", "") + + +async def main() -> None: + """List up to ten StarRez bookings.""" + if not CONNECTION_RUNTIME_URL: + print("Set STARREZRESTV1_CONNECTION_URL to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with Starrezrestv1Client( + CONNECTION_RUNTIME_URL, + credential, + ) as client: + bookings = [item async for item in client.list_select_booking( + input=SelectBookingInput( + return_empty_array_on_no_result=True, + page_size=10, + page_index=1, + ) + )] + print(f"Bookings: {bookings}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_tallyfy.py b/samples/sample_connector_usage/aio/sample_connector_usage_tallyfy.py new file mode 100644 index 0000000..0dad5ba --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_tallyfy.py @@ -0,0 +1,53 @@ +"""Tallyfy sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.tallyfy import TallyfyClient +from azure.connectors.tallyfy import CreateRunInput + + +CONNECTION_RUNTIME_URL = os.environ.get("TALLYFY_CONNECTION_URL", "") + + +async def list_organizations() -> None: + """List organizations available to the current user.""" + async with DefaultAzureCredential() as credential: + async with TallyfyClient(CONNECTION_RUNTIME_URL, credential) as client: + organizations = await client.get_user_organizations() + print(f"Organizations: {organizations}") + + +async def create_run() -> None: + """Create a run from a checklist.""" + async with DefaultAzureCredential() as credential: + async with TallyfyClient(CONNECTION_RUNTIME_URL, credential) as client: + run = await client.create_run( + input=CreateRunInput( + name="Quarterly review", + checklist_id="CHECKLIST_ID", + summary="Created with the Azure Connectors Python SDK.", + ), + org="ORGANIZATION_ID", + ) + print(f"Created run: {run}") + + +async def main() -> None: + """Run Tallyfy connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Set TALLYFY_CONNECTION_URL to run this sample.") + return + + try: + await list_organizations() + await create_run() + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_teams.py b/samples/sample_connector_usage/aio/sample_connector_usage_teams.py new file mode 100644 index 0000000..bee8b62 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_teams.py @@ -0,0 +1,77 @@ +""" +Microsoft Teams sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Teams client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Teams connection +2. Teams connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + python sample_teams_usage.py +""" + +import asyncio +from azure.identity.aio import DefaultAzureCredential +from azure.connectors.aio.teams import TeamsClient + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/teams/[connection-id] +CONNECTION_RUNTIME_URL = "" + + +async def example_1_list_joined_teams(): + """Example 1: List all Teams you're a member of""" + print("\n=== Example 1: List Joined Teams ===") + + async with DefaultAzureCredential() as credential: + client = TeamsClient(CONNECTION_RUNTIME_URL, credential) + + try: + teams = [team async for team in client.list_all_teams()] + + print(f"Found {len(teams)} teams") + for team in teams[:3]: # Show first 3 + print(f" - {team.get('displayName')} ({team.get('id')})") + + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_list_associated_teams(): + """Example 2: List associated teams (direct membership + shared channels)""" + print("\n=== Example 2: List Associated Teams ===") + + async with DefaultAzureCredential() as credential: + client = TeamsClient(CONNECTION_RUNTIME_URL, credential) + + try: + teams = [team async for team in client.list_all_associated_teams()] + + print(f"Found {len(teams)} associated teams") + for team in teams[:3]: # Show first 3 + print(f" - {team.get('displayName')}") + + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples""" + print("Teams sample usage for the Azure Connectors Python SDK") + print("=" * 50) + print() + + await example_1_list_joined_teams() + await example_2_list_associated_teams() + + print("\n" + "=" * 50) + print("Sample completed!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_textrequest.py b/samples/sample_connector_usage/aio/sample_connector_usage_textrequest.py new file mode 100644 index 0000000..7ee8f91 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_textrequest.py @@ -0,0 +1,136 @@ +""" +TextRequest sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the TextRequest client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a TextRequest connection +2. TextRequest connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:TEXTREQUEST_CONNECTION_URL = "https://[region].azure-apihub.net/apim/textrequest/[id]" + + python sample_connector_usage_textrequest.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.textrequest import TextrequestClient +from azure.connectors.textrequest import ( + CreateContactInput, + SendMessageByPhoneNumberInput, + ) + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/textrequest/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("TEXTREQUEST_CONNECTION_URL", "") + +# The id of the dashboard to make calls on. +DASHBOARD_ID = int(os.environ.get("TEXTREQUEST_DASHBOARD_ID", "0")) + + +async def example_1_send_message() -> None: + """Example 1: Send a message to a contact by phone number.""" + print("\n=== Example 1: Send Message ===") + + async with DefaultAzureCredential() as credential: + async with TextrequestClient(CONNECTION_RUNTIME_URL, credential) as client: + result = await client.send_message_by_phone_number( + input=SendMessageByPhoneNumberInput( + body="Hello from the TextRequest client in the Azure Connectors Python SDK.", + sender_name="Support Team", + ), + dashboard_id=DASHBOARD_ID, + phone_number="+15553334444", + ) + print(f"Send result: {result}") + + +async def example_2_get_conversations() -> None: + """Example 2: List all conversations for the dashboard.""" + print("\n=== Example 2: Get Conversations ===") + + async with DefaultAzureCredential() as credential: + async with TextrequestClient(CONNECTION_RUNTIME_URL, credential) as client: + conversations = [ + conversation + async for conversation in client.list_conversations( + dashboard_id=DASHBOARD_ID, + page=1, + page_size=20, + ) + ] + print(f"Conversations: {conversations}") + + +async def example_3_create_contact() -> None: + """Example 3: Create or update a contact.""" + print("\n=== Example 3: Create Contact ===") + + async with DefaultAzureCredential() as credential: + async with TextrequestClient(CONNECTION_RUNTIME_URL, credential) as client: + result = await client.create_contact( + input=CreateContactInput( + first_name="Ada", + last_name="Lovelace", + display_name="Ada Lovelace", + ), + dashboard_id=DASHBOARD_ID, + phone_number="+15553334444", + ) + print(f"Contact result: {result}") + + +async def example_4_get_dashboards() -> None: + """Example 4: Get all dashboards in the account.""" + print("\n=== Example 4: Get Dashboards ===") + + async with DefaultAzureCredential() as credential: + async with TextrequestClient(CONNECTION_RUNTIME_URL, credential) as client: + dashboards = [ + dashboard + async for dashboard in client.list_dashboards( + page=1, + page_size=20, + ) + ] + print(f"Dashboards: {dashboards}") + + +async def main() -> None: + """Run TextRequest connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: TEXTREQUEST_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("TextRequest sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + # Uncomment to send a message, list conversations, create a contact, + # or list dashboards. + # await example_1_send_message() + # await example_2_get_conversations() + # await example_3_create_contact() + # await example_4_get_dashboards() + print("Set the example calls in main() to run against your instance.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_ticketmaster.py b/samples/sample_connector_usage/aio/sample_connector_usage_ticketmaster.py new file mode 100644 index 0000000..92fe2aa --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_ticketmaster.py @@ -0,0 +1,31 @@ +"""Ticketmaster sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.ticketmaster import TicketmasterClient + + +CONNECTION_RUNTIME_URL = os.environ.get("TICKETMASTER_CONNECTION_URL", "") + + +async def main() -> None: + """List Ticketmaster attractions.""" + if not CONNECTION_RUNTIME_URL: + print("Set TICKETMASTER_CONNECTION_URL to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with TicketmasterClient(CONNECTION_RUNTIME_URL, credential) as client: + attractions = await client.attractions_get() + print(f"Attractions: {attractions}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_todo.py b/samples/sample_connector_usage/aio/sample_connector_usage_todo.py new file mode 100644 index 0000000..fafc73e --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_todo.py @@ -0,0 +1,124 @@ +""" +Microsoft To Do sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Microsoft To Do client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Microsoft To Do connection +2. Microsoft To Do connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:TODO_CONNECTION_URL = "https://[region].azure-apihub.net/apim/todo/[connection-id]" + + python sample_connector_usage_todo.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.todo import TodoClient +from azure.connectors.todo import CreateToDo, CreateToDoList, UpdateToDo + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/todo/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("TODO_CONNECTION_URL", "") + + +async def example_1_list_lists() -> list[dict]: + """Example 1: List all to-do lists.""" + print("\n=== Example 1: List To-Do Lists ===") + + async with DefaultAzureCredential() as credential: + async with TodoClient(CONNECTION_RUNTIME_URL, credential) as client: + lists_response = [item async for item in client.list_all_todo_lists()] + lists = lists_response + + print(f"Found {len(lists)} lists") + for todo_list in lists[:10]: + print(f" - {todo_list.get('displayName')} ({todo_list.get('id')})") + + return lists + + +async def example_2_create_list() -> str | None: + """Example 2: Create a to-do list.""" + print("\n=== Example 2: Create To-Do List ===") + + async with DefaultAzureCredential() as credential: + async with TodoClient(CONNECTION_RUNTIME_URL, credential) as client: + request = CreateToDoList(display_name="SDK Sample List") + created = await client.create_to_do_list(input=request) + + if not created: + print("No list was created") + return None + + list_id = created.get("id") + print(f"Created list id: {list_id}") + return list_id + + +async def example_3_create_and_update_todo(list_id: str) -> None: + """Example 3: Create and update a to-do item.""" + print("\n=== Example 3: Create And Update To-Do ===") + + async with DefaultAzureCredential() as credential: + async with TodoClient(CONNECTION_RUNTIME_URL, credential) as client: + create_request = CreateToDo(title="SDK sample task", status="notStarted") + created_todo = await client.create_to_do(input=create_request, folder_id=list_id) + + if not created_todo: + print("No to-do item returned from create operation") + return + + todo_id = created_todo.get("id") + print(f"Created to-do id: {todo_id}") + + if not todo_id: + return + + update_request = UpdateToDo(title="SDK sample task (updated)", status="inProgress") + updated_todo = await client.update_to_do( + input=update_request, + folder_id=list_id, + id=todo_id, + ) + print(f"Updated title: {updated_todo.get('title') if updated_todo else 'n/a'}") + + +async def main() -> None: + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: TODO_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Microsoft To Do sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + await example_1_list_lists() + list_id = await example_2_create_list() + + if list_id: + await example_3_create_and_update_todo(list_id) + else: + print("Skipping to-do create/update because no list id was returned.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_trello.py b/samples/sample_connector_usage/aio/sample_connector_usage_trello.py new file mode 100644 index 0000000..9950e82 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_trello.py @@ -0,0 +1,120 @@ +""" +Trello sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Trello client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a Trello connection +2. Trello connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:TRELLO_CONNECTION_URL = "https://[region].azure-apihub.net/apim/trello/[id]" + + python sample_connector_usage_trello.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.trello import TrelloClient +from azure.connectors.trello import CreateBoard, CreateCard, CreateList + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/trello/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("TRELLO_CONNECTION_URL", "") + + +async def example_1_list_boards() -> None: + """Example 1: List boards available to the current member.""" + print("\n=== Example 1: List Boards ===") + + async with DefaultAzureCredential() as credential: + async with TrelloClient(CONNECTION_RUNTIME_URL, credential) as client: + boards = [item async for item in client.list_boards_simple()] + print(f"Boards: {boards}") + + +async def example_2_create_board() -> None: + """Example 2: Create a board.""" + print("\n=== Example 2: Create Board ===") + + async with DefaultAzureCredential() as credential: + async with TrelloClient(CONNECTION_RUNTIME_URL, credential) as client: + board = await client.create_board( + input=CreateBoard( + name="SDK sample board", + desc="Created by the Trello client in the Azure Connectors Python SDK.", + default_lists="false", + ) + ) + print(f"Created board: {board}") + + +async def example_3_create_list() -> None: + """Example 3: Create a list on an existing board.""" + print("\n=== Example 3: Create List ===") + + async with DefaultAzureCredential() as credential: + async with TrelloClient(CONNECTION_RUNTIME_URL, credential) as client: + created_list = await client.create_list( + input=CreateList( + name="SDK sample list", + id_board="board-id", + pos="bottom", + ) + ) + print(f"Created list: {created_list}") + + +async def example_4_create_card() -> None: + """Example 4: Create a card in an existing list.""" + print("\n=== Example 4: Create Card ===") + + async with DefaultAzureCredential() as credential: + async with TrelloClient(CONNECTION_RUNTIME_URL, credential) as client: + card = await client.create_card( + input=CreateCard( + id_list="list-id", + name="SDK sample card", + desc="Created by the Trello client in the Azure Connectors Python SDK.", + ), + board_id="board-id", + ) + print(f"Created card: {card}") + + +async def main() -> None: + """Run Trello connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: TRELLO_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Trello sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + # Uncomment the examples to run them against your Trello connection. + # await example_1_list_boards() + # await example_2_create_board() + # await example_3_create_list() + # await example_4_create_card() + print("Set the example calls in main() to run against your instance.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_twitter.py b/samples/sample_connector_usage/aio/sample_connector_usage_twitter.py new file mode 100644 index 0000000..98833b0 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_twitter.py @@ -0,0 +1,51 @@ +"""Twitter sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.twitter import TwitterClient + + +CONNECTION_RUNTIME_URL = os.environ.get("TWITTER_CONNECTION_URL", "") + + +async def list_user_timeline() -> None: + """List recent posts from a user's timeline.""" + async with DefaultAzureCredential() as credential: + async with TwitterClient(CONNECTION_RUNTIME_URL, credential) as client: + timeline = [item async for item in client.list_user_timeline( + user_name="Azure", + max_results=10, + )] + print(f"Timeline: {timeline}") + + +async def search_posts() -> None: + """Search recent posts.""" + async with DefaultAzureCredential() as credential: + async with TwitterClient(CONNECTION_RUNTIME_URL, credential) as client: + results = [item async for item in client.list_search_tweet( + search_query="Azure Logic Apps", + max_results=10, + )] + print(f"Search results: {results}") + + +async def main() -> None: + """Run Twitter connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Set TWITTER_CONNECTION_URL to run this sample.") + return + + try: + await list_user_timeline() + await search_posts() + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_typeform.py b/samples/sample_connector_usage/aio/sample_connector_usage_typeform.py new file mode 100644 index 0000000..81f5683 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_typeform.py @@ -0,0 +1,31 @@ +"""Typeform sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.typeform import TypeformClient + + +CONNECTION_RUNTIME_URL = os.environ.get("TYPEFORM_CONNECTION_URL", "") + + +async def main() -> None: + """List Typeform forms.""" + if not CONNECTION_RUNTIME_URL: + print("Set TYPEFORM_CONNECTION_URL to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with TypeformClient(CONNECTION_RUNTIME_URL, credential) as client: + forms = [form async for form in client.list_forms()] + print(f"Forms: {forms}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_universalprint.py b/samples/sample_connector_usage/aio/sample_connector_usage_universalprint.py new file mode 100644 index 0000000..1a7566d --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_universalprint.py @@ -0,0 +1,104 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Universal Print sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Universal Print client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a Universal Print connection +2. Universal Print connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:UNIVERSALPRINT_CONNECTION_URL = "" + + python sample_connector_usage_universalprint.py +""" + +import asyncio +import os +from pathlib import Path + +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.universalprint import UniversalprintClient + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/universalprint/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "UNIVERSALPRINT_CONNECTION_URL", + "", +) + + +async def example_1_list_recent_shares(): + """Example 1: List recently used printer shares.""" + print("\n=== Example 1: List Recent Printer Shares ===") + + async with DefaultAzureCredential() as credential: + + async with UniversalprintClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_recent_shares()] + + shares = items + print(f"Found {len(shares)} recent printer share(s).") + for share in shares: + print(f" - {share}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_print_file(): + """Example 2: Print a PDF to a printer share.""" + print("\n=== Example 2: Print File ===") + + async with DefaultAzureCredential() as credential: + pdf_file_path = Path( + os.environ.get("UNIVERSALPRINT_PDF_PATH", "document.pdf") + ) + + async with UniversalprintClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + await client.print_file( + input=pdf_file_path.read_bytes(), + printer="your-printer-share-id", + file_name=pdf_file_path.name, + configuration_copies=1, + configuration_color_mode="color", + configuration_orientation="portrait", + ) + + print("Print job submitted successfully.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: UNIVERSALPRINT_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_list_recent_shares() + await example_2_print_file() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_waywedo.py b/samples/sample_connector_usage/aio/sample_connector_usage_waywedo.py new file mode 100644 index 0000000..dd9b4f1 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_waywedo.py @@ -0,0 +1,31 @@ +"""Way We Do sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.waywedo import WaywedoClient + + +CONNECTION_RUNTIME_URL = os.environ.get("WAYWEDO_CONNECTION_URL", "") + + +async def main() -> None: + """Find Way We Do checklists.""" + if not CONNECTION_RUNTIME_URL: + print("Set WAYWEDO_CONNECTION_URL to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with WaywedoClient(CONNECTION_RUNTIME_URL, credential) as client: + checklists = [item async for item in client.list_find_checklist()] + print(f"Checklists: {checklists}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_wdatp.py b/samples/sample_connector_usage/aio/sample_connector_usage_wdatp.py new file mode 100644 index 0000000..eb067d8 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_wdatp.py @@ -0,0 +1,275 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Windows Defender ATP (Microsoft Defender for Endpoint) sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Windows Defender ATP client from the Azure Connectors Python SDK +to interact with Microsoft Defender for Endpoint for security operations. + +Prerequisites: +1. Azure subscription with Windows Defender ATP connection +2. WDATP connection in Connector Namespaces (with access configured) +3. Connection runtime URL from Azure Portal +4. Microsoft Defender for Endpoint subscription + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:WDATP_CONNECTION_URL = "https://...apihub.net/apim/wdatp/..." + + python sample_connector_usage_wdatp.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.wdatp import WdatpClient +from azure.connectors.wdatp import ( + AdvancedHuntingInput, + PatchAlertInput, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/wdatp/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "WDATP_CONNECTION_URL", + "" +) + + +async def example_1_list_alerts(): + """Example 1: List recent security alerts.""" + print("\n=== Example 1: List Security Alerts ===") + + async with DefaultAzureCredential() as credential: + + async with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + alerts = [item async for item in client.list_alerts( + top=5, + orderby="alertCreationTime desc" + )] + + if alerts: + print(f"Found {len(alerts)} alerts:") + for alert in alerts[:5]: + print(f" - [{alert.get('severity', 'N/A')}] {alert.get('title', 'N/A')}") + print(f" ID: {alert.get('id', 'N/A')}") + print(f" Status: {alert.get('status', 'N/A')}") + else: + print("No alerts found.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_get_machines(): + """Example 2: List machines in the organization.""" + print("\n=== Example 2: List Machines ===") + + async with DefaultAzureCredential() as credential: + + async with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + machines = [ + item async for item in client.list_machines(top=10) + ] + + if machines: + print(f"Found {len(machines)} machines:") + for machine in machines[:5]: + print(f" - {machine.get('computerDnsName', 'N/A')}") + print(f" ID: {machine.get('id', 'N/A')}") + print(f" OS: {machine.get('osPlatform', 'N/A')}") + print(f" Health: {machine.get('healthStatus', 'N/A')}") + else: + print("No machines found.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_advanced_hunting(): + """Example 3: Run an advanced hunting query.""" + print("\n=== Example 3: Advanced Hunting Query ===") + + async with DefaultAzureCredential() as credential: + + async with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Query for device information + query = "DeviceInfo | take 5 | project DeviceName, OSPlatform, PublicIP" + input_data = AdvancedHuntingInput(query=query) + + result = await client.advanced_hunting(input=input_data) + + if result and result.get("results"): + print(f"Query returned {len(result['results'])} results:") + for row in result["results"]: + print(f" - {row}") + else: + print("No results from query.") + + if result and result.get("stats"): + print(f"Execution time: {result['stats'].get('executionTime', 'N/A')}s") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_update_alert(): + """Example 4: Update an alert status.""" + print("\n=== Example 4: Update Alert Status ===") + + # Get alert ID from environment or skip + alert_id = os.environ.get("WDATP_ALERT_ID", "") + if not alert_id: + print("Set WDATP_ALERT_ID to update a specific alert.") + print("Skipping this example.") + return + + async with DefaultAzureCredential() as credential: + + async with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + input_data = PatchAlertInput( + status="InProgress", + assigned_to="security-team@example.com", + classification="TruePositive" + ) + + result = await client.patch_alert( + input=input_data, + alert_id=alert_id + ) + + print("Alert updated:") + print(f" ID: {result.get('id', 'N/A')}") + print(f" Status: {result.get('status', 'N/A')}") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_get_file_stats(): + """Example 5: Get file statistics by SHA1 hash.""" + print("\n=== Example 5: Get File Statistics ===") + + # Example SHA1 hash (use a real one from your environment) + file_sha1 = os.environ.get("WDATP_FILE_SHA1", "") + if not file_sha1: + print("Set WDATP_FILE_SHA1 to check a specific file.") + print("Skipping this example.") + return + + async with DefaultAzureCredential() as credential: + + async with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.get_file_stats(file_id=file_sha1) + + print(f"File statistics for {file_sha1}:") + print(f" Global prevalence: {result.get('globallyPrevalence', 'N/A')}") + print(f" Org prevalence: {result.get('organizationPrevalence', 'N/A')}") + print(f" First seen globally: {result.get('globalFirstObserved', 'N/A')}") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_6_machine_actions(): + """Example 6: List recent machine actions.""" + print("\n=== Example 6: List Machine Actions ===") + + async with DefaultAzureCredential() as credential: + + async with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + machine_actions = [item async for item in client.list_machine_actions( + top=5, + orderby="creationDateTimeUtc desc" + )] + + if machine_actions: + print(f"Found {len(machine_actions)} actions:") + for action in machine_actions[:5]: + print(f" - Type: {action.get('type', 'N/A')}") + print(f" Status: {action.get('status', 'N/A')}") + print(f" Machine: {action.get('machineId', 'N/A')[:20]}...") + else: + print("No machine actions found.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_7_investigations(): + """Example 7: List automated investigations.""" + print("\n=== Example 7: List Investigations ===") + + async with DefaultAzureCredential() as credential: + + async with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + investigations = [ + item async for item in client.list_investigations(top=5) + ] + + if investigations: + print(f"Found {len(investigations)} investigations:") + for inv in investigations[:5]: + print(f" - ID: {inv.get('id', 'N/A')}") + print(f" State: {inv.get('state', 'N/A')}") + print(f" Machine: {inv.get('computerDnsName', 'N/A')}") + else: + print("No investigations found.") + + except ConnectorException as ex: + print(f"Connector error (status {ex.status_code}): {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: WDATP_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + print("\nExample:") + print('$env:WDATP_CONNECTION_URL = ') + print(' "https://[region].azure-apihub.net/apim/wdatp/[id]"') + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + # Read operations + await example_1_list_alerts() + await example_2_get_machines() + await example_3_advanced_hunting() + await example_5_get_file_stats() + await example_6_machine_actions() + await example_7_investigations() + + # Update operations (requires specific IDs) + await example_4_update_alert() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_webex.py b/samples/sample_connector_usage/aio/sample_connector_usage_webex.py new file mode 100644 index 0000000..f28e811 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_webex.py @@ -0,0 +1,111 @@ +""" +Webex sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Webex client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a Webex connection +2. Webex connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:WEBEX_CONNECTION_URL = "https://[region].azure-apihub.net/apim/webex/[id]" + + python sample_connector_usage_webex.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.webex import WebexClient +from azure.connectors.webex import ( + CreateSpaceInput, + SendMessageInput, + ) + + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/webex/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get("WEBEX_CONNECTION_URL", "") + + +async def example_1_send_message() -> None: + """Example 1: Send a message to a space.""" + print("\n=== Example 1: Send Message ===") + + async with DefaultAzureCredential() as credential: + async with WebexClient(CONNECTION_RUNTIME_URL, credential) as client: + result = await client.send_message( + input=SendMessageInput( + room_id="ROOM_ID", + text="Hello from the Webex client in the Azure Connectors Python SDK.", + ), + ) + print(f"Send result: {result}") + + +async def example_2_get_spaces() -> None: + """Example 2: List spaces.""" + print("\n=== Example 2: Get Spaces ===") + + async with DefaultAzureCredential() as credential: + async with WebexClient(CONNECTION_RUNTIME_URL, credential) as client: + spaces = [item async for item in client.list_spaces()] + print(f"Spaces: {spaces}") + + +async def example_3_create_space() -> None: + """Example 3: Create a space.""" + print("\n=== Example 3: Create Space ===") + + async with DefaultAzureCredential() as credential: + async with WebexClient(CONNECTION_RUNTIME_URL, credential) as client: + space = await client.create_space( + input=CreateSpaceInput(title="My New Space"), + ) + print(f"Created space: {space}") + + +async def example_4_get_my_own_details() -> None: + """Example 4: Get details about the authenticated user.""" + print("\n=== Example 4: Get My Own Details ===") + + async with DefaultAzureCredential() as credential: + async with WebexClient(CONNECTION_RUNTIME_URL, credential) as client: + me = await client.get_my_own_details() + print(f"My details: {me}") + + +async def main() -> None: + """Run Webex connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: WEBEX_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print("Webex sample usage for the Azure Connectors Python SDK") + print("=" * 50) + + try: + # Uncomment to send a message, list/create spaces, or get your details. + # await example_1_send_message() + # await example_2_get_spaces() + # await example_3_create_space() + # await example_4_get_my_own_details() + print("Set the example calls in main() to run against your instance.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Unexpected error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_wordonlinebusiness.py b/samples/sample_connector_usage/aio/sample_connector_usage_wordonlinebusiness.py new file mode 100644 index 0000000..1f291b5 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_wordonlinebusiness.py @@ -0,0 +1,218 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Word Online (Business) sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Word Online (Business) client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with Word Online (Business) connection +2. Word Online (Business) connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:WORDONLINEBUSINESS_CONNECTION_URL = ` + "https://[region].azure-apihub.net/apim/wordonlinebusiness/[connection-id]" + + python sample_connector_usage_wordonlinebusiness.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.wordonlinebusiness import WordonlinebusinessClient +from azure.connectors.wordonlinebusiness import ( + CreateFileItemInput, + ContentBody, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/wordonlinebusiness/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "WORDONLINEBUSINESS_CONNECTION_URL", + "" +) +SOURCE = os.environ.get("WORDONLINEBUSINESS_SOURCE", "me") +DRIVE = os.environ.get("WORDONLINEBUSINESS_DRIVE", "") +FILE = os.environ.get("WORDONLINEBUSINESS_FILE", "") + + +async def example_1_populate_word_template(): + """Example 1: Populate a Microsoft Word template. + + Reads a Microsoft Word template and fills template fields with dynamic values + to generate a Word Document. + """ + print("\n=== Example 1: Populate Word Template ===") + + async with DefaultAzureCredential() as credential: + + async with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Create input with template field values + # The additional_properties dict contains the template field mappings + input_data = CreateFileItemInput( + additional_properties={ + "templateId": "your-template-id", + "field_Name": "John Doe", + "field_Date": "2024-01-15", + "field_Company": "Contoso Ltd.", + } + ) + + result = await client.create_file_item( + input=input_data, + source=SOURCE, + drive=DRIVE, + file=FILE + ) + + print(f"Generated document size: {len(result)} bytes") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_create_word_document(): + """Example 2: Create a Word document with content. + + Creates a new Microsoft Word file with the given content. + """ + print("\n=== Example 2: Create Word Document ===") + + async with DefaultAzureCredential() as credential: + + async with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Create document content + content = ContentBody( + content="This is the content of my Word document.\n\n" + "It can include multiple paragraphs and formatting." + ) + + result = await client.create_word_file_with_content( + input=content, + file_name="MyDocument.docx" + ) + + if result: + print(f"Document created with ID: {result.get('id', 'N/A')}") + print(f"Document name: {result.get('name', 'N/A')}") + else: + print("Document created successfully") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_create_word_document_without_filename(): + """Example 3: Create a Word document without specifying filename. + + Creates a new Microsoft Word file with auto-generated filename. + """ + print("\n=== Example 3: Create Word Document (Auto-named) ===") + + async with DefaultAzureCredential() as credential: + + async with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + content = ContentBody(content="Auto-generated document content.") + + result = await client.create_word_file_with_content(input=content) + + if result: + print(f"Document created: {result}") + else: + print("Document created successfully") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_convert_word_to_pdf(): + """Example 4: Convert a Word document to PDF. + + Gets a PDF version of a selected Word file. + """ + print("\n=== Example 4: Convert Word to PDF ===") + + async with DefaultAzureCredential() as credential: + + async with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.get_file_pdf( + source=SOURCE, + drive=DRIVE, + file=FILE + ) + + print(f"PDF generated, size: {len(result)} bytes") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_convert_with_sensitivity_labels(): + """Example 5: Convert Word to PDF with sensitivity label extraction. + + Converts a Word document to PDF while extracting sensitivity label metadata. + """ + print("\n=== Example 5: Convert with Sensitivity Labels ===") + + async with DefaultAzureCredential() as credential: + + async with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + result = await client.get_file_pdf( + source=SOURCE, + drive=DRIVE, + file=FILE, + extract_sensitivity_label=True, + fetch_sensitivity_label_metadata=True + ) + + print(f"PDF generated with sensitivity labels, size: {len(result)} bytes") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: WORDONLINEBUSINESS_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + if not DRIVE or not FILE: + print("Error: WORDONLINEBUSINESS_DRIVE and WORDONLINEBUSINESS_FILE must be set.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_populate_word_template() + await example_2_create_word_document() + await example_3_create_word_document_without_filename() + await example_4_convert_word_to_pdf() + await example_5_convert_with_sensitivity_labels() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_wordpress.py b/samples/sample_connector_usage/aio/sample_connector_usage_wordpress.py new file mode 100644 index 0000000..1c0f6e7 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_wordpress.py @@ -0,0 +1,53 @@ +"""WordPress sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.wordpress import WordpressClient +from azure.connectors.wordpress import CreatePostModel + + +CONNECTION_RUNTIME_URL = os.environ.get("WORDPRESS_CONNECTION_URL", "") + + +async def list_sites() -> None: + """List WordPress sites available to the connection.""" + async with DefaultAzureCredential() as credential: + async with WordpressClient(CONNECTION_RUNTIME_URL, credential) as client: + sites = [item async for item in client.list_sites()] + print(f"Sites: {sites}") + + +async def create_post() -> None: + """Create a draft WordPress post.""" + async with DefaultAzureCredential() as credential: + async with WordpressClient(CONNECTION_RUNTIME_URL, credential) as client: + post = await client.create( + input=CreatePostModel( + title="Generated connector sample", + content="Created with the Azure Connectors Python SDK.", + status="draft", + ), + site_id="SITE_ID", + ) + print(f"Created post: {post}") + + +async def main() -> None: + """Run WordPress connector examples.""" + if not CONNECTION_RUNTIME_URL: + print("Set WORDPRESS_CONNECTION_URL to run this sample.") + return + + try: + await list_sites() + await create_post() + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_yammer.py b/samples/sample_connector_usage/aio/sample_connector_usage_yammer.py new file mode 100644 index 0000000..bc24ad0 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_yammer.py @@ -0,0 +1,222 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Yammer (Viva Engage) sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Yammer client from the Azure Connectors Python SDK to interact with +Viva Engage (formerly Yammer) networks, groups, messages, and users. + +Prerequisites: +1. Azure subscription with Yammer connection +2. Yammer connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:YAMMER_CONNECTION_URL = "https://[region].azure-apihub.net/apim/yammer/[connection-id]" + + python sample_connector_usage_yammer.py +""" + +import asyncio +import os +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.yammer import YammerClient +from azure.connectors.yammer import ( + PostOperationRequest, +) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/yammer/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "YAMMER_CONNECTION_URL", + "" +) + + +async def example_1_get_networks(): + """Example 1: Get all networks the user belongs to.""" + print("\n=== Example 1: Get Networks ===") + + async with DefaultAzureCredential() as credential: + + async with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + networks = [item async for item in client.list_networks()] + + if networks: + print(f"Found {len(networks)} network(s):") + for network in networks: + print(f" - {network.get('name')} (ID: {network.get('id')})") + else: + print("No networks found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_get_groups(): + """Example 2: Get groups in the network.""" + print("\n=== Example 2: Get Groups ===") + + async with DefaultAzureCredential() as credential: + + async with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Get only groups the user belongs to + groups = [item async for item in client.list_groups(mine=1)] + + if groups: + print(f"Found {len(groups)} group(s):") + for group in groups[:5]: # Show first 5 + print(f" - {group.get('full_name')} (ID: {group.get('id')})") + else: + print("No groups found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_get_messages(): + """Example 3: Get messages from the network.""" + print("\n=== Example 3: Get All Messages ===") + + async with DefaultAzureCredential() as credential: + + async with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Get recent messages (limit to 10) + messages = [ + item async for item in client.list_all_messages(limit=10) + ] + + if messages: + print(f"Found {len(messages)} message(s):") + for msg in messages[:3]: # Show first 3 + excerpt = msg.get("content_excerpt", "")[:50] + print(f" - ID {msg.get('id')}: {excerpt}...") + else: + print("No messages found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_get_following_feed(): + """Example 4: Get messages from the Following feed.""" + print("\n=== Example 4: Get Following Feed ===") + + async with DefaultAzureCredential() as credential: + + async with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + messages = [ + item async for item in client.list_messages_following( + limit=5 + ) + ] + + if messages: + print(f"Found {len(messages)} message(s) in following feed:") + for msg in messages[:3]: + sender_id = msg.get("sender_id") + excerpt = msg.get("content_excerpt", "")[:40] + print(f" - From user {sender_id}: {excerpt}...") + else: + print("No messages in following feed.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_5_post_message(): + """Example 5: Post a message to All Company feed.""" + print("\n=== Example 5: Post Message ===") + + async with DefaultAzureCredential() as credential: + + async with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Create message request (group_id=0 posts to All Company) + message = PostOperationRequest( + group_id=0, + body="Hello from the Azure Connectors Python SDK!", + title="SDK Test Message" + ) + + result = await client.post_message(input=message) + + if result: + print("Message posted successfully!") + print(f" Message ID: {result.get('id')}") + print(f" Web URL: {result.get('web_url')}") + else: + print("Message posted (no response body).") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_6_get_user_details(): + """Example 6: Get user profile details.""" + print("\n=== Example 6: Get User Details ===") + + async with DefaultAzureCredential() as credential: + + async with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + # Replace with an actual user ID + user_id = 123456789 + user = await client.get_user_details_by_id(user_id=user_id) + + if user: + print("User details:") + print(f" Name: {user.get('full_name')}") + print(f" Email: {user.get('email')}") + print(f" Title: {user.get('job_title')}") + print(f" Location: {user.get('location')}") + else: + print("User not found.") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: YAMMER_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_get_networks() + await example_2_get_groups() + await example_3_get_messages() + await example_4_get_following_feed() + # Uncomment to test posting (be careful in production!) + # await example_5_post_message() + await example_6_get_user_details() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_zendesk.py b/samples/sample_connector_usage/aio/sample_connector_usage_zendesk.py new file mode 100644 index 0000000..beb72fe --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_zendesk.py @@ -0,0 +1,147 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +""" +Zendesk sample for the Azure Connectors Python SDK + +This sample demonstrates how to use the Zendesk client from the Azure Connectors Python SDK. + +Prerequisites: +1. Azure subscription with a Zendesk connection +2. Zendesk connection in Connector Namespaces +3. Connection runtime URL from Azure Portal + +Installation: + pip install azure-connectors + +Usage: + Set environment variable: + $env:ZENDESK_CONNECTION_URL = "https://[region].azure-apihub.net/apim/zendesk/[connection-id]" + + python sample_connector_usage_zendesk.py +""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential +from azure.connectors import ConnectorException +from azure.connectors.aio.zendesk import ZendeskClient +from azure.connectors.zendesk import ( + Item, + ) + +# Connection runtime URL format: +# https://[region].azure-apihub.net/apim/zendesk/[connection-id] +CONNECTION_RUNTIME_URL = os.environ.get( + "ZENDESK_CONNECTION_URL", + "", +) + + +async def example_1_get_tables(): + """Example 1: List the available Zendesk tables (object types).""" + print("\n=== Example 1: Get Tables ===") + + async with DefaultAzureCredential() as credential: + + async with ZendeskClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_tables()] + + tables = items + print(f"Found {len(tables)} table(s).") + for table in tables: + print(f" - {table}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_2_get_items(): + """Example 2: Retrieve items from a Zendesk table.""" + print("\n=== Example 2: Get Items ===") + + async with DefaultAzureCredential() as credential: + + async with ZendeskClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_items( + table="tickets", + top=10, + )] + + print(f"Retrieved {len(items)} item(s).") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_3_create_item(): + """Example 3: Create a new item in a Zendesk table.""" + print("\n=== Example 3: Create Item ===") + + async with DefaultAzureCredential() as credential: + + async with ZendeskClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + new_item = Item( + dynamic_properties={ + "subject": "Sample ticket", + "description": "Created from the Zendesk SDK sample.", + }, + ) + + result = await client.post_item(input=new_item, table="tickets") + print(f"Created item: {result}") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def example_4_search_articles(): + """Example 4: Search Zendesk Help Center articles.""" + print("\n=== Example 4: Search Articles ===") + + async with DefaultAzureCredential() as credential: + + async with ZendeskClient(CONNECTION_RUNTIME_URL, credential) as client: + try: + items = [item async for item in client.list_search_articles( + query="password reset", + locale="en-us", + )] + + articles = items + print(f"Found {len(articles)} article(s).") + + except ConnectorException as ex: + print(f"Connector error: {ex}") + except Exception as ex: + print(f"Error: {ex}") + + +async def main(): + """Run all examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: ZENDESK_CONNECTION_URL environment variable not set.") + print("Set it to your connection runtime URL from Azure Portal.") + return + + print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") + + await example_1_get_tables() + await example_2_get_items() + await example_3_create_item() + await example_4_search_articles() + + print("\n=== All examples completed ===") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_zeptomail.py b/samples/sample_connector_usage/aio/sample_connector_usage_zeptomail.py new file mode 100644 index 0000000..8e1817c --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_zeptomail.py @@ -0,0 +1,34 @@ +"""Zoho ZeptoMail sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.zeptomail import ZeptomailClient + + +CONNECTION_RUNTIME_URL = os.environ.get("ZEPTOMAIL_CONNECTION_URL", "") + + +async def main() -> None: + """List the configured ZeptoMail mail agents.""" + if not CONNECTION_RUNTIME_URL: + print("Set ZEPTOMAIL_CONNECTION_URL to run this sample.") + return + + async with DefaultAzureCredential() as credential: + try: + async with ZeptomailClient( + CONNECTION_RUNTIME_URL, + credential, + ) as client: + mail_agents = await client.get_mail_agent() + print(f"Mail agents: {mail_agents}") + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/aio/sample_connector_usage_zohosign.py b/samples/sample_connector_usage/aio/sample_connector_usage_zohosign.py new file mode 100644 index 0000000..7d0a3a8 --- /dev/null +++ b/samples/sample_connector_usage/aio/sample_connector_usage_zohosign.py @@ -0,0 +1,52 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Zoho Sign sample for the Azure Connectors Python SDK.""" + +import asyncio +import os + +from azure.identity.aio import DefaultAzureCredential + +from azure.connectors import ConnectorException +from azure.connectors.aio.zohosign import ZohosignClient + + +CONNECTION_RUNTIME_URL = os.environ.get("ZOHOSIGN_CONNECTION_URL", "") +REQUEST_ID = os.environ.get("ZOHOSIGN_REQUEST_ID", "") + + +async def list_templates() -> None: + """List available Zoho Sign templates.""" + async with DefaultAzureCredential() as credential: + async with ZohosignClient(CONNECTION_RUNTIME_URL, credential) as client: + templates = [item async for item in client.list_templates()] + print(f"Templates: {templates}") + + +async def get_document() -> None: + """Get a Zoho Sign document request.""" + if not REQUEST_ID: + print("Set ZOHOSIGN_REQUEST_ID to retrieve a document request.") + return + + async with DefaultAzureCredential() as credential: + async with ZohosignClient(CONNECTION_RUNTIME_URL, credential) as client: + document = await client.get_document(request_id=int(REQUEST_ID)) + print(f"Document: {document}") + + +async def main() -> None: + """Run the Zoho Sign examples.""" + if not CONNECTION_RUNTIME_URL: + print("Error: ZOHOSIGN_CONNECTION_URL environment variable not set.") + return + + try: + await list_templates() + await get_document() + except ConnectorException as ex: + print(f"Connector error: {ex}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/samples/sample_connector_usage/sample_connector_usage_arm.py b/samples/sample_connector_usage/sample_connector_usage_arm.py index c751255..88255b2 100644 --- a/samples/sample_connector_usage/sample_connector_usage_arm.py +++ b/samples/sample_connector_usage/sample_connector_usage_arm.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure Resource Manager (ARM) Connector SDK Sample +Azure Resource Manager (ARM) sample for the Azure Connectors Python SDK -This sample demonstrates how to use the ARM connector SDK to interact +This sample demonstrates how to use the ARM client from the Azure Connectors Python SDK to interact with Azure Resource Manager APIs. Prerequisites: @@ -24,10 +24,8 @@ The ARM connector uses OAuth (user-delegated Azure AD token). The connection requires OAuth consent via the consent link flow. """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.arm import ArmClient @@ -39,16 +37,16 @@ ) -async def example_1_list_subscriptions(): +def example_1_list_subscriptions(): """Example 1: List all subscriptions accessible to the authenticated user.""" print("\n=== Example 1: List Subscriptions ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ArmClient(CONNECTION_RUNTIME_URL, credential) as client: + with ArmClient(CONNECTION_RUNTIME_URL, credential) as client: try: subscriptions = [ - item async for item in client.subscriptions_list_async() + item for item in client.list_subscriptions() ] if subscriptions: @@ -69,16 +67,16 @@ async def example_1_list_subscriptions(): print(f"Error: {ex}") -async def example_2_list_subscriptions_with_details(): +def example_2_list_subscriptions_with_details(): """Example 2: List subscriptions with full details.""" print("\n=== Example 2: List Subscriptions with Details ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ArmClient(CONNECTION_RUNTIME_URL, credential) as client: + with ArmClient(CONNECTION_RUNTIME_URL, credential) as client: try: subscriptions = [ - item async for item in client.subscriptions_list_async() + item for item in client.list_subscriptions() ] if subscriptions: @@ -112,16 +110,16 @@ async def example_2_list_subscriptions_with_details(): print(f"Error: {ex}") -async def example_3_filter_enabled_subscriptions(): +def example_3_filter_enabled_subscriptions(): """Example 3: List only enabled subscriptions.""" print("\n=== Example 3: Filter Enabled Subscriptions ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ArmClient(CONNECTION_RUNTIME_URL, credential) as client: + with ArmClient(CONNECTION_RUNTIME_URL, credential) as client: try: subscriptions = [ - item async for item in client.subscriptions_list_async() + item for item in client.list_subscriptions() ] if subscriptions: @@ -156,9 +154,9 @@ async def example_3_filter_enabled_subscriptions(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" - print("Azure Resource Manager (ARM) Connector SDK - Sample Usage") + print("Azure Resource Manager (ARM) sample usage for the Azure Connectors Python SDK") print("=" * 60) if not CONNECTION_RUNTIME_URL: @@ -167,13 +165,13 @@ async def main(): print("Format: https://[region].azure-apihub.net/apim/arm/[connection-id]") return - await example_1_list_subscriptions() - await example_2_list_subscriptions_with_details() - await example_3_filter_enabled_subscriptions() + example_1_list_subscriptions() + example_2_list_subscriptions_with_details() + example_3_filter_enabled_subscriptions() print("\n" + "=" * 60) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_azuread.py b/samples/sample_connector_usage/sample_connector_usage_azuread.py index a5f4fc4..ec9b6c6 100644 --- a/samples/sample_connector_usage/sample_connector_usage_azuread.py +++ b/samples/sample_connector_usage/sample_connector_usage_azuread.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure AD (Microsoft Entra ID) Connector SDK Sample +Azure AD (Microsoft Entra ID) sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure AD connector SDK. +This sample demonstrates how to use the Azure AD client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Azure AD connection @@ -19,10 +19,8 @@ python sample_connector_usage_azuread.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.azuread import ( AzureadClient, @@ -40,7 +38,7 @@ ) -async def example_1_create_office365_group(): +def example_1_create_office365_group(): """Example 1: Create an Office 365 group.""" print("\n=== Example 1: Create Office 365 Group ===") @@ -50,9 +48,9 @@ async def example_1_create_office365_group(): print("Example: $env:TEST_O365_GROUP_NAME = 'SDK Test Group'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: try: input_data = CreateOffice365GroupInput( display_name=group_name, @@ -63,7 +61,7 @@ async def example_1_create_office365_group(): mail_enabled=True, ) - result = await client.create_office365_group_async(input=input_data) + result = client.create_office365_group(input=input_data) if result: print("Office 365 group created:") @@ -80,7 +78,7 @@ async def example_1_create_office365_group(): print(f"Error: {ex}") -async def example_2_create_security_group(): +def example_2_create_security_group(): """Example 2: Create a security group.""" print("\n=== Example 2: Create Security Group ===") @@ -90,9 +88,9 @@ async def example_2_create_security_group(): print("Example: $env:TEST_SECURITY_GROUP_NAME = 'SDK Security Group'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: try: input_data = CreateSecurityGroupInput( display_name=group_name, @@ -102,7 +100,7 @@ async def example_2_create_security_group(): mail_enabled=False, ) - result = await client.create_security_group_async(input=input_data) + result = client.create_security_group(input=input_data) if result: print("Security group created:") @@ -118,7 +116,7 @@ async def example_2_create_security_group(): print(f"Error: {ex}") -async def example_3_create_group(): +def example_3_create_group(): """Example 3: Create a generic group.""" print("\n=== Example 3: Create Group ===") @@ -132,9 +130,9 @@ async def example_3_create_group(): group_type = os.environ.get("TEST_GROUP_TYPE", "Unified") group_types = [group_type] if group_type else [] - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: try: input_data = CreateGroupInput( display_name=group_name, @@ -145,7 +143,7 @@ async def example_3_create_group(): mail_enabled=bool(group_types), ) - result = await client.create_group_async(input=input_data) + result = client.create_group(input=input_data) if result: print("Group created:") @@ -163,7 +161,7 @@ async def example_3_create_group(): print(f"Error: {ex}") -async def example_4_create_user(): +def example_4_create_user(): """Example 4: Create a new user.""" print("\n=== Example 4: Create User ===") @@ -178,9 +176,9 @@ async def example_4_create_user(): print(" $env:TEST_USER_PASSWORD = 'TempPassword123!'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: try: input_data = CreateUserRequest( account_enabled=True, @@ -193,7 +191,7 @@ async def example_4_create_user(): }, ) - result = await client.create_user_async(input=input_data) + result = client.create_user(input=input_data) if result: print("User created:") @@ -210,7 +208,7 @@ async def example_4_create_user(): print(f"Error: {ex}") -async def example_5_remove_member_from_group(): +def example_5_remove_member_from_group(): """Example 5: Remove a member from a group.""" print("\n=== Example 5: Remove Member From Group ===") @@ -223,11 +221,11 @@ async def example_5_remove_member_from_group(): print(" $env:TEST_MEMBER_ID = ''") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzureadClient(CONNECTION_RUNTIME_URL, credential) as client: try: - await client.remove_member_from_group_async( + client.remove_member_from_group( group_id=group_id, member_id=member_id, ) @@ -242,9 +240,9 @@ async def example_5_remove_member_from_group(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" - print("Azure AD (Microsoft Entra ID) Connector SDK - Sample Usage") + print("Azure AD (Microsoft Entra ID) sample usage for the Azure Connectors Python SDK") print("=" * 60) if not CONNECTION_RUNTIME_URL: @@ -253,15 +251,15 @@ async def main(): print("Format: https://[region].azure-apihub.net/apim/azuread/[connection-id]") return - await example_1_create_office365_group() - await example_2_create_security_group() - await example_3_create_group() - await example_4_create_user() - await example_5_remove_member_from_group() + example_1_create_office365_group() + example_2_create_security_group() + example_3_create_group() + example_4_create_user() + example_5_remove_member_from_group() print("\n" + "=" * 60) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_azureautomation.py b/samples/sample_connector_usage/sample_connector_usage_azureautomation.py index a476fab..5af63ef 100644 --- a/samples/sample_connector_usage/sample_connector_usage_azureautomation.py +++ b/samples/sample_connector_usage/sample_connector_usage_azureautomation.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure Automation Connector SDK Sample +Azure Automation sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure Automation connector SDK +This sample demonstrates how to use the Azure Automation client from the Azure Connectors Python SDK to interact with Azure Automation accounts, runbooks, and jobs. Prerequisites: @@ -29,10 +29,8 @@ - Get job status - Get job output """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.azureautomation import ( AzureautomationClient, @@ -68,13 +66,13 @@ ) -async def example_1_client_initialization(): +def example_1_client_initialization(): """Example 1: Initialize and verify the client.""" print("\n=== Example 1: Client Initialization ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureautomationClient( + with AzureautomationClient( CONNECTION_RUNTIME_URL, credential ) as client: try: @@ -88,18 +86,18 @@ async def example_1_client_initialization(): print(f"Error: {ex}") -async def example_2_create_job(): +def example_2_create_job(): """Example 2: Create an automation job.""" print("\n=== Example 2: Create Automation Job ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureautomationClient( + with AzureautomationClient( CONNECTION_RUNTIME_URL, credential ) as client: try: # Create a new automation job - result = await client.create_job_async( + result = client.create_job( input=CreateJobInput(properties={}), subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP_NAME, @@ -119,18 +117,18 @@ async def example_2_create_job(): print(f"Error: {ex}") -async def example_3_create_job_and_wait(): +def example_3_create_job_and_wait(): """Example 3: Create a job and wait for completion.""" print("\n=== Example 3: Create Job and Wait ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureautomationClient( + with AzureautomationClient( CONNECTION_RUNTIME_URL, credential ) as client: try: # Create job with wait parameter to wait for completion - result = await client.create_job_async( + result = client.create_job( input=CreateJobInput(properties={}), subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP_NAME, @@ -150,18 +148,18 @@ async def example_3_create_job_and_wait(): print(f"Error: {ex}") -async def example_4_get_job_status(): +def example_4_get_job_status(): """Example 4: Get the status of a job.""" print("\n=== Example 4: Get Job Status ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureautomationClient( + with AzureautomationClient( CONNECTION_RUNTIME_URL, credential ) as client: try: # Get status of a job - result = await client.get_status_of_job_async( + result = client.get_status_of_job( subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP_NAME, automation_account=AUTOMATION_ACCOUNT, @@ -183,18 +181,18 @@ async def example_4_get_job_status(): print(f"Error: {ex}") -async def example_5_get_job_output(): +def example_5_get_job_output(): """Example 5: Get the output of a job.""" print("\n=== Example 5: Get Job Output ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureautomationClient( + with AzureautomationClient( CONNECTION_RUNTIME_URL, credential ) as client: try: # Get output from a completed job - output = await client.get_job_output_async( + output = client.get_job_output( subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP_NAME, automation_account=AUTOMATION_ACCOUNT, @@ -217,7 +215,7 @@ async def example_5_get_job_output(): print(f"Error: {ex}") -async def example_6_dataclass_usage(): +def example_6_dataclass_usage(): """Example 6: Working with Azure Automation data types.""" print("\n=== Example 6: Data Types ===") @@ -250,14 +248,14 @@ async def example_6_dataclass_usage(): print(f"Resource Group: {rg.name}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: AZUREAUTOMATION_CONNECTION_URL environment variable " "not set.") print("Set it to your connection runtime URL from Azure Portal.") print("\nRunning data type examples without connection...\n") - await example_6_dataclass_usage() + example_6_dataclass_usage() return if not all([SUBSCRIPTION_ID, RESOURCE_GROUP_NAME, AUTOMATION_ACCOUNT]): @@ -265,20 +263,20 @@ async def main(): print("Required: AZUREAUTOMATION_SUBSCRIPTION_ID, " "AZUREAUTOMATION_RESOURCE_GROUP, AZUREAUTOMATION_ACCOUNT") print("\nRunning data type examples without connection...\n") - await example_6_dataclass_usage() + example_6_dataclass_usage() return print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_client_initialization() - await example_2_create_job() - await example_3_create_job_and_wait() - await example_4_get_job_status() - await example_5_get_job_output() - await example_6_dataclass_usage() + example_1_client_initialization() + example_2_create_job() + example_3_create_job_and_wait() + example_4_get_job_status() + example_5_get_job_output() + example_6_dataclass_usage() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_azureblob.py b/samples/sample_connector_usage/sample_connector_usage_azureblob.py index 1b8846e..fae8809 100644 --- a/samples/sample_connector_usage/sample_connector_usage_azureblob.py +++ b/samples/sample_connector_usage/sample_connector_usage_azureblob.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure Blob Storage Connector SDK Sample +Azure Blob Storage sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure Blob Storage connector SDK. +This sample demonstrates how to use the Azure Blob Storage client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Azure Blob Storage connection @@ -25,10 +25,8 @@ python sample_connector_usage_azureblob.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.azureblob import AzureblobClient @@ -46,7 +44,7 @@ ) -async def example_1_get_blob_metadata(): +def example_1_get_blob_metadata(): """Example 1: Get blob metadata by path.""" print("\n=== Example 1: Get Blob Metadata ===") @@ -56,11 +54,11 @@ async def example_1_get_blob_metadata(): print("Example: $env:TEST_BLOB_PATH = 'container/folder/file.txt'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: - metadata = await client.get_file_metadata_by_path_async( + metadata = client.get_file_metadata_by_path( dataset=STORAGE_ACCOUNT, path=blob_path, ) @@ -77,7 +75,7 @@ async def example_1_get_blob_metadata(): print(f"No metadata returned for: {blob_path}") -async def example_2_download_blob(): +def example_2_download_blob(): """Example 2: Download blob content.""" print("\n=== Example 2: Download Blob Content ===") @@ -87,10 +85,10 @@ async def example_2_download_blob(): print("Example: $env:TEST_BLOB_PATH = 'container/folder/file.txt'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: - content = await client.get_file_content_by_path_async( + with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: + content = client.get_file_content_by_path( dataset=STORAGE_ACCOUNT, path=blob_path, ) @@ -110,7 +108,7 @@ async def example_2_download_blob(): print(f"No content returned for: {blob_path}") -async def example_3_upload_blob(): +def example_3_upload_blob(): """Example 3: Upload a blob.""" print("\n=== Example 3: Upload Blob ===") @@ -121,14 +119,13 @@ async def example_3_upload_blob(): return blob_name = "sample-upload.txt" - blob_content = "Hello from Azure Connectors SDK for Python!\nUploaded at: " + \ - asyncio.get_event_loop().time().__str__() + blob_content = "Hello from Azure Connectors SDK for Python!" - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: try: - metadata = await client.create_file_async( + metadata = client.create_file( input=blob_content.encode("utf-8"), dataset=STORAGE_ACCOUNT, folder_path=folder_path, @@ -149,7 +146,7 @@ async def example_3_upload_blob(): print(f"Error: {ex}") -async def example_4_list_blobs(): +def example_4_list_blobs(): """Example 4: List blobs in a container/folder.""" print("\n=== Example 4: List Blobs ===") @@ -157,15 +154,15 @@ async def example_4_list_blobs(): if not folder_id: print("Set TEST_FOLDER_ID environment variable to a folder identifier.") print("Example: $env:TEST_FOLDER_ID = 'JTJmbXljb250YWluZXI=' (base64 encoded path)") - print("Or use list_root_folder_async to list root container blobs.") + print("Or use list_root_folder to list root container blobs.") # Try listing root folder instead print("\nListing root folder blobs instead...") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: try: - blobs = [item async for item in client.list_root_folder_async( + blobs = [item for item in client.list_root_folder( dataset=STORAGE_ACCOUNT, )] @@ -186,11 +183,11 @@ async def example_4_list_blobs(): print(f"Error: {ex}") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: try: - blobs = [item async for item in client.list_folder_async( + blobs = [item for item in client.list_folder( dataset=STORAGE_ACCOUNT, id=folder_id, )] @@ -212,7 +209,7 @@ async def example_4_list_blobs(): print(f"Error: {ex}") -async def example_5_delete_blob(): +def example_5_delete_blob(): """Example 5: Delete a blob.""" print("\n=== Example 5: Delete Blob ===") @@ -220,14 +217,14 @@ async def example_5_delete_blob(): if not blob_id: print("Set TEST_BLOB_ID environment variable to a blob identifier.") print("Example: $env:TEST_BLOB_ID = 'JTJmbXljb250YWluZXIlMmZmaWxlLnR4dA=='") - print("You can get blob IDs from the list_folder_async response.") + print("You can get blob IDs from the list_folder response.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzureblobClient(CONNECTION_RUNTIME_URL, credential) as client: try: - await client.delete_file_async( + client.delete_file( dataset=STORAGE_ACCOUNT, id=blob_id, ) @@ -240,9 +237,9 @@ async def example_5_delete_blob(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" - print("Azure Blob Storage Connector SDK - Sample Usage") + print("Azure Blob Storage sample usage for the Azure Connectors Python SDK") print("=" * 60) if not CONNECTION_RUNTIME_URL: @@ -256,15 +253,15 @@ async def main(): print("Set it to your storage account name.") return - await example_1_get_blob_metadata() - await example_2_download_blob() - await example_3_upload_blob() - await example_4_list_blobs() - await example_5_delete_blob() + example_1_get_blob_metadata() + example_2_download_blob() + example_3_upload_blob() + example_4_list_blobs() + example_5_delete_blob() print("\n" + "=" * 60) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_azuredatafactory.py b/samples/sample_connector_usage/sample_connector_usage_azuredatafactory.py index 55c60ac..42f0f92 100644 --- a/samples/sample_connector_usage/sample_connector_usage_azuredatafactory.py +++ b/samples/sample_connector_usage/sample_connector_usage_azuredatafactory.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure Data Factory Connector SDK Sample +Azure Data Factory sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure Data Factory connector SDK +This sample demonstrates how to use the Azure Data Factory client from the Azure Connectors Python SDK to create, monitor, and cancel pipeline runs. Prerequisites: @@ -25,10 +25,8 @@ - Get pipeline run status - Cancel pipeline runs """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.azuredatafactory import ( AzuredatafactoryClient, @@ -51,13 +49,13 @@ PIPELINE_NAME = os.environ.get("ADF_PIPELINE_NAME", "your-pipeline") -async def example_1_create_pipeline_run(): +def example_1_create_pipeline_run(): """Example 1: Create a new pipeline run.""" print("\n=== Example 1: Create Pipeline Run ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzuredatafactoryClient( + with AzuredatafactoryClient( CONNECTION_RUNTIME_URL, credential ) as client: try: @@ -71,7 +69,7 @@ async def example_1_create_pipeline_run(): ) # Create the pipeline run - result = await client.create_pipeline_run_async( + result = client.create_pipeline_run( input=parameters, subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP, @@ -96,7 +94,7 @@ async def example_1_create_pipeline_run(): return None -async def example_2_get_pipeline_run_status(run_id: str): +def example_2_get_pipeline_run_status(run_id: str): """Example 2: Get the status of a pipeline run.""" print("\n=== Example 2: Get Pipeline Run Status ===") @@ -104,14 +102,14 @@ async def example_2_get_pipeline_run_status(run_id: str): print("No run ID provided, skipping...") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzuredatafactoryClient( + with AzuredatafactoryClient( CONNECTION_RUNTIME_URL, credential ) as client: try: # Get the pipeline run status - result = await client.get_pipeline_run_async( + result = client.get_pipeline_run( subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP, data_factory_name=DATA_FACTORY_NAME, @@ -139,7 +137,7 @@ async def example_2_get_pipeline_run_status(run_id: str): print(f"Error: {ex}") -async def example_3_cancel_pipeline_run(run_id: str): +def example_3_cancel_pipeline_run(run_id: str): """Example 3: Cancel a running pipeline.""" print("\n=== Example 3: Cancel Pipeline Run ===") @@ -147,14 +145,14 @@ async def example_3_cancel_pipeline_run(run_id: str): print("No run ID provided, skipping...") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzuredatafactoryClient( + with AzuredatafactoryClient( CONNECTION_RUNTIME_URL, credential ) as client: try: # Cancel the pipeline run - await client.cancel_pipeline_run_async( + client.cancel_pipeline_run( subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP, data_factory_name=DATA_FACTORY_NAME, @@ -169,7 +167,7 @@ async def example_3_cancel_pipeline_run(run_id: str): print(f"Error: {ex}") -async def example_4_dataclass_usage(): +def example_4_dataclass_usage(): """Example 4: Working with Azure Data Factory data types.""" print("\n=== Example 4: Data Types ===") @@ -204,14 +202,14 @@ async def example_4_dataclass_usage(): print(f"Parameters: {params.additional_properties}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: AZUREDATAFACTORY_CONNECTION_URL environment variable " "not set.") print("Set it to your connection runtime URL from Azure Portal.") print("\nRunning data type examples without connection...\n") - await example_4_dataclass_usage() + example_4_dataclass_usage() return print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") @@ -221,21 +219,21 @@ async def main(): print(f"Pipeline: {PIPELINE_NAME}") # Create a pipeline run - run_id = await example_1_create_pipeline_run() + run_id = example_1_create_pipeline_run() # Get the status of the run if run_id: - await example_2_get_pipeline_run_status(run_id) + example_2_get_pipeline_run_status(run_id) # Uncomment to cancel the run (be careful with this!) # if run_id: # await example_3_cancel_pipeline_run(run_id) # Show data type usage - await example_4_dataclass_usage() + example_4_dataclass_usage() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_azuredigitaltwins.py b/samples/sample_connector_usage/sample_connector_usage_azuredigitaltwins.py index 28d75ac..ff12201 100644 --- a/samples/sample_connector_usage/sample_connector_usage_azuredigitaltwins.py +++ b/samples/sample_connector_usage/sample_connector_usage_azuredigitaltwins.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure Digital Twins Connector SDK Sample +Azure Digital Twins sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure Digital Twins connector SDK +This sample demonstrates how to use the Azure Digital Twins client from the Azure Connectors Python SDK to manage digital twins, models, relationships, and queries. Prerequisites: @@ -27,10 +27,8 @@ - Query twins - Send telemetry """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.azuredigitaltwins import ( AzuredigitaltwinsClient, @@ -48,18 +46,18 @@ ) -async def example_1_list_models(): +def example_1_list_models(): """Example 1: List all models in the instance.""" print("\n=== Example 1: List Models ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzuredigitaltwinsClient( + with AzuredigitaltwinsClient( CONNECTION_RUNTIME_URL, credential ) as client: try: # List all models - models = [item async for item in client.list_models_async( + models = [item for item in client.list_models( include_model_definition="true" )] @@ -76,19 +74,19 @@ async def example_1_list_models(): print(f"Error: {ex}") -async def example_2_get_twin(): +def example_2_get_twin(): """Example 2: Get a specific digital twin.""" print("\n=== Example 2: Get Twin ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: twin_id = "room1" # Replace with your twin ID - async with AzuredigitaltwinsClient( + with AzuredigitaltwinsClient( CONNECTION_RUNTIME_URL, credential ) as client: try: # Get a twin by ID - result = await client.get_twin_by_id_async(twinid=twin_id) + result = client.get_twin_by_id(twinid=twin_id) if result: print(f"Twin ID: {result.get('$dtId', 'Unknown')}") @@ -108,13 +106,13 @@ async def example_2_get_twin(): print(f"Error: {ex}") -async def example_3_query_twins(): +def example_3_query_twins(): """Example 3: Query digital twins.""" print("\n=== Example 3: Query Twins ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzuredigitaltwinsClient( + with AzuredigitaltwinsClient( CONNECTION_RUNTIME_URL, credential ) as client: try: @@ -122,7 +120,7 @@ async def example_3_query_twins(): query_input = QueryTwinsInput( query="SELECT * FROM digitaltwins" ) - result = await client.query_twins_async(input=query_input) + result = client.query_twins(input=query_input) if result and result.get("value"): print(f"Query results: {result['value']}") @@ -139,19 +137,19 @@ async def example_3_query_twins(): print(f"Error: {ex}") -async def example_4_list_relationships(): +def example_4_list_relationships(): """Example 4: List relationships for a twin.""" print("\n=== Example 4: List Relationships ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: twin_id = "room1" # Replace with your twin ID - async with AzuredigitaltwinsClient( + with AzuredigitaltwinsClient( CONNECTION_RUNTIME_URL, credential ) as client: try: # List outgoing relationships - outgoing = [item async for item in client.list_relationships_async(twinid=twin_id)] + outgoing = [item for item in client.list_relationships(twinid=twin_id)] if outgoing: print(f"Outgoing relationships from {twin_id}:") @@ -162,7 +160,7 @@ async def example_4_list_relationships(): print(f"No outgoing relationships from {twin_id}") # List incoming relationships - incoming = [item async for item in client.list_incoming_relationships_async( + incoming = [item for item in client.list_incoming_relationships( twinid=twin_id )] @@ -180,14 +178,14 @@ async def example_4_list_relationships(): print(f"Error: {ex}") -async def example_5_send_telemetry(): +def example_5_send_telemetry(): """Example 5: Send telemetry from a twin.""" print("\n=== Example 5: Send Telemetry ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: twin_id = "room1" # Replace with your twin ID - async with AzuredigitaltwinsClient( + with AzuredigitaltwinsClient( CONNECTION_RUNTIME_URL, credential ) as client: try: @@ -195,7 +193,7 @@ async def example_5_send_telemetry(): telemetry = SendTelemetryInput( value='{"temperature": 72.5, "humidity": 45}' ) - await client.send_telemetry_async( + client.send_telemetry( input=telemetry, twinid=twin_id ) @@ -208,7 +206,7 @@ async def example_5_send_telemetry(): print(f"Error: {ex}") -async def example_6_dataclass_usage(): +def example_6_dataclass_usage(): """Example 6: Working with Azure Digital Twins data types.""" print("\n=== Example 6: Data Types ===") @@ -239,28 +237,28 @@ async def example_6_dataclass_usage(): print(f"Query: {query.query}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: AZUREDIGITALTWINS_CONNECTION_URL environment variable " "not set.") print("Set it to your connection runtime URL from Azure Portal.") print("\nRunning data type examples without connection...\n") - await example_6_dataclass_usage() + example_6_dataclass_usage() return print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_list_models() - await example_2_get_twin() - await example_3_query_twins() - await example_4_list_relationships() + example_1_list_models() + example_2_get_twin() + example_3_query_twins() + example_4_list_relationships() # Uncomment to send telemetry (requires existing twin) # await example_5_send_telemetry() - await example_6_dataclass_usage() + example_6_dataclass_usage() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_azureeventgrid.py b/samples/sample_connector_usage/sample_connector_usage_azureeventgrid.py index 2d7c0bb..ec372f1 100644 --- a/samples/sample_connector_usage/sample_connector_usage_azureeventgrid.py +++ b/samples/sample_connector_usage/sample_connector_usage_azureeventgrid.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure Event Grid Connector SDK Sample +Azure Event Grid sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure Event Grid connector SDK. +This sample demonstrates how to use the Azure Event Grid client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with an Azure Event Grid connection @@ -21,11 +21,9 @@ python sample_connector_usage_azureeventgrid.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors.azureeventgrid import ( AzureeventgridClient, EventRequest, @@ -39,14 +37,14 @@ ) -async def example_1_list_subscriptions(): +def example_1_list_subscriptions(): """Example 1: List Azure subscriptions available to the principal.""" print("\n=== Example 1: List Subscriptions ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureeventgridClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.subscriptions_list_async() + with AzureeventgridClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.list_subscriptions() subscriptions = result.get("value", []) if result else [] print(f"Found {len(subscriptions)} subscription(s).") @@ -56,14 +54,14 @@ async def example_1_list_subscriptions(): print(f" - {display_name} ({subscription_id})") -async def example_2_list_topic_types(): +def example_2_list_topic_types(): """Example 2: List Event Grid topic types.""" print("\n=== Example 2: List Topic Types ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureeventgridClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.topic_types_list_async() + with AzureeventgridClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.list_topic_types() topic_types = result.get("value", []) if result else [] print(f"Found {len(topic_types)} topic type(s).") @@ -71,7 +69,7 @@ async def example_2_list_topic_types(): print(f" - {topic_type.get('name', 'N/A')}") -async def example_3_build_event_request(): +def example_3_build_event_request(): """Example 3: Build an Event Grid request payload.""" print("\n=== Example 3: Build Event Request ===") @@ -94,7 +92,7 @@ async def example_3_build_event_request(): print("The generated client exposes discovery operations, not subscription creation.") -async def main(): +def main(): """Run all Azure Event Grid connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: AZUREEVENTGRID_CONNECTION_URL environment variable is not set.") @@ -103,12 +101,12 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_list_subscriptions() - await example_2_list_topic_types() - await example_3_build_event_request() + example_1_list_subscriptions() + example_2_list_topic_types() + example_3_build_event_request() print("\n=== Azure Event Grid sample completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_azureiotcentral.py b/samples/sample_connector_usage/sample_connector_usage_azureiotcentral.py index 6ad184e..29d84e8 100644 --- a/samples/sample_connector_usage/sample_connector_usage_azureiotcentral.py +++ b/samples/sample_connector_usage/sample_connector_usage_azureiotcentral.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure IoT Central Connector SDK Sample +Azure IoT Central sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure IoT Central connector SDK. +This sample demonstrates how to use the Azure IoT Central client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with an Azure IoT Central connection @@ -22,11 +22,9 @@ python sample_connector_usage_azureiotcentral.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.azureiotcentral import ( AzureiotcentralClient, @@ -44,15 +42,15 @@ APPLICATION = os.environ.get("AZUREIOTCENTRAL_APPLICATION", "") -async def example_1_list_devices(): +def example_1_list_devices(): """Example 1: List devices in the IoT Central application.""" print("\n=== Example 1: List Devices ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureiotcentralClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzureiotcentralClient(CONNECTION_RUNTIME_URL, credential) as client: devices = [ - item async for item in client.devices_list_async( + item for item in client.list_devices( application=APPLICATION ) ] @@ -64,15 +62,15 @@ async def example_1_list_devices(): print(f" - {display_name} ({device_id})") -async def example_2_list_device_groups(): +def example_2_list_device_groups(): """Example 2: List device groups in the IoT Central application.""" print("\n=== Example 2: List Device Groups ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureiotcentralClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzureiotcentralClient(CONNECTION_RUNTIME_URL, credential) as client: device_groups = [ - item async for item in client.device_groups_list_async( + item for item in client.list_device_groups( application=APPLICATION ) ] @@ -84,7 +82,7 @@ async def example_2_list_device_groups(): print(f" - {display_name} ({group_id})") -async def example_3_create_device_group(): +def example_3_create_device_group(): """Example 3: Create or update a device group.""" print("\n=== Example 3: Create Device Group ===") @@ -94,12 +92,15 @@ async def example_3_create_device_group(): print("Set AZUREIOTCENTRAL_DEVICE_GROUP_ID to run this example.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzureiotcentralClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzureiotcentralClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.device_groups_set_async( - input=DeviceGroup(display_name="SDK sample group"), + result = client.device_groups_set( + input=DeviceGroup( + display_name="SDK sample group", + filter="status = 'registered'", + ), device_group_id=device_group_id, application=APPLICATION, ) @@ -109,7 +110,7 @@ async def example_3_create_device_group(): print(f"Connector error: {ex}") -async def main(): +def main(): """Run all Azure IoT Central connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: AZUREIOTCENTRAL_CONNECTION_URL environment variable is not set.") @@ -118,12 +119,12 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_list_devices() - await example_2_list_device_groups() - await example_3_create_device_group() + example_1_list_devices() + example_2_list_device_groups() + example_3_create_device_group() print("\n=== Azure IoT Central sample completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_azuremonitorlogs.py b/samples/sample_connector_usage/sample_connector_usage_azuremonitorlogs.py index 65c0551..d451e41 100644 --- a/samples/sample_connector_usage/sample_connector_usage_azuremonitorlogs.py +++ b/samples/sample_connector_usage/sample_connector_usage_azuremonitorlogs.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure Monitor Logs Connector SDK Sample +Azure Monitor Logs sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure Monitor Logs connector SDK. +This sample demonstrates how to use the Azure Monitor Logs client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Azure Monitor Logs access @@ -22,12 +22,10 @@ python sample_connector_usage_azuremonitorlogs.py """ - -import asyncio import os try: - from azure.identity.aio import DefaultAzureCredential + from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.azuremonitorlogs import ( AzuremonitorlogsClient, @@ -63,19 +61,19 @@ def _print_configuration_help(): print(" AZUREMONITORLOGS_RESOURCE_NAME") -async def example_list_discovery_values(): +def example_list_discovery_values(): """List subscriptions and resource groups using discovery APIs.""" print("\n=== Example 1: Discovery Operations ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzuremonitorlogsClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzuremonitorlogsClient(CONNECTION_RUNTIME_URL, credential) as client: try: - subscriptions = [item async for item in client.list_subscriptions_async()] + subscriptions = [item for item in client.list_subscriptions()] count = len(subscriptions) if subscriptions else 0 print(f"Found {count} subscriptions.") - resource_groups = [item async for item in client.list_resource_groups_async( + resource_groups = [item for item in client.list_resource_groups( subscriptions=SUBSCRIPTION_ID )] rg_count = len(resource_groups) if resource_groups else 0 @@ -87,20 +85,21 @@ async def example_list_discovery_values(): print(f"Error: {ex}") -async def example_run_query(): +def example_run_query(): """Run a KQL query and list tabular rows.""" print("\n=== Example 2: Run Query Data ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzuremonitorlogsClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzuremonitorlogsClient(CONNECTION_RUNTIME_URL, credential) as client: try: request = QueryDataInput( query="Heartbeat | take 5", timerangetype="SetInQuery", + timerange={}, ) - result = await client.query_data_async( + result = client.query_data( input=request, subscriptions=SUBSCRIPTION_ID, resourcegroups=RESOURCE_GROUP, @@ -119,13 +118,13 @@ async def example_run_query(): print(f"Error: {ex}") -async def example_visualize_query(): +def example_visualize_query(): """Run query visualization.""" print("\n=== Example 3: Visualize Query ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzuremonitorlogsClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzuremonitorlogsClient(CONNECTION_RUNTIME_URL, credential) as client: try: request = VisualizeQueryInput( query=( @@ -134,9 +133,10 @@ async def example_visualize_query(): "| order by TimeGenerated asc" ), timerangetype="SetInQuery", + timerange={}, ) - result = await client.visualize_query_async( + result = client.visualize_query( input=request, subscriptions=SUBSCRIPTION_ID, resourcegroups=RESOURCE_GROUP, @@ -157,7 +157,7 @@ async def example_visualize_query(): print(f"Error: {ex}") -async def main(): +def main(): """Run Azure Monitor Logs connector samples.""" if not IMPORTS_AVAILABLE: print("Required imports are unavailable:") @@ -172,10 +172,10 @@ async def main(): _print_configuration_help() return - await example_list_discovery_values() - await example_run_query() - await example_visualize_query() + example_list_discovery_values() + example_run_query() + example_visualize_query() if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_azurequeues.py b/samples/sample_connector_usage/sample_connector_usage_azurequeues.py index cf091bd..7599ece 100644 --- a/samples/sample_connector_usage/sample_connector_usage_azurequeues.py +++ b/samples/sample_connector_usage/sample_connector_usage_azurequeues.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure Storage Queues Connector SDK Sample +Azure Storage Queues sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure Storage Queues connector SDK +This sample demonstrates how to use the Azure Storage Queues client from the Azure Connectors Python SDK to interact with Azure Storage Queue messages. Prerequisites: @@ -23,10 +23,8 @@ python sample_connector_usage_azurequeues.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.azurequeues import AzurequeuesClient @@ -44,7 +42,7 @@ QUEUE_NAME = os.environ.get("AZUREQUEUES_QUEUE_NAME", "") -async def example_1_list_queues(): +def example_1_list_queues(): """Example 1: List all queues in a storage account.""" print("\n=== Example 1: List Queues ===") @@ -53,11 +51,11 @@ async def example_1_list_queues(): print("Example: $env:AZUREQUEUES_STORAGE_ACCOUNT = 'mystorageaccount'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.list_queues_async( + result = client.list_queues( storage_account_name=STORAGE_ACCOUNT ) @@ -81,7 +79,7 @@ async def example_1_list_queues(): print(f"Error: {ex}") -async def example_2_create_queue(): +def example_2_create_queue(): """Example 2: Create a new queue.""" print("\n=== Example 2: Create Queue ===") @@ -92,11 +90,11 @@ async def example_2_create_queue(): print(" $env:AZUREQUEUES_NEW_QUEUE_NAME = 'my-new-queue'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.put_queue_async( + result = client.put_queue( storage_account_name=STORAGE_ACCOUNT, queue_name=new_queue_name ) @@ -111,7 +109,7 @@ async def example_2_create_queue(): print(f"Error: {ex}") -async def example_3_put_message(): +def example_3_put_message(): """Example 3: Put a message on a queue.""" print("\n=== Example 3: Put Message ===") @@ -121,13 +119,13 @@ async def example_3_put_message(): print(" $env:AZUREQUEUES_QUEUE_NAME = ''") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: try: message_input = "Hello from Azure Connectors SDK for Python!" - await client.put_message_async( + client.put_message( input=message_input, storage_account_name=STORAGE_ACCOUNT, queue_name=QUEUE_NAME @@ -142,7 +140,7 @@ async def example_3_put_message(): print(f"Error: {ex}") -async def example_4_get_messages(): +def example_4_get_messages(): """Example 4: Get messages from a queue.""" print("\n=== Example 4: Get Messages ===") @@ -152,11 +150,11 @@ async def example_4_get_messages(): print(" $env:AZUREQUEUES_QUEUE_NAME = ''") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_messages_async( + result = client.get_messages( storage_account_name=STORAGE_ACCOUNT, queue_name=QUEUE_NAME, numofmessages="5", # Get up to 5 messages @@ -186,7 +184,7 @@ async def example_4_get_messages(): print(f"Error: {ex}") -async def example_5_delete_message(): +def example_5_delete_message(): """Example 5: Delete a message from a queue.""" print("\n=== Example 5: Delete Message ===") @@ -202,11 +200,11 @@ async def example_5_delete_message(): print("\nNote: Get message ID and pop receipt from Example 4.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzurequeuesClient(CONNECTION_RUNTIME_URL, credential) as client: try: - await client.delete_message_async( + client.delete_message( storage_account_name=STORAGE_ACCOUNT, queue_name=QUEUE_NAME, message_id=message_id, @@ -221,9 +219,9 @@ async def example_5_delete_message(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" - print("Azure Storage Queues Connector SDK - Sample Usage") + print("Azure Storage Queues sample usage for the Azure Connectors Python SDK") print("=" * 60) if not CONNECTION_RUNTIME_URL: @@ -232,15 +230,15 @@ async def main(): print("Format: https://[region].azure-apihub.net/apim/azurequeues/[id]") return - await example_1_list_queues() - await example_2_create_queue() - await example_3_put_message() - await example_4_get_messages() - await example_5_delete_message() + example_1_list_queues() + example_2_create_queue() + example_3_put_message() + example_4_get_messages() + example_5_delete_message() print("\n" + "=" * 60) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_azuretables.py b/samples/sample_connector_usage/sample_connector_usage_azuretables.py index b3ff375..1fb202d 100644 --- a/samples/sample_connector_usage/sample_connector_usage_azuretables.py +++ b/samples/sample_connector_usage/sample_connector_usage_azuretables.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure Storage Tables Connector SDK Sample +Azure Storage Tables sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure Storage Tables connector SDK +This sample demonstrates how to use the Azure Storage Tables client from the Azure Connectors Python SDK to interact with Azure Table Storage. Prerequisites: @@ -23,10 +23,8 @@ python sample_connector_usage_azuretables.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.azuretables import ( AzuretablesClient, @@ -48,7 +46,7 @@ TABLE_NAME = os.environ.get("AZURETABLES_TABLE_NAME", "") -async def example_1_list_tables(): +def example_1_list_tables(): """Example 1: List all tables in a storage account.""" print("\n=== Example 1: List Tables ===") @@ -57,24 +55,19 @@ async def example_1_list_tables(): print("Example: $env:AZURETABLES_STORAGE_ACCOUNT = 'mystorageaccount'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_tables_async( - storage_account_name=STORAGE_ACCOUNT + tables = list( + client.list_tables(storage_account_name=STORAGE_ACCOUNT) ) - if result: + if tables: print(f"Tables in storage account '{STORAGE_ACCOUNT}':") - # Response contains 'value' with list of tables - tables = result.get("value", []) - if tables: - for table in tables: - table_name = table.get("TableName", table) - print(f" - {table_name}") - else: - print(" No tables found.") + for table in tables: + table_name = table.get("TableName", table) + print(f" - {table_name}") else: print("No tables found or empty response.") @@ -84,7 +77,7 @@ async def example_1_list_tables(): print(f"Error: {ex}") -async def example_2_create_table(): +def example_2_create_table(): """Example 2: Create a new table in the storage account.""" print("\n=== Example 2: Create Table ===") @@ -95,16 +88,16 @@ async def example_2_create_table(): print(" $env:AZURETABLES_NEW_TABLE_NAME = 'MyNewTable'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Create table input with table name in additional_properties table_input = CreateTableInput( additional_properties={"TableName": new_table_name} ) - result = await client.create_table_async( + result = client.create_table( input=table_input, storage_account_name=STORAGE_ACCOUNT ) @@ -120,7 +113,7 @@ async def example_2_create_table(): print(f"Error: {ex}") -async def example_3_create_entity(): +def example_3_create_entity(): """Example 3: Insert a new entity into a table.""" print("\n=== Example 3: Create Entity ===") @@ -130,9 +123,9 @@ async def example_3_create_entity(): print(" $env:AZURETABLES_TABLE_NAME = ''") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Create entity with PartitionKey, RowKey, and custom properties entity_input = CreateEntityInput( @@ -146,7 +139,7 @@ async def example_3_create_entity(): } ) - result = await client.create_entity_async( + result = client.create_entity( input=entity_input, storage_account_name=STORAGE_ACCOUNT, table_name=TABLE_NAME @@ -165,7 +158,7 @@ async def example_3_create_entity(): print(f"Error: {ex}") -async def example_4_get_entities(): +def example_4_get_entities(): """Example 4: Query entities from a table.""" print("\n=== Example 4: Get Entities ===") @@ -175,12 +168,12 @@ async def example_4_get_entities(): print(" $env:AZURETABLES_TABLE_NAME = ''") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Query entities with optional filter - entities = [item async for item in client.get_entities_async( + entities = [item for item in client.list_entities( storage_account_name=STORAGE_ACCOUNT, table_name=TABLE_NAME, # Optional: filter entities @@ -206,7 +199,7 @@ async def example_4_get_entities(): print(f"Error: {ex}") -async def example_5_get_entity(): +def example_5_get_entity(): """Example 5: Get a specific entity by PartitionKey and RowKey.""" print("\n=== Example 5: Get Entity ===") @@ -222,11 +215,11 @@ async def example_5_get_entity(): print(" $env:AZURETABLES_ROW_KEY = ''") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzuretablesClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_entity_async( + result = client.get_entity( storage_account_name=STORAGE_ACCOUNT, table_name=TABLE_NAME, partition_key=partition_key, @@ -258,9 +251,9 @@ async def example_5_get_entity(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" - print("Azure Storage Tables Connector SDK - Sample Usage") + print("Azure Storage Tables sample usage for the Azure Connectors Python SDK") print("=" * 60) if not CONNECTION_RUNTIME_URL: @@ -269,15 +262,15 @@ async def main(): print("Format: https://[region].azure-apihub.net/apim/azuretables/[id]") return - await example_1_list_tables() - await example_2_create_table() - await example_3_create_entity() - await example_4_get_entities() - await example_5_get_entity() + example_1_list_tables() + example_2_create_table() + example_3_create_entity() + example_4_get_entities() + example_5_get_entity() print("\n" + "=" * 60) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_azurevm.py b/samples/sample_connector_usage/sample_connector_usage_azurevm.py index 1b222a5..ffd92ce 100644 --- a/samples/sample_connector_usage/sample_connector_usage_azurevm.py +++ b/samples/sample_connector_usage/sample_connector_usage_azurevm.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure VM Connector SDK Sample +Azure VM sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure VM connector SDK to manage +This sample demonstrates how to use the Azure VM client from the Azure Connectors Python SDK to manage virtual machines and VM scale sets. Prerequisites: @@ -20,10 +20,8 @@ python sample_connector_usage_azurevm.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.azurevm import AzurevmClient @@ -42,15 +40,15 @@ VMSS_INSTANCE_ID = os.environ.get("AZURE_VMSS_INSTANCE_ID", "0") -async def example_1_get_virtual_machine(): +def example_1_get_virtual_machine(): """Example 1: Get details of a virtual machine.""" print("\n=== Example 1: Get Virtual Machine ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.virtual_machine_get_async( + result = client.virtual_machine_get( subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP, virtual_machine_name=VM_NAME @@ -70,15 +68,15 @@ async def example_1_get_virtual_machine(): print(f"Error: {ex}") -async def example_2_start_virtual_machine(): +def example_2_start_virtual_machine(): """Example 2: Start a virtual machine.""" print("\n=== Example 2: Start Virtual Machine ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: try: - await client.virtual_machine_start_async( + client.virtual_machine_start( subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP, virtual_machine_name=VM_NAME @@ -93,15 +91,15 @@ async def example_2_start_virtual_machine(): print(f"Error: {ex}") -async def example_3_deallocate_virtual_machine(): +def example_3_deallocate_virtual_machine(): """Example 3: Deallocate (stop and release resources) a virtual machine.""" print("\n=== Example 3: Deallocate Virtual Machine ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: try: - await client.virtual_machine_deallocate_async( + client.virtual_machine_deallocate( subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP, virtual_machine_name=VM_NAME @@ -116,15 +114,15 @@ async def example_3_deallocate_virtual_machine(): print(f"Error: {ex}") -async def example_4_restart_virtual_machine(): +def example_4_restart_virtual_machine(): """Example 4: Restart a virtual machine.""" print("\n=== Example 4: Restart Virtual Machine ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: try: - await client.virtual_machine_restart_async( + client.virtual_machine_restart( subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP, virtual_machine_name=VM_NAME @@ -138,15 +136,15 @@ async def example_4_restart_virtual_machine(): print(f"Error: {ex}") -async def example_5_get_vm_in_scale_set(): +def example_5_get_vm_in_scale_set(): """Example 5: Get details of a VM in a scale set.""" print("\n=== Example 5: Get VM in Scale Set ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.virtual_machine_in_scale_set_get_async( + result = client.virtual_machine_in_scale_set_get( subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP, virtual_machine_scale_set_name=VMSS_NAME, @@ -167,17 +165,17 @@ async def example_5_get_vm_in_scale_set(): print(f"Error: {ex}") -async def example_6_scale_set_operations(): +def example_6_scale_set_operations(): """Example 6: Perform operations on a VM in a scale set.""" print("\n=== Example 6: Scale Set VM Operations ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: + with AzurevmClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Start VM in scale set print(f"Starting VMSS instance {VMSS_INSTANCE_ID}...") - await client.virtual_machine_in_scale_set_start_async( + client.virtual_machine_in_scale_set_start( subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP, virtual_machine_scale_set_name=VMSS_NAME, @@ -186,11 +184,11 @@ async def example_6_scale_set_operations(): print("Start command sent") # Other available operations (commented out): - # - virtual_machine_in_scale_set_deallocate_async - # - virtual_machine_in_scale_set_power_off_async - # - virtual_machine_in_scale_set_restart_async - # - virtual_machine_in_scale_set_redeploy_async - # - virtual_machine_in_scale_set_reimage_async + # - virtual_machine_in_scale_set_deallocate + # - virtual_machine_in_scale_set_power_off + # - virtual_machine_in_scale_set_restart + # - virtual_machine_in_scale_set_redeploy + # - virtual_machine_in_scale_set_reimage except ConnectorException as ex: print(f"Connector error: {ex}") @@ -198,7 +196,7 @@ async def example_6_scale_set_operations(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: AZUREVM_CONNECTION_URL environment variable not set.") @@ -208,7 +206,7 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") # Only run the read-only example by default - await example_1_get_virtual_machine() + example_1_get_virtual_machine() # Uncomment to run VM control operations: # await example_2_start_virtual_machine() @@ -221,4 +219,4 @@ async def main(): if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_box.py b/samples/sample_connector_usage/sample_connector_usage_box.py index c0d3db7..2c224ff 100644 --- a/samples/sample_connector_usage/sample_connector_usage_box.py +++ b/samples/sample_connector_usage/sample_connector_usage_box.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Box Connector SDK Sample +Box sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Box connector SDK. +This sample demonstrates how to use the Box client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Box connection @@ -19,11 +19,9 @@ python sample_connector_usage_box.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.box import BoxClient @@ -35,14 +33,14 @@ ) -async def example_1_list_root_folder(): +def example_1_list_root_folder(): """Example 1: List items in the root folder.""" print("\n=== Example 1: List Root Folder ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with BoxClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.list_root_folder_async() + with BoxClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.list_root_folder() if result and "value" in result: print(f"Found {len(result['value'])} items in root folder:") @@ -53,7 +51,7 @@ async def example_1_list_root_folder(): print("No root-folder items returned.") -async def example_2_get_file_metadata_by_path(): +def example_2_get_file_metadata_by_path(): """Example 2: Get file metadata by path.""" print("\n=== Example 2: Get Metadata by Path ===") @@ -62,11 +60,11 @@ async def example_2_get_file_metadata_by_path(): print("Set BOX_TEST_FILE_PATH, for example '/Documents/report.pdf'.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with BoxClient(CONNECTION_RUNTIME_URL, credential) as client: + with BoxClient(CONNECTION_RUNTIME_URL, credential) as client: try: - metadata = await client.get_file_metadata_by_path_async(path=file_path) + metadata = client.get_file_metadata_by_path(path=file_path) if metadata: print(f"Name: {metadata.get('Name', 'N/A')}") @@ -78,18 +76,18 @@ async def example_2_get_file_metadata_by_path(): print(f"Connector error: {ex}") -async def example_3_create_file(): +def example_3_create_file(): """Example 3: Upload a file from bytes content.""" print("\n=== Example 3: Create File ===") destination_folder = os.environ.get("BOX_TEST_DEST_FOLDER", "/Documents") destination_name = os.environ.get("BOX_TEST_FILE_NAME", "sdk-sample.txt") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with BoxClient(CONNECTION_RUNTIME_URL, credential) as client: + with BoxClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.create_file_async( + result = client.create_file( input=b"Hello from azure-connectors Box sample!", folder_path=destination_folder, name=destination_name, @@ -103,7 +101,7 @@ async def example_3_create_file(): print(f"Connector error: {ex}") -async def example_4_list_folder_for_polling(): +def example_4_list_folder_for_polling(): """Example 4: List a folder as the basis for polling logic.""" print("\n=== Example 4: List Folder for Polling ===") @@ -112,11 +110,11 @@ async def example_4_list_folder_for_polling(): print("Set BOX_TEST_FOLDER_ID to test trigger polling calls.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with BoxClient(CONNECTION_RUNTIME_URL, credential) as client: + with BoxClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.list_folder_async(id=folder_id) + result = client.list_folder(id=folder_id) items = result.get("value", []) if result else [] print(f"Folder listing returned {len(items)} item(s).") print("Persist item IDs or timestamps to implement polling with this action client.") @@ -124,7 +122,7 @@ async def example_4_list_folder_for_polling(): print(f"Connector error: {ex}") -async def main(): +def main(): """Run all Box connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: BOX_CONNECTION_URL environment variable is not set.") @@ -133,13 +131,13 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_list_root_folder() - await example_2_get_file_metadata_by_path() - await example_3_create_file() - await example_4_list_folder_for_polling() + example_1_list_root_folder() + example_2_get_file_metadata_by_path() + example_3_create_file() + example_4_list_folder_for_polling() print("\n=== Box sample completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_campfire.py b/samples/sample_connector_usage/sample_connector_usage_campfire.py index 40e68e0..1695c80 100644 --- a/samples/sample_connector_usage/sample_connector_usage_campfire.py +++ b/samples/sample_connector_usage/sample_connector_usage_campfire.py @@ -1,7 +1,7 @@ """ -Campfire Connector SDK Sample +Campfire sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Campfire connector SDK. +This sample demonstrates how to use the Campfire client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a Campfire connection @@ -17,11 +17,9 @@ python sample_connector_usage_campfire.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.campfire import CampfireClient @@ -32,58 +30,58 @@ CONNECTION_RUNTIME_URL = os.environ.get("CAMPFIRE_CONNECTION_URL", "") -async def example_1_list_accounts() -> None: +def example_1_list_accounts() -> None: """Example 1: List accounts this user has access to.""" print("\n=== Example 1: List Accounts ===") - async with DefaultAzureCredential() as credential: - async with CampfireClient(CONNECTION_RUNTIME_URL, credential) as client: - accounts = await client.list_accounts_async() + with DefaultAzureCredential() as credential: + with CampfireClient(CONNECTION_RUNTIME_URL, credential) as client: + accounts = client.list_accounts() print(f"Accounts: {accounts}") -async def example_2_list_rooms() -> None: +def example_2_list_rooms() -> None: """Example 2: List the rooms in an account.""" print("\n=== Example 2: List Rooms ===") - async with DefaultAzureCredential() as credential: - async with CampfireClient(CONNECTION_RUNTIME_URL, credential) as client: - rooms = await client.list_rooms_async(account="ACCOUNT_ID") + with DefaultAzureCredential() as credential: + with CampfireClient(CONNECTION_RUNTIME_URL, credential) as client: + rooms = client.list_rooms(account="ACCOUNT_ID") print(f"Rooms: {rooms}") -async def example_3_create_message() -> None: +def example_3_create_message() -> None: """Example 3: Send a message to a room.""" print("\n=== Example 3: Create Message ===") - async with DefaultAzureCredential() as credential: - async with CampfireClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.create_message_async( + with DefaultAzureCredential() as credential: + with CampfireClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.create_message( room_id="ROOM_ID", account="ACCOUNT_ID", - message="Hello from the Campfire connector SDK.", + message="Hello from the Campfire client in the Azure Connectors Python SDK.", ) print(f"Create message result: {result}") -async def example_4_get_user() -> None: +def example_4_get_user() -> None: """Example 4: Get information about a user by ID.""" print("\n=== Example 4: Get User ===") - async with DefaultAzureCredential() as credential: - async with CampfireClient(CONNECTION_RUNTIME_URL, credential) as client: - user = await client.get_user_async(user_id=12345, account="ACCOUNT_ID") + with DefaultAzureCredential() as credential: + with CampfireClient(CONNECTION_RUNTIME_URL, credential) as client: + user = client.get_user(user_id=12345, account="ACCOUNT_ID") print(f"User: {user}") -async def main() -> None: +def main() -> None: """Run Campfire connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: CAMPFIRE_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Campfire Connector SDK - Sample Usage") + print("Campfire sample usage for the Azure Connectors Python SDK") print("=" * 50) try: @@ -101,4 +99,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_clicksendsms.py b/samples/sample_connector_usage/sample_connector_usage_clicksendsms.py index d0983e2..8000122 100644 --- a/samples/sample_connector_usage/sample_connector_usage_clicksendsms.py +++ b/samples/sample_connector_usage/sample_connector_usage_clicksendsms.py @@ -1,7 +1,7 @@ """ -ClickSend SMS Connector SDK Sample +ClickSend SMS sample for the Azure Connectors Python SDK -This sample demonstrates how to use the ClickSend SMS connector SDK. +This sample demonstrates how to use the ClickSend SMS client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a ClickSend SMS connection @@ -17,11 +17,9 @@ python sample_connector_usage_clicksendsms.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.clicksendsms import ( @@ -36,18 +34,18 @@ CONNECTION_RUNTIME_URL = os.environ.get("CLICKSENDSMS_CONNECTION_URL", "") -async def example_1_send_sms() -> None: +def example_1_send_sms() -> None: """Example 1: Send an SMS message.""" print("\n=== Example 1: Send SMS ===") - async with DefaultAzureCredential() as credential: - async with ClicksendsmsClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.sms_send_async( + with DefaultAzureCredential() as credential: + with ClicksendsmsClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.sms_send( input=SmsSendInput( messages=[ { "to": "+61411111111", - "body": "Hello from the ClickSend SMS connector SDK.", + "body": "Hello from the ClickSend SMS client in the Azure Connectors Python SDK.", } ], ), @@ -55,46 +53,46 @@ async def example_1_send_sms() -> None: print(f"Send result: {result}") -async def example_2_get_contact_lists() -> None: +def example_2_get_contact_lists() -> None: """Example 2: Get contact lists.""" print("\n=== Example 2: Get Contact Lists ===") - async with DefaultAzureCredential() as credential: - async with ClicksendsmsClient(CONNECTION_RUNTIME_URL, credential) as client: - lists = await client.get_contact_lists_async(page=1, limit=10) + with DefaultAzureCredential() as credential: + with ClicksendsmsClient(CONNECTION_RUNTIME_URL, credential) as client: + lists = client.get_contact_lists(page=1, limit=10) print(f"Contact lists: {lists}") -async def example_3_create_list() -> None: +def example_3_create_list() -> None: """Example 3: Create a new contact list.""" print("\n=== Example 3: Create Contact List ===") - async with DefaultAzureCredential() as credential: - async with ClicksendsmsClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.create_list_async( + with DefaultAzureCredential() as credential: + with ClicksendsmsClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.create_list( input=CreateListInput(list_name="My New List"), ) print(f"Created list: {result}") -async def example_4_search_contact_lists() -> None: +def example_4_search_contact_lists() -> None: """Example 4: Search contact lists.""" print("\n=== Example 4: Search Contact Lists ===") - async with DefaultAzureCredential() as credential: - async with ClicksendsmsClient(CONNECTION_RUNTIME_URL, credential) as client: - results = await client.search_contact_list_async(q="friends") + with DefaultAzureCredential() as credential: + with ClicksendsmsClient(CONNECTION_RUNTIME_URL, credential) as client: + results = client.search_contact_list(q="friends") print(f"Search results: {results}") -async def main() -> None: +def main() -> None: """Run ClickSend SMS connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: CLICKSENDSMS_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("ClickSend SMS Connector SDK - Sample Usage") + print("ClickSend SMS sample usage for the Azure Connectors Python SDK") print("=" * 50) try: @@ -112,4 +110,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_cloudconvert.py b/samples/sample_connector_usage/sample_connector_usage_cloudconvert.py index 1530954..416c7e7 100644 --- a/samples/sample_connector_usage/sample_connector_usage_cloudconvert.py +++ b/samples/sample_connector_usage/sample_connector_usage_cloudconvert.py @@ -1,9 +1,7 @@ -"""CloudConvert connector SDK sample.""" - -import asyncio +"""CloudConvert sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.cloudconvert import CloudconvertClient @@ -12,20 +10,20 @@ CONNECTION_RUNTIME_URL = os.environ.get("CLOUDCONVERT_CONNECTION_URL", "") -async def main() -> None: +def main() -> None: """Get CloudConvert conversion options.""" if not CONNECTION_RUNTIME_URL: print("Set CLOUDCONVERT_CONNECTION_URL to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with CloudconvertClient(CONNECTION_RUNTIME_URL, credential) as client: - options = await client.get_convert_options_async() + with CloudconvertClient(CONNECTION_RUNTIME_URL, credential) as client: + options = client.get_convert_options() print(f"Conversion options: {options}") except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_cloudmersiveconvert.py b/samples/sample_connector_usage/sample_connector_usage_cloudmersiveconvert.py index 55f9be3..236412d 100644 --- a/samples/sample_connector_usage/sample_connector_usage_cloudmersiveconvert.py +++ b/samples/sample_connector_usage/sample_connector_usage_cloudmersiveconvert.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Cloudmersive Convert Connector SDK Sample +Cloudmersive Convert sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Cloudmersive Convert connector SDK. +This sample demonstrates how to use the Cloudmersive Convert client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a Cloudmersive Convert connection @@ -20,11 +20,9 @@ python sample_connector_usage_cloudmersiveconvert.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.cloudmersiveconvert import ( @@ -38,19 +36,19 @@ CONNECTION_RUNTIME_URL = os.environ.get("CLOUDMERSIVECONVERT_CONNECTION_URL", "") -async def example_1_convert_url_to_pdf(): +def example_1_convert_url_to_pdf(): """Example 1: Convert a web page URL to a PDF document.""" print("\n=== Example 1: Convert URL to PDF ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with CloudmersiveconvertClient(CONNECTION_RUNTIME_URL, credential) as client: + with CloudmersiveconvertClient(CONNECTION_RUNTIME_URL, credential) as client: try: request = ScreenshotRequest( url="https://www.example.com", ) - result = await client.convert_web_url_to_pdf_async(input=request) + result = client.convert_web_url_to_pdf(input=request) print(f"Converted PDF byte length: {len(result) if result else 0}") @@ -60,19 +58,19 @@ async def example_1_convert_url_to_pdf(): print(f"Error: {ex}") -async def example_2_get_docx_body(): +def example_2_get_docx_body(): """Example 2: Get the body content from a Word DOCX document.""" print("\n=== Example 2: Get DOCX body ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with CloudmersiveconvertClient(CONNECTION_RUNTIME_URL, credential) as client: + with CloudmersiveconvertClient(CONNECTION_RUNTIME_URL, credential) as client: try: request = GetDocxBodyRequest( input_file_url="https://example.com/document.docx", ) - result = await client.edit_document_docx_body_async(input=request) + result = client.edit_document_docx_body(input=request) print(f"DOCX body result: {result}") @@ -82,7 +80,7 @@ async def example_2_get_docx_body(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: CLOUDMERSIVECONVERT_CONNECTION_URL environment variable not set.") @@ -91,11 +89,11 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_convert_url_to_pdf() - await example_2_get_docx_body() + example_1_convert_url_to_pdf() + example_2_get_docx_body() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_commondataservice.py b/samples/sample_connector_usage/sample_connector_usage_commondataservice.py index 28f2a7a..c565964 100644 --- a/samples/sample_connector_usage/sample_connector_usage_commondataservice.py +++ b/samples/sample_connector_usage/sample_connector_usage_commondataservice.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Microsoft Dataverse (Common Data Service) Connector SDK Sample +Microsoft Dataverse (Common Data Service) sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Microsoft Dataverse connector SDK. +This sample demonstrates how to use the Microsoft Dataverse client from the Azure Connectors Python SDK. This connector was formerly known as Common Data Service (legacy). Prerequisites: @@ -26,10 +26,8 @@ python sample_connector_usage_commondataservice.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.commondataservice import ( CommondataserviceClient, @@ -53,15 +51,15 @@ ) -async def example_1_list_datasets(): +def example_1_list_datasets(): """Example 1: List the datasets (environments) available to the connection.""" print("\n=== Example 1: List Datasets ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_data_sets_async() + result = client.list_data_sets() if result and result.get("value"): print(f"Found {len(result['value'])} datasets:") @@ -76,20 +74,20 @@ async def example_1_list_datasets(): print(f"Error: {ex}") -async def example_2_list_accounts(): +def example_2_list_accounts(): """Example 2: List rows from the 'accounts' table. Retrieves account rows with OData query options. """ print("\n=== Example 2: List Accounts ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: try: accounts = [ account - async for account in client.get_items_async( + for account in client.list_items( dataset=DATASET, table="accounts", filter="statecode eq 0", # Active accounts only @@ -111,18 +109,18 @@ async def example_2_list_accounts(): print(f"Error: {ex}") -async def example_3_get_account_by_id(): +def example_3_get_account_by_id(): """Example 3: Get a single account row by its primary id.""" print("\n=== Example 3: Get Account by ID ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: # Replace with an actual account id from your Dataverse environment. account_id = "00000000-0000-0000-0000-000000000000" - async with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_item_async( + result = client.get_item( dataset=DATASET, table="accounts", id=account_id, @@ -140,13 +138,13 @@ async def example_3_get_account_by_id(): print(f"Error: {ex}") -async def example_4_create_account(): +def example_4_create_account(): """Example 4: Add a new row to the 'accounts' table.""" print("\n=== Example 4: Create Account ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: try: new_account = PostItemInput( additional_properties={ @@ -157,7 +155,7 @@ async def example_4_create_account(): } ) - result = await client.post_item_async( + result = client.post_item( input=new_account, dataset=DATASET, table="accounts", @@ -174,16 +172,16 @@ async def example_4_create_account(): print(f"Error: {ex}") -async def example_5_update_account(): +def example_5_update_account(): """Example 5: Update an existing row in the 'accounts' table.""" print("\n=== Example 5: Update Account ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: # Replace with an actual account id. account_id = "00000000-0000-0000-0000-000000000000" - async with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: try: update_data = PatchItemInput( additional_properties={ @@ -192,7 +190,7 @@ async def example_5_update_account(): } ) - await client.patch_item_async( + client.patch_item( input=update_data, dataset=DATASET, table="accounts", @@ -207,18 +205,18 @@ async def example_5_update_account(): print(f"Error: {ex}") -async def example_6_create_attachment(): +def example_6_create_attachment(): """Example 6: Add a note attachment to an account row.""" print("\n=== Example 6: Create Account Attachment ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: # Replace with an actual account id from your Dataverse environment. account_id = "00000000-0000-0000-0000-000000000000" - async with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.create_attachment_async( + result = client.create_attachment( input=b"Sample attachment content", dataset=DATASET, table="accounts", @@ -237,15 +235,15 @@ async def example_6_create_attachment(): print(f"Error: {ex}") -async def example_7_get_table_metadata(): +def example_7_get_table_metadata(): """Example 7: Get metadata for the 'accounts' table.""" print("\n=== Example 7: Get Table Metadata ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + with CommondataserviceClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_table_async( + result = client.get_table( dataset=DATASET, table="accounts", ) @@ -261,7 +259,7 @@ async def example_7_get_table_metadata(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: COMMONDATASERVICE_CONNECTION_URL environment variable not set.") @@ -271,16 +269,16 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") print(f"Using dataset: {DATASET}") - await example_1_list_datasets() - await example_2_list_accounts() - await example_3_get_account_by_id() - await example_4_create_account() - await example_5_update_account() - await example_6_create_attachment() - await example_7_get_table_metadata() + example_1_list_datasets() + example_2_list_accounts() + example_3_get_account_by_id() + example_4_create_account() + example_5_update_account() + example_6_create_attachment() + example_7_get_table_metadata() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_documentdb.py b/samples/sample_connector_usage/sample_connector_usage_documentdb.py index 66891a9..6c1b5ed 100644 --- a/samples/sample_connector_usage/sample_connector_usage_documentdb.py +++ b/samples/sample_connector_usage/sample_connector_usage_documentdb.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure Cosmos DB (DocumentDB) Connector SDK Sample +Azure Cosmos DB (DocumentDB) sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure Cosmos DB connector SDK +This sample demonstrates how to use the Azure Cosmos DB client from the Azure Connectors Python SDK to query documents in Cosmos DB containers. Note: The connector name "documentdb" reflects the original Azure DocumentDB @@ -27,10 +27,8 @@ python sample_connector_usage_documentdb.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.documentdb import DocumentdbClient @@ -51,7 +49,7 @@ CONTAINER_ID = os.environ.get("DOCUMENTDB_CONTAINER", "") -async def example_1_query_all_documents(): +def example_1_query_all_documents(): """Example 1: Query all documents in a container.""" print("\n=== Example 1: Query All Documents ===") @@ -62,11 +60,11 @@ async def example_1_query_all_documents(): print(" $env:DOCUMENTDB_CONTAINER = ''") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: + with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: try: - documents = [item async for item in client.query_documents_async( + documents = [item for item in client.list_query_documents( cosmos_db_account_name=COSMOS_DB_ACCOUNT, database_id=DATABASE_ID, container_id=CONTAINER_ID, @@ -90,7 +88,7 @@ async def example_1_query_all_documents(): print(f"Error: {ex}") -async def example_2_query_with_filter(): +def example_2_query_with_filter(): """Example 2: Query documents with a filter condition.""" print("\n=== Example 2: Query with Filter ===") @@ -98,12 +96,12 @@ async def example_2_query_with_filter(): print("Set environment variables to query documents.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: + with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Query with WHERE clause - adjust field names for your schema - documents = [item async for item in client.query_documents_async( + documents = [item for item in client.list_query_documents( cosmos_db_account_name=COSMOS_DB_ACCOUNT, database_id=DATABASE_ID, container_id=CONTAINER_ID, @@ -126,7 +124,7 @@ async def example_2_query_with_filter(): print(f"Error: {ex}") -async def example_3_query_with_pagination(): +def example_3_query_with_pagination(): """Example 3: Query documents across automatically followed pages.""" print("\n=== Example 3: Query with Automatic Pagination ===") @@ -134,12 +132,12 @@ async def example_3_query_with_pagination(): print("Set environment variables to query documents.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: + with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: try: # The iterator follows continuation links until all pages are consumed. - documents = [item async for item in client.query_documents_async( + documents = [item for item in client.list_query_documents( cosmos_db_account_name=COSMOS_DB_ACCOUNT, database_id=DATABASE_ID, container_id=CONTAINER_ID, @@ -160,7 +158,7 @@ async def example_3_query_with_pagination(): print(f"Error: {ex}") -async def example_4_query_with_partition_key(): +def example_4_query_with_partition_key(): """Example 4: Query documents with a specific partition key.""" print("\n=== Example 4: Query with Partition Key ===") @@ -175,12 +173,12 @@ async def example_4_query_with_partition_key(): print("Skipping partition key example...") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: + with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Query within a specific partition - documents = [item async for item in client.query_documents_async( + documents = [item for item in client.list_query_documents( cosmos_db_account_name=COSMOS_DB_ACCOUNT, database_id=DATABASE_ID, container_id=CONTAINER_ID, @@ -201,7 +199,7 @@ async def example_4_query_with_partition_key(): print(f"Error: {ex}") -async def example_5_query_with_consistency(): +def example_5_query_with_consistency(): """Example 5: Query documents with a specific consistency level.""" print("\n=== Example 5: Query with Consistency Level ===") @@ -209,13 +207,13 @@ async def example_5_query_with_consistency(): print("Set environment variables to query documents.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: + with DocumentdbClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Query with Session consistency (common for read-your-writes) # Valid levels: Strong, BoundedStaleness, Session, Eventual - documents = [item async for item in client.query_documents_async( + documents = [item for item in client.list_query_documents( cosmos_db_account_name=COSMOS_DB_ACCOUNT, database_id=DATABASE_ID, container_id=CONTAINER_ID, @@ -238,9 +236,9 @@ async def example_5_query_with_consistency(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" - print("Azure Cosmos DB (DocumentDB) Connector SDK - Sample Usage") + print("Azure Cosmos DB (DocumentDB) sample usage for the Azure Connectors Python SDK") print("=" * 60) if not CONNECTION_RUNTIME_URL: @@ -249,15 +247,15 @@ async def main(): print("Format: https://[region].azure-apihub.net/apim/documentdb/[id]") return - await example_1_query_all_documents() - await example_2_query_with_filter() - await example_3_query_with_pagination() - await example_4_query_with_partition_key() - await example_5_query_with_consistency() + example_1_query_all_documents() + example_2_query_with_filter() + example_3_query_with_pagination() + example_4_query_with_partition_key() + example_5_query_with_consistency() print("\n" + "=" * 60) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_docusign.py b/samples/sample_connector_usage/sample_connector_usage_docusign.py index 64f5d52..14ca5a1 100644 --- a/samples/sample_connector_usage/sample_connector_usage_docusign.py +++ b/samples/sample_connector_usage/sample_connector_usage_docusign.py @@ -1,7 +1,7 @@ """ -DocuSign Connector SDK Sample +DocuSign sample for the Azure Connectors Python SDK -This sample demonstrates how to use the DocuSign connector SDK. +This sample demonstrates how to use the DocuSign client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with DocuSign connection @@ -17,11 +17,9 @@ python sample_connector_usage_docusign.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.docusign import DocusignClient @@ -32,13 +30,13 @@ CONNECTION_RUNTIME_URL = os.environ.get("DOCUSIGN_CONNECTION_URL", "") -async def example_1_get_login_accounts() -> list[dict]: +def example_1_get_login_accounts() -> list[dict]: """Example 1: Get available DocuSign accounts.""" print("\n=== Example 1: Get Login Accounts ===") - async with DefaultAzureCredential() as credential: - async with DocusignClient(CONNECTION_RUNTIME_URL, credential) as client: - accounts_response = await client.get_login_accounts_async() + with DefaultAzureCredential() as credential: + with DocusignClient(CONNECTION_RUNTIME_URL, credential) as client: + accounts_response = client.list_login_accounts() accounts = accounts_response.get("accounts", []) if accounts_response else [] print(f"Found {len(accounts)} accounts") @@ -48,13 +46,13 @@ async def example_1_get_login_accounts() -> list[dict]: return accounts -async def example_2_search_envelopes(account_id: str) -> None: +def example_2_search_envelopes(account_id: str) -> None: """Example 2: Search envelopes for an account.""" print("\n=== Example 2: Search Envelopes ===") - async with DefaultAzureCredential() as credential: - async with DocusignClient(CONNECTION_RUNTIME_URL, credential) as client: - envelopes_response = await client.search_list_envelopes_async( + with DefaultAzureCredential() as credential: + with DocusignClient(CONNECTION_RUNTIME_URL, credential) as client: + envelopes_response = client.search_list_envelopes( account_id=account_id, top=5, ) @@ -65,22 +63,22 @@ async def example_2_search_envelopes(account_id: str) -> None: print(f" - {envelope.get('envelopeId')} ({envelope.get('status')})") -async def main() -> None: +def main() -> None: """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: DOCUSIGN_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("DocuSign Connector SDK - Sample Usage") + print("DocuSign sample usage for the Azure Connectors Python SDK") print("=" * 50) try: - accounts = await example_1_get_login_accounts() + accounts = example_1_get_login_accounts() if accounts: first_account_id = accounts[0].get("accountId") if first_account_id: - await example_2_search_envelopes(first_account_id) + example_2_search_envelopes(first_account_id) else: print("No account id found in first record; skipping envelope search.") else: @@ -93,4 +91,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_docuware.py b/samples/sample_connector_usage/sample_connector_usage_docuware.py index d3789be..46db62d 100644 --- a/samples/sample_connector_usage/sample_connector_usage_docuware.py +++ b/samples/sample_connector_usage/sample_connector_usage_docuware.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -DocuWare Connector SDK Sample +DocuWare sample for the Azure Connectors Python SDK -This sample demonstrates how to use the DocuWare connector SDK. +This sample demonstrates how to use the DocuWare client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a DocuWare connection @@ -20,11 +20,9 @@ python sample_connector_usage_docuware.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.docuware import ( @@ -37,15 +35,15 @@ CONNECTION_RUNTIME_URL = os.environ.get("DOCUWARE_CONNECTION_URL", "") -async def example_1_get_file_cabinets(): +def example_1_get_file_cabinets(): """Example 1: List available file cabinets and document trays.""" print("\n=== Example 1: Get file cabinets ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with DocuwareClient(CONNECTION_RUNTIME_URL, credential) as client: + with DocuwareClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_file_cabinets_async( + result = client.list_file_cabinets( file_cabinet_type="", ) @@ -57,17 +55,17 @@ async def example_1_get_file_cabinets(): print(f"Error: {ex}") -async def example_2_search_documents(): +def example_2_search_documents(): """Example 2: Search a file cabinet for matching documents.""" print("\n=== Example 2: Search documents in file cabinet ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with DocuwareClient(CONNECTION_RUNTIME_URL, credential) as client: + with DocuwareClient(CONNECTION_RUNTIME_URL, credential) as client: try: request = SearchForDocumentsInFileCabinetInput() - result = await client.search_for_documents_in_file_cabinet_async( + result = client.search_for_documents_in_file_cabinet( input=request, file_cabinet="", search_dialog_id="", @@ -81,7 +79,7 @@ async def example_2_search_documents(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: DOCUWARE_CONNECTION_URL environment variable not set.") @@ -90,11 +88,11 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_get_file_cabinets() - await example_2_search_documents() + example_1_get_file_cabinets() + example_2_search_documents() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_dropbox.py b/samples/sample_connector_usage/sample_connector_usage_dropbox.py index 04c3cf7..76e2a02 100644 --- a/samples/sample_connector_usage/sample_connector_usage_dropbox.py +++ b/samples/sample_connector_usage/sample_connector_usage_dropbox.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Dropbox Connector SDK Sample +Dropbox sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Dropbox connector SDK. +This sample demonstrates how to use the Dropbox client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Dropbox connection @@ -19,11 +19,9 @@ python sample_connector_usage_dropbox.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.dropbox import DropboxClient @@ -35,14 +33,14 @@ ) -async def example_1_list_root_folder(): +def example_1_list_root_folder(): """Example 1: List items in the root folder.""" print("\n=== Example 1: List Root Folder ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with DropboxClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.list_root_folder_async() + with DropboxClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.list_root_folder() if result and "value" in result: print(f"Found {len(result['value'])} items in root folder:") @@ -53,7 +51,7 @@ async def example_1_list_root_folder(): print("No root-folder items returned.") -async def example_2_get_file_metadata_by_path(): +def example_2_get_file_metadata_by_path(): """Example 2: Get file metadata by path.""" print("\n=== Example 2: Get Metadata by Path ===") @@ -62,11 +60,11 @@ async def example_2_get_file_metadata_by_path(): print("Set DROPBOX_TEST_FILE_PATH, for example '/Documents/report.pdf'.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with DropboxClient(CONNECTION_RUNTIME_URL, credential) as client: + with DropboxClient(CONNECTION_RUNTIME_URL, credential) as client: try: - metadata = await client.get_file_metadata_by_path_async(path=file_path) + metadata = client.get_file_metadata_by_path(path=file_path) if metadata: print(f"Name: {metadata.get('Name', 'N/A')}") @@ -78,18 +76,18 @@ async def example_2_get_file_metadata_by_path(): print(f"Connector error: {ex}") -async def example_3_create_file(): +def example_3_create_file(): """Example 3: Upload a text file.""" print("\n=== Example 3: Create File ===") destination_folder = os.environ.get("DROPBOX_TEST_DEST_FOLDER", "/Documents") destination_name = os.environ.get("DROPBOX_TEST_FILE_NAME", "sdk-sample.txt") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with DropboxClient(CONNECTION_RUNTIME_URL, credential) as client: + with DropboxClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.create_file_async( + result = client.create_file( input=b"Hello from azure-connectors Dropbox sample!", folder_path=destination_folder, name=destination_name, @@ -103,7 +101,7 @@ async def example_3_create_file(): print(f"Connector error: {ex}") -async def example_4_list_folder_for_polling(): +def example_4_list_folder_for_polling(): """Example 4: List a folder as the basis for polling logic.""" print("\n=== Example 4: List Folder for Polling ===") @@ -112,11 +110,11 @@ async def example_4_list_folder_for_polling(): print("Set DROPBOX_TEST_FOLDER_ID to test trigger polling calls.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with DropboxClient(CONNECTION_RUNTIME_URL, credential) as client: + with DropboxClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.list_folder_async(id=folder_id) + result = client.list_folder(id=folder_id) items = result.get("value", []) if result else [] print(f"Folder listing returned {len(items)} item(s).") print("Persist item IDs or timestamps to implement polling with this action client.") @@ -124,7 +122,7 @@ async def example_4_list_folder_for_polling(): print(f"Connector error: {ex}") -async def main(): +def main(): """Run all Dropbox connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: DROPBOX_CONNECTION_URL environment variable is not set.") @@ -133,13 +131,13 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_list_root_folder() - await example_2_get_file_metadata_by_path() - await example_3_create_file() - await example_4_list_folder_for_polling() + example_1_list_root_folder() + example_2_get_file_metadata_by_path() + example_3_create_file() + example_4_list_folder_for_polling() print("\n=== Dropbox sample completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_dynamicsax.py b/samples/sample_connector_usage/sample_connector_usage_dynamicsax.py index c57d10f..8f7171f 100644 --- a/samples/sample_connector_usage/sample_connector_usage_dynamicsax.py +++ b/samples/sample_connector_usage/sample_connector_usage_dynamicsax.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Dynamics 365 for Finance and Operations (Dynamics AX) Connector SDK Sample +Dynamics 365 for Finance and Operations (Dynamics AX) sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Dynamics AX connector SDK. +This sample demonstrates how to use the Dynamics AX client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a Dynamics AX connection @@ -22,11 +22,9 @@ python sample_connector_usage_dynamicsax.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.dynamicsax import ( DynamicsaxClient, @@ -44,14 +42,14 @@ DATASET = os.environ.get("DYNAMICSAX_DATASET", "") -async def example_1_list_instances(): +def example_1_list_instances(): """Example 1: List accessible Dynamics 365 Fin & Ops instances.""" print("\n=== Example 1: List Instances ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with DynamicsaxClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.get_data_sets_async() + with DynamicsaxClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.list_data_sets() datasets = result.get("value", []) if result else [] print(f"Found {len(datasets)} instance(s).") @@ -59,7 +57,7 @@ async def example_1_list_instances(): print(f" - {dataset.get('name', 'N/A')}") -async def example_2_list_tables(): +def example_2_list_tables(): """Example 2: List entities (tables) for an instance.""" print("\n=== Example 2: List Tables ===") @@ -67,10 +65,10 @@ async def example_2_list_tables(): print("Set DYNAMICSAX_DATASET to run this example.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with DynamicsaxClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.get_tables_async(dataset=DATASET) + with DynamicsaxClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.list_tables(dataset=DATASET) tables = result.get("value", []) if result else [] print(f"Found {len(tables)} table(s).") @@ -78,7 +76,7 @@ async def example_2_list_tables(): print(f" - {table.get('name', 'N/A')}") -async def example_3_create_record(): +def example_3_create_record(): """Example 3: Create a new record in an entity.""" print("\n=== Example 3: Create Record ===") @@ -88,13 +86,13 @@ async def example_3_create_record(): print("Set DYNAMICSAX_DATASET and DYNAMICSAX_TABLE to run this example.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with DynamicsaxClient(CONNECTION_RUNTIME_URL, credential) as client: + with DynamicsaxClient(CONNECTION_RUNTIME_URL, credential) as client: try: record = PostItemInput() record.additional_properties = {"Name": "SDK Sample"} - result = await client.post_item_async( + result = client.post_item( input=record, dataset=DATASET, table=table, @@ -104,7 +102,7 @@ async def example_3_create_record(): print(f"Connector error: {ex}") -async def main(): +def main(): """Run all Dynamics AX connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: DYNAMICSAX_CONNECTION_URL environment variable is not set.") @@ -113,12 +111,12 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_list_instances() - await example_2_list_tables() - await example_3_create_record() + example_1_list_instances() + example_2_list_tables() + example_3_create_record() print("\n=== Dynamics AX sample completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_elfsquaddata.py b/samples/sample_connector_usage/sample_connector_usage_elfsquaddata.py index bfbaa6c..0dbeb22 100644 --- a/samples/sample_connector_usage/sample_connector_usage_elfsquaddata.py +++ b/samples/sample_connector_usage/sample_connector_usage_elfsquaddata.py @@ -1,9 +1,7 @@ -"""Elfsquad Data connector SDK sample.""" - -import asyncio +"""Elfsquad Data sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.elfsquaddata import ElfsquaddataClient @@ -13,7 +11,7 @@ ENTITY_NAME = os.environ.get("ELFSQUADDATA_ENTITY_NAME", "") -async def main() -> None: +def main() -> None: """List entities from an Elfsquad Data entity set.""" if not CONNECTION_RUNTIME_URL or not ENTITY_NAME: print( @@ -22,13 +20,13 @@ async def main() -> None: ) return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with ElfsquaddataClient( + with ElfsquaddataClient( CONNECTION_RUNTIME_URL, credential, ) as client: - entities = [item async for item in client.get_entities_async( + entities = [item for item in client.list_entities( entity_name=ENTITY_NAME, top=10, )] @@ -38,4 +36,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_etsy.py b/samples/sample_connector_usage/sample_connector_usage_etsy.py index c31a6b9..5176ec8 100644 --- a/samples/sample_connector_usage/sample_connector_usage_etsy.py +++ b/samples/sample_connector_usage/sample_connector_usage_etsy.py @@ -1,9 +1,7 @@ -"""Etsy connector SDK sample.""" - -import asyncio +"""Etsy sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.etsy import EtsyClient @@ -12,20 +10,20 @@ CONNECTION_RUNTIME_URL = os.environ.get("ETSY_CONNECTION_URL", "") -async def main() -> None: +def main() -> None: """Ping the Etsy connector.""" if not CONNECTION_RUNTIME_URL: print("Set ETSY_CONNECTION_URL to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with EtsyClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.ping_async() + with EtsyClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.ping() print(f"Result: {result}") except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_eventbrite.py b/samples/sample_connector_usage/sample_connector_usage_eventbrite.py index bf25156..176ce0a 100644 --- a/samples/sample_connector_usage/sample_connector_usage_eventbrite.py +++ b/samples/sample_connector_usage/sample_connector_usage_eventbrite.py @@ -1,9 +1,7 @@ -"""Eventbrite connector SDK sample.""" - -import asyncio +"""Eventbrite sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.eventbrite import EventbriteClient @@ -12,20 +10,20 @@ CONNECTION_RUNTIME_URL = os.environ.get("EVENTBRITE_CONNECTION_URL", "") -async def main() -> None: +def main() -> None: """List Eventbrite event categories.""" if not CONNECTION_RUNTIME_URL: print("Set EVENTBRITE_CONNECTION_URL to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with EventbriteClient(CONNECTION_RUNTIME_URL, credential) as client: - categories = await client.get_categories_async() + with EventbriteClient(CONNECTION_RUNTIME_URL, credential) as client: + categories = client.list_categories() print(f"Categories: {categories}") except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_eventhubs.py b/samples/sample_connector_usage/sample_connector_usage_eventhubs.py index 9d5bc0e..1e3f7c2 100644 --- a/samples/sample_connector_usage/sample_connector_usage_eventhubs.py +++ b/samples/sample_connector_usage/sample_connector_usage_eventhubs.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure Event Hubs Connector SDK Sample +Azure Event Hubs sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure Event Hubs connector SDK +This sample demonstrates how to use the Azure Event Hubs client from the Azure Connectors Python SDK to send and receive events from Azure Event Hubs. Prerequisites: @@ -22,11 +22,9 @@ python sample_connector_usage_eventhubs.py """ - -import asyncio import json import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.eventhubs import ( EventhubsClient, @@ -45,7 +43,7 @@ EVENT_HUB_NAME = os.environ.get("EVENTHUBS_HUB_NAME", "") -async def example_1_send_event(): +def example_1_send_event(): """Example 1: Send a single event to Event Hub.""" print("\n=== Example 1: Send Single Event ===") @@ -54,9 +52,9 @@ async def example_1_send_event(): print("Example: $env:EVENTHUBS_HUB_NAME = 'my-event-hub'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: + with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Create a single event event = SendEvent( @@ -71,7 +69,7 @@ async def example_1_send_event(): } ) - await client.send_event_async( + client.send_event( input=event, event_hub_name=EVENT_HUB_NAME ) @@ -86,7 +84,7 @@ async def example_1_send_event(): print(f"Error: {ex}") -async def example_2_send_event_with_partition_key(): +def example_2_send_event_with_partition_key(): """Example 2: Send an event with a specific partition key.""" print("\n=== Example 2: Send Event with Partition Key ===") @@ -95,9 +93,9 @@ async def example_2_send_event_with_partition_key(): return partition_key = os.environ.get("EVENTHUBS_PARTITION_KEY", "partition-1") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: + with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: try: event = SendEvent( content_data=json.dumps({ @@ -110,7 +108,7 @@ async def example_2_send_event_with_partition_key(): } ) - await client.send_event_async( + client.send_event( input=event, event_hub_name=EVENT_HUB_NAME, partition_key=partition_key @@ -125,7 +123,7 @@ async def example_2_send_event_with_partition_key(): print(f"Error: {ex}") -async def example_3_send_batch_events(): +def example_3_send_batch_events(): """Example 3: Send multiple events in a batch.""" print("\n=== Example 3: Send Batch Events ===") @@ -133,9 +131,9 @@ async def example_3_send_batch_events(): print("Set EVENTHUBS_HUB_NAME environment variable.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: + with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Create batch with multiple events batch_input = SendEventsInput( @@ -157,7 +155,7 @@ async def example_3_send_batch_events(): } ) - await client.send_events_async( + client.send_events( input=batch_input, event_hub_name=EVENT_HUB_NAME, partition_key=os.environ.get("EVENTHUBS_PARTITION_KEY", "partition-1") @@ -174,15 +172,15 @@ async def example_3_send_batch_events(): print(f"Error: {ex}") -async def example_4_list_event_hubs(): +def example_4_list_event_hubs(): """Example 4: List Event Hubs in the namespace.""" print("\n=== Example 4: List Event Hubs ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: + with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_event_hubs_async() + result = client.list_event_hubs() print(f"Event Hubs: {result}") except ConnectorException as ex: @@ -191,7 +189,7 @@ async def example_4_list_event_hubs(): print(f"Error: {ex}") -async def example_5_list_consumer_groups(): +def example_5_list_consumer_groups(): """Example 5: List consumer groups for an Event Hub.""" print("\n=== Example 5: List Consumer Groups ===") @@ -199,11 +197,11 @@ async def example_5_list_consumer_groups(): print("Set EVENTHUBS_HUB_NAME environment variable.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: + with EventhubsClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_consumer_groups_async( + result = client.list_consumer_groups( event_hub_name=EVENT_HUB_NAME ) print(f"Consumer groups for '{EVENT_HUB_NAME}': {result}") @@ -214,9 +212,9 @@ async def example_5_list_consumer_groups(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" - print("Azure Event Hubs Connector SDK - Sample Usage") + print("Azure Event Hubs sample usage for the Azure Connectors Python SDK") print("=" * 60) if not CONNECTION_RUNTIME_URL: @@ -225,15 +223,15 @@ async def main(): print("Format: https://[region].azure-apihub.net/apim/eventhubs/[id]") return - await example_1_send_event() - await example_2_send_event_with_partition_key() - await example_3_send_batch_events() - await example_4_list_event_hubs() - await example_5_list_consumer_groups() + example_1_send_event() + example_2_send_event_with_partition_key() + example_3_send_batch_events() + example_4_list_event_hubs() + example_5_list_consumer_groups() print("\n" + "=" * 60) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_excelonline.py b/samples/sample_connector_usage/sample_connector_usage_excelonline.py index 4d0e6a2..644036b 100644 --- a/samples/sample_connector_usage/sample_connector_usage_excelonline.py +++ b/samples/sample_connector_usage/sample_connector_usage_excelonline.py @@ -1,11 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """Sample usage for the Excelonline connector client.""" - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors.excelonline import ( CreateWorksheetInput, @@ -14,7 +12,7 @@ ) -async def main() -> None: +def main() -> None: """Run a simple Excel Online sample flow.""" connection_url = os.getenv("EXCELONLINE_CONNECTION_URL") if not connection_url: @@ -24,28 +22,28 @@ async def main() -> None: file_id = os.getenv("EXCELONLINE_FILE_ID", "file-id") table_name = os.getenv("EXCELONLINE_TABLE_NAME", "Table1") - async with DefaultAzureCredential() as credential: - async with ExcelonlineClient(connection_url, credential) as client: - worksheets = await client.get_all_worksheets_async( + with DefaultAzureCredential() as credential: + with ExcelonlineClient(connection_url, credential) as client: + worksheets = client.list_all_worksheets( drive=drive_id, file=file_id, ) print("worksheets", worksheets) - tables = await client.get_tables_async( + tables = client.list_tables( drive=drive_id, file=file_id, ) print("tables", tables) - new_sheet = await client.create_worksheet_async( + new_sheet = client.create_worksheet( input=CreateWorksheetInput(name="SampleSheet"), drive=drive_id, file=file_id, ) print("created worksheet", new_sheet) - row = await client.add_row_async( + row = client.add_row( input=Item(dynamic_properties={"Name": "Sample Item", "Value": 100}), drive=drive_id, file=file_id, @@ -55,4 +53,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_excelonlinebusiness.py b/samples/sample_connector_usage/sample_connector_usage_excelonlinebusiness.py index 0cb93ce..98b9eeb 100644 --- a/samples/sample_connector_usage/sample_connector_usage_excelonlinebusiness.py +++ b/samples/sample_connector_usage/sample_connector_usage_excelonlinebusiness.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Excel Online (Business) Connector SDK Sample +Excel Online (Business) sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Excel Online Business connector SDK +This sample demonstrates how to use the Excel Online Business client from the Azure Connectors Python SDK to work with Excel files stored in SharePoint document libraries. Prerequisites: @@ -24,10 +24,8 @@ python sample_connector_usage_excelonlinebusiness.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.excelonlinebusiness import ( ExcelonlinebusinessClient, @@ -55,7 +53,7 @@ SOURCE_URL = os.environ.get("EXCELONLINE_SOURCE_URL", "") -async def example_1_list_table_rows(): +def example_1_list_table_rows(): """Example 1: List rows in an Excel table.""" print("\n=== Example 1: List Table Rows ===") @@ -67,11 +65,11 @@ async def example_1_list_table_rows(): print(" $env:EXCELONLINE_SOURCE_URL = '' (optional)") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: try: - rows = [item async for item in client.get_items_async( + rows = [item for item in client.list_items( drive=DRIVE_ID, file=FILE_ID, table=TABLE_NAME, @@ -94,7 +92,7 @@ async def example_1_list_table_rows(): print(f"Error: {ex}") -async def example_2_get_specific_row(): +def example_2_get_specific_row(): """Example 2: Get a specific row by key value.""" print("\n=== Example 2: Get Specific Row ===") @@ -110,11 +108,11 @@ async def example_2_get_specific_row(): print(" $env:EXCELONLINE_ID_COLUMN = '' (optional)") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_item_async( + result = client.get_item( drive=DRIVE_ID, file=FILE_ID, table=TABLE_NAME, @@ -137,7 +135,7 @@ async def example_2_get_specific_row(): print(f"Error: {ex}") -async def example_3_list_workbook_comments(): +def example_3_list_workbook_comments(): """Example 3: List comments in an Excel workbook.""" print("\n=== Example 3: List Workbook Comments ===") @@ -147,11 +145,11 @@ async def example_3_list_workbook_comments(): print(" $env:EXCELONLINE_FILE_ID = ''") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_comments_async( + result = client.list_comments( drive=DRIVE_ID, file=FILE_ID, source=SOURCE_URL if SOURCE_URL else None, @@ -175,7 +173,7 @@ async def example_3_list_workbook_comments(): print(f"Error: {ex}") -async def example_4_create_table(): +def example_4_create_table(): """Example 4: Create a new table in an Excel workbook.""" print("\n=== Example 4: Create Table ===") @@ -192,9 +190,9 @@ async def example_4_create_table(): print(" $env:EXCELONLINE_COLUMN_NAMES = 'Name;Email;Phone' (optional)") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: try: table_input = TableToCreate( table_name=new_table_name, @@ -202,7 +200,7 @@ async def example_4_create_table(): columns_names=column_names if column_names else None, ) - result = await client.create_table_async( + result = client.create_table( input=table_input, drive=DRIVE_ID, file=FILE_ID, @@ -222,7 +220,7 @@ async def example_4_create_table(): print(f"Error: {ex}") -async def example_5_update_row(): +def example_5_update_row(): """Example 5: Update a row in an Excel table.""" print("\n=== Example 5: Update Row ===") @@ -238,9 +236,9 @@ async def example_5_update_row(): print(" $env:EXCELONLINE_ID_COLUMN = '' (optional)") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + with ExcelonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Create an Item with the fields to update # The dynamic_properties dict contains column-value pairs @@ -251,7 +249,7 @@ async def example_5_update_row(): } ) - result = await client.patch_item_async( + result = client.patch_item( input=update_data, drive=DRIVE_ID, file=FILE_ID, @@ -275,9 +273,9 @@ async def example_5_update_row(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" - print("Excel Online (Business) Connector SDK - Sample Usage") + print("Excel Online (Business) sample usage for the Azure Connectors Python SDK") print("=" * 60) if not CONNECTION_RUNTIME_URL: @@ -286,15 +284,15 @@ async def main(): print("Format: https://[region].azure-apihub.net/apim/excelonlinebusiness/[connection-id]") return - await example_1_list_table_rows() - await example_2_get_specific_row() - await example_3_list_workbook_comments() - await example_4_create_table() - await example_5_update_row() + example_1_list_table_rows() + example_2_get_specific_row() + example_3_list_workbook_comments() + example_4_create_table() + example_5_update_row() print("\n" + "=" * 60) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_formstackforms.py b/samples/sample_connector_usage/sample_connector_usage_formstackforms.py index 6d4c6c4..7164451 100644 --- a/samples/sample_connector_usage/sample_connector_usage_formstackforms.py +++ b/samples/sample_connector_usage/sample_connector_usage_formstackforms.py @@ -1,9 +1,7 @@ -"""Formstack Forms connector SDK sample.""" - -import asyncio +"""Formstack Forms sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.formstackforms import FormstackformsClient @@ -12,23 +10,23 @@ CONNECTION_RUNTIME_URL = os.environ.get("FORMSTACKFORMS_CONNECTION_URL", "") -async def main() -> None: +def main() -> None: """List available Formstack forms.""" if not CONNECTION_RUNTIME_URL: print("Set FORMSTACKFORMS_CONNECTION_URL to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with FormstackformsClient( + with FormstackformsClient( CONNECTION_RUNTIME_URL, credential, ) as client: - forms = await client.get_available_forms_async() + forms = client.get_available_forms() print(f"Forms: {forms}") except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_freshservice.py b/samples/sample_connector_usage/sample_connector_usage_freshservice.py index 0c81eb3..b79afba 100644 --- a/samples/sample_connector_usage/sample_connector_usage_freshservice.py +++ b/samples/sample_connector_usage/sample_connector_usage_freshservice.py @@ -1,7 +1,7 @@ """ -Freshservice Connector SDK Sample +Freshservice sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Freshservice connector SDK. +This sample demonstrates how to use the Freshservice client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Freshservice connection @@ -17,11 +17,9 @@ python sample_connector_usage_freshservice.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.freshservice import ( @@ -37,12 +35,12 @@ CONNECTION_RUNTIME_URL = os.environ.get("FRESHSERVICE_CONNECTION_URL", "") -async def example_1_create_ticket() -> None: +def example_1_create_ticket() -> None: """Example 1: Create a ticket.""" print("\n=== Example 1: Create Ticket ===") - async with DefaultAzureCredential() as credential: - async with FreshserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + with DefaultAzureCredential() as credential: + with FreshserviceClient(CONNECTION_RUNTIME_URL, credential) as client: request = CreateTicketRequest( subject="SDK sample ticket", description="Created from the freshservice SDK sample.", @@ -51,48 +49,48 @@ async def example_1_create_ticket() -> None: status="2", ) - created = await client.create_ticket_async(input=request) + created = client.create_ticket(input=request) ticket = created.get("ticket", {}) if created else {} print(f"Created ticket: {ticket.get('id')}") -async def example_2_update_ticket() -> None: +def example_2_update_ticket() -> None: """Example 2: Update an existing ticket.""" print("\n=== Example 2: Update Ticket ===") - async with DefaultAzureCredential() as credential: - async with FreshserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + with DefaultAzureCredential() as credential: + with FreshserviceClient(CONNECTION_RUNTIME_URL, credential) as client: request = UpdateTicketRequest(priority="3", status="3") - updated = await client.update_ticket_async(input=request, ticket_id=1) + updated = client.update_ticket(input=request, ticket_id=1) ticket = updated.get("ticket", {}) if updated else {} print(f"Updated ticket: {ticket.get('id')}") -async def example_3_add_note() -> None: +def example_3_add_note() -> None: """Example 3: Add a note to a ticket.""" print("\n=== Example 3: Add Note ===") - async with DefaultAzureCredential() as credential: - async with FreshserviceClient(CONNECTION_RUNTIME_URL, credential) as client: + with DefaultAzureCredential() as credential: + with FreshserviceClient(CONNECTION_RUNTIME_URL, credential) as client: request = AddNoteRequest( body="Note added from the freshservice SDK sample.", private=True, ) - note = await client.add_note_async(input=request, ticket_id=1) + note = client.add_note(input=request, ticket_id=1) conversation = note.get("conversation", {}) if note else {} print(f"Added note: {conversation.get('id')}") -async def main() -> None: +def main() -> None: """Run Freshservice connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: FRESHSERVICE_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Freshservice Connector SDK - Sample Usage") + print("Freshservice sample usage for the Azure Connectors Python SDK") print("=" * 50) try: @@ -109,4 +107,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_ftp.py b/samples/sample_connector_usage/sample_connector_usage_ftp.py index a2ada01..29cd4b3 100644 --- a/samples/sample_connector_usage/sample_connector_usage_ftp.py +++ b/samples/sample_connector_usage/sample_connector_usage_ftp.py @@ -1,16 +1,14 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """Sample usage for the FTP connector client.""" - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors.ftp import FtpClient -async def main() -> None: +def main() -> None: """Run a simple FTP sample flow.""" connection_url = os.getenv("FTP_CONNECTION_URL") if not connection_url: @@ -19,21 +17,21 @@ async def main() -> None: folder_path = os.getenv("FTP_FOLDER_PATH", "/inbound") file_name = os.getenv("FTP_FILE_NAME", "sample-from-sdk.txt") - async with DefaultAzureCredential() as credential: - async with FtpClient(connection_url, credential) as client: - root_listing = await client.list_root_folder_async() + with DefaultAzureCredential() as credential: + with FtpClient(connection_url, credential) as client: + root_listing = client.list_root_folder() print("root listing", root_listing) - created = await client.create_file_async( + created = client.create_file( input=b"hello from azure-connectors ftp sample", folder_path=folder_path, name=file_name, ) print("created file", created) - folder_items = await client.list_folder_async(id=folder_path) + folder_items = client.list_folder(id=folder_path) print("folder items available for polling", folder_items) if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_github.py b/samples/sample_connector_usage/sample_connector_usage_github.py index 7cb5fdf..d3c7d54 100644 --- a/samples/sample_connector_usage/sample_connector_usage_github.py +++ b/samples/sample_connector_usage/sample_connector_usage_github.py @@ -1,7 +1,7 @@ """ -GitHub Connector SDK Sample +GitHub sample for the Azure Connectors Python SDK -This sample demonstrates how to use the GitHub connector SDK. +This sample demonstrates how to use the GitHub client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with GitHub connection @@ -17,11 +17,9 @@ python sample_connector_usage_github.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.github import GithubClient, IssueBasicDetailsModel @@ -32,23 +30,23 @@ CONNECTION_RUNTIME_URL = os.environ.get("GITHUB_CONNECTION_URL", "") -async def example_1_get_authenticated_user() -> None: +def example_1_get_authenticated_user() -> None: """Example 1: Get authenticated GitHub user.""" print("\n=== Example 1: Get Authenticated User ===") - async with DefaultAzureCredential() as credential: - async with GithubClient(CONNECTION_RUNTIME_URL, credential) as client: - user = await client.get_user_async() + with DefaultAzureCredential() as credential: + with GithubClient(CONNECTION_RUNTIME_URL, credential) as client: + user = client.get_user() print(f"Authenticated as: {user.get('login') if user else 'unknown'}") -async def example_2_list_issues(repository_owner: str, repository_name: str) -> None: +def example_2_list_issues(repository_owner: str, repository_name: str) -> None: """Example 2: List open issues in a repository.""" print("\n=== Example 2: List Issues ===") - async with DefaultAzureCredential() as credential: - async with GithubClient(CONNECTION_RUNTIME_URL, credential) as client: - issues = await client.get_issues_async( + with DefaultAzureCredential() as credential: + with GithubClient(CONNECTION_RUNTIME_URL, credential) as client: + issues = client.list_issues( repository_owner=repository_owner, repository_name=repository_name, state="open", @@ -61,17 +59,17 @@ async def example_2_list_issues(repository_owner: str, repository_name: str) -> print(f" - #{issue.get('number')}: {issue.get('title')}") -async def example_3_create_issue(repository_owner: str, repository_name: str) -> None: +def example_3_create_issue(repository_owner: str, repository_name: str) -> None: """Example 3: Create a new issue in a repository.""" print("\n=== Example 3: Create Issue ===") - async with DefaultAzureCredential() as credential: - async with GithubClient(CONNECTION_RUNTIME_URL, credential) as client: + with DefaultAzureCredential() as credential: + with GithubClient(CONNECTION_RUNTIME_URL, credential) as client: request = IssueBasicDetailsModel( title="SDK sample issue", body="Created from github Python SDK sample.", ) - created = await client.create_issue_async( + created = client.create_issue( input=request, repository_owner=repository_owner, repository_name=repository_name, @@ -80,7 +78,7 @@ async def example_3_create_issue(repository_owner: str, repository_name: str) -> print(f"Created issue: #{created.get('number') if created else 'n/a'}") -async def main() -> None: +def main() -> None: """Run GitHub connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: GITHUB_CONNECTION_URL environment variable not set.") @@ -91,12 +89,12 @@ async def main() -> None: repository_owner = "octocat" repository_name = "hello-world" - print("GitHub Connector SDK - Sample Usage") + print("GitHub sample usage for the Azure Connectors Python SDK") print("=" * 50) try: - await example_1_get_authenticated_user() - await example_2_list_issues(repository_owner, repository_name) + example_1_get_authenticated_user() + example_2_list_issues(repository_owner, repository_name) # Uncomment after confirming write permissions. # await example_3_create_issue(repository_owner, repository_name) @@ -107,4 +105,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_googlecalendar.py b/samples/sample_connector_usage/sample_connector_usage_googlecalendar.py index 1d91b4e..30a05eb 100644 --- a/samples/sample_connector_usage/sample_connector_usage_googlecalendar.py +++ b/samples/sample_connector_usage/sample_connector_usage_googlecalendar.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Google Calendar Connector SDK Sample +Google Calendar sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Google Calendar connector SDK. +This sample demonstrates how to use the Google Calendar client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Google Calendar connection @@ -21,11 +21,9 @@ python sample_connector_usage_googlecalendar.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.googlecalendar import ( GooglecalendarClient, @@ -40,14 +38,14 @@ ) -async def example_1_list_calendars(): +def example_1_list_calendars(): """Example 1: List calendars visible to the connection account.""" print("\n=== Example 1: List Calendars ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with GooglecalendarClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.list_calendars_async(min_access_role="reader") + with GooglecalendarClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.list_calendars(min_access_role="reader") items = result.get("items", []) if result else [] print(f"Found {len(items)} calendar(s).") @@ -55,7 +53,7 @@ async def example_1_list_calendars(): print(f" - {calendar.get('summary', 'N/A')} ({calendar.get('id', 'N/A')})") -async def example_2_list_events(): +def example_2_list_events(): """Example 2: List events for a configured calendar.""" print("\n=== Example 2: List Events ===") @@ -64,10 +62,10 @@ async def example_2_list_events(): print("Set GOOGLECALENDAR_TEST_CALENDAR_ID to run this example.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with GooglecalendarClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.list_events_async(calendar_id=calendar_id) + with GooglecalendarClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.list_events(calendar_id=calendar_id) events = result.get("items", []) if result else [] print(f"Found {len(events)} event(s) in calendar '{calendar_id}'.") @@ -75,7 +73,7 @@ async def example_2_list_events(): print(f" - {event.get('summary', 'N/A')} ({event.get('id', 'N/A')})") -async def example_3_create_event(): +def example_3_create_event(): """Example 3: Create a test event in the configured calendar.""" print("\n=== Example 3: Create Event ===") @@ -84,9 +82,9 @@ async def example_3_create_event(): print("Set GOOGLECALENDAR_TEST_CALENDAR_ID to run this example.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with GooglecalendarClient(CONNECTION_RUNTIME_URL, credential) as client: + with GooglecalendarClient(CONNECTION_RUNTIME_URL, credential) as client: try: payload = RequestEvent( summary="SDK Sample Event", @@ -97,7 +95,7 @@ async def example_3_create_event(): status="confirmed", ) - created = await client.create_event_async(input=payload, calendar_id=calendar_id) + created = client.create_event(input=payload, calendar_id=calendar_id) if created: print(f"Created event id: {created.get('id', 'N/A')}") else: @@ -106,7 +104,7 @@ async def example_3_create_event(): print(f"Connector error: {ex}") -async def example_4_list_events_for_polling(): +def example_4_list_events_for_polling(): """Example 4: List events in a time window for polling logic.""" print("\n=== Example 4: List Events for Polling ===") @@ -115,11 +113,11 @@ async def example_4_list_events_for_polling(): print("Set GOOGLECALENDAR_TEST_CALENDAR_ID to run this example.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with GooglecalendarClient(CONNECTION_RUNTIME_URL, credential) as client: + with GooglecalendarClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.list_events_async( + result = client.list_events( calendar_id=calendar_id, time_min="2026-07-09T00:00:00Z", time_max="2026-07-10T00:00:00Z", @@ -131,7 +129,7 @@ async def example_4_list_events_for_polling(): print(f"Connector error: {ex}") -async def main(): +def main(): """Run all Google Calendar connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: GOOGLECALENDAR_CONNECTION_URL environment variable is not set.") @@ -140,13 +138,13 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_list_calendars() - await example_2_list_events() - await example_3_create_event() - await example_4_list_events_for_polling() + example_1_list_calendars() + example_2_list_events() + example_3_create_event() + example_4_list_events_for_polling() print("\n=== Google Calendar sample completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_googledrive.py b/samples/sample_connector_usage/sample_connector_usage_googledrive.py index bf64875..bb4bace 100644 --- a/samples/sample_connector_usage/sample_connector_usage_googledrive.py +++ b/samples/sample_connector_usage/sample_connector_usage_googledrive.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Google Drive Connector SDK Sample +Google Drive sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Google Drive connector SDK. +This sample demonstrates how to use the Google Drive client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Google Drive connection @@ -21,11 +21,9 @@ python sample_connector_usage_googledrive.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.googledrive import GoogledriveClient @@ -37,14 +35,14 @@ ) -async def example_1_list_root_folder(): +def example_1_list_root_folder(): """Example 1: List items in the root folder.""" print("\n=== Example 1: List Root Folder ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with GoogledriveClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.list_root_folder_async() + with GoogledriveClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.list_root_folder() if result and "value" in result: print(f"Found {len(result['value'])} items in root folder:") @@ -55,7 +53,7 @@ async def example_1_list_root_folder(): print("No root-folder items returned.") -async def example_2_get_file_metadata_by_path(): +def example_2_get_file_metadata_by_path(): """Example 2: Retrieve file metadata by path.""" print("\n=== Example 2: Get Metadata by Path ===") @@ -64,11 +62,11 @@ async def example_2_get_file_metadata_by_path(): print("Set GOOGLEDRIVE_TEST_FILE_PATH, for example '/Documents/report.pdf'.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with GoogledriveClient(CONNECTION_RUNTIME_URL, credential) as client: + with GoogledriveClient(CONNECTION_RUNTIME_URL, credential) as client: try: - metadata = await client.get_file_metadata_by_path_async(path=file_path) + metadata = client.get_file_metadata_by_path(path=file_path) if metadata: print(f"Name: {metadata.get('Name', 'N/A')}") @@ -80,18 +78,18 @@ async def example_2_get_file_metadata_by_path(): print(f"Connector error: {ex}") -async def example_3_create_file(): +def example_3_create_file(): """Example 3: Upload a text file.""" print("\n=== Example 3: Create File ===") destination_folder = os.environ.get("GOOGLEDRIVE_TEST_DEST_FOLDER", "/Documents") destination_name = os.environ.get("GOOGLEDRIVE_TEST_FILE_NAME", "sdk-sample.txt") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with GoogledriveClient(CONNECTION_RUNTIME_URL, credential) as client: + with GoogledriveClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.create_file_async( + result = client.create_file( input=b"Hello from azure-connectors Google Drive sample!", folder_id=destination_folder, name=destination_name, @@ -105,7 +103,7 @@ async def example_3_create_file(): print(f"Connector error: {ex}") -async def example_4_list_drive_items_for_sheet_selection(): +def example_4_list_drive_items_for_sheet_selection(): """Example 4: List Drive items to locate a Google Sheet file.""" print("\n=== Example 4: Find Google Sheet Files ===") @@ -114,11 +112,11 @@ async def example_4_list_drive_items_for_sheet_selection(): print("Set GOOGLEDRIVE_TEST_SHEET_FOLDER to a Drive folder id.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with GoogledriveClient(CONNECTION_RUNTIME_URL, credential) as client: + with GoogledriveClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.list_folder_async(id=folder_id) + result = client.list_folder(id=folder_id) if result and "value" in result: print(f"Found {len(result['value'])} Drive item(s):") @@ -130,7 +128,7 @@ async def example_4_list_drive_items_for_sheet_selection(): print(f"Connector error: {ex}") -async def main(): +def main(): """Run all Google Drive connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: GOOGLEDRIVE_CONNECTION_URL environment variable is not set.") @@ -139,13 +137,13 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_list_root_folder() - await example_2_get_file_metadata_by_path() - await example_3_create_file() - await example_4_list_drive_items_for_sheet_selection() + example_1_list_root_folder() + example_2_get_file_metadata_by_path() + example_3_create_file() + example_4_list_drive_items_for_sheet_selection() print("\n=== Google Drive sample completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_googletasks.py b/samples/sample_connector_usage/sample_connector_usage_googletasks.py index 9e2258a..7daba6a 100644 --- a/samples/sample_connector_usage/sample_connector_usage_googletasks.py +++ b/samples/sample_connector_usage/sample_connector_usage_googletasks.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Google Tasks Connector SDK Sample +Google Tasks sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Google Tasks connector SDK. +This sample demonstrates how to use the Google Tasks client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Google Tasks connection @@ -21,11 +21,9 @@ python sample_connector_usage_googletasks.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.googletasks import ( GoogletasksClient, @@ -42,14 +40,14 @@ ) -async def example_1_list_task_lists(): +def example_1_list_task_lists(): """Example 1: List task lists.""" print("\n=== Example 1: List Task Lists ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with GoogletasksClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.list_task_lists_async() + with GoogletasksClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.list_task_lists() items = result.get("items", []) if result else [] print(f"Found {len(items)} task list(s).") @@ -57,15 +55,15 @@ async def example_1_list_task_lists(): print(f" - {task_list.get('title', 'N/A')} ({task_list.get('id', 'N/A')})") -async def example_2_create_task_list_and_task(): +def example_2_create_task_list_and_task(): """Example 2: Create a task list and task.""" print("\n=== Example 2: Create Task List and Task ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with GoogletasksClient(CONNECTION_RUNTIME_URL, credential) as client: + with GoogletasksClient(CONNECTION_RUNTIME_URL, credential) as client: try: - list_result = await client.create_task_list_async( + list_result = client.create_task_list( input=TaskListCreate(title="SDK Sample List"), ) task_list_id = list_result.get("id") if list_result else None @@ -74,7 +72,7 @@ async def example_2_create_task_list_and_task(): print("Task list creation returned no id.") return - task_result = await client.create_task_async( + task_result = client.create_task( input=TaskCreate( title="Follow up sample", notes="Created by azure-connectors sample.", @@ -98,7 +96,7 @@ def example_3_list_triggers(): print(f"{operation_id}: required parameters: {parameters}") -async def main(): +def main(): """Run all Google Tasks connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: GOOGLETASKS_CONNECTION_URL environment variable is not set.") @@ -107,12 +105,12 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_list_task_lists() - await example_2_create_task_list_and_task() + example_1_list_task_lists() + example_2_create_task_list_and_task() example_3_list_triggers() print("\n=== Google Tasks sample completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_impexium.py b/samples/sample_connector_usage/sample_connector_usage_impexium.py index e524b73..37f1442 100644 --- a/samples/sample_connector_usage/sample_connector_usage_impexium.py +++ b/samples/sample_connector_usage/sample_connector_usage_impexium.py @@ -1,9 +1,7 @@ -"""Impexium connector SDK sample.""" - -import asyncio +"""Impexium sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.impexium import ImpexiumClient @@ -12,20 +10,20 @@ CONNECTION_RUNTIME_URL = os.environ.get("IMPEXIUM_CONNECTION_URL", "") -async def main() -> None: +def main() -> None: """List countries from Impexium.""" if not CONNECTION_RUNTIME_URL: print("Set IMPEXIUM_CONNECTION_URL to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with ImpexiumClient(CONNECTION_RUNTIME_URL, credential) as client: - countries = await client.list_all_countries_async(page_number=1) + with ImpexiumClient(CONNECTION_RUNTIME_URL, credential) as client: + countries = client.list_all_countries(page_number=1) print(f"Countries: {countries}") except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_infusionsoft.py b/samples/sample_connector_usage/sample_connector_usage_infusionsoft.py index 38b4227..c5ec0bb 100644 --- a/samples/sample_connector_usage/sample_connector_usage_infusionsoft.py +++ b/samples/sample_connector_usage/sample_connector_usage_infusionsoft.py @@ -1,7 +1,7 @@ """ -Infusionsoft (Keap) Connector SDK Sample +Infusionsoft (Keap) sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Infusionsoft connector SDK. +This sample demonstrates how to use the Infusionsoft client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Infusionsoft connection @@ -17,11 +17,9 @@ python sample_connector_usage_infusionsoft.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.infusionsoft import CreateTaskRequest, InfusionsoftClient @@ -32,13 +30,13 @@ CONNECTION_RUNTIME_URL = os.environ.get("INFUSIONSOFT_CONNECTION_URL", "") -async def example_1_list_tasks() -> None: +def example_1_list_tasks() -> None: """Example 1: List tasks ordered by due date.""" print("\n=== Example 1: List Tasks ===") - async with DefaultAzureCredential() as credential: - async with InfusionsoftClient(CONNECTION_RUNTIME_URL, credential) as client: - response = await client.list_tasks_async() + with DefaultAzureCredential() as credential: + with InfusionsoftClient(CONNECTION_RUNTIME_URL, credential) as client: + response = client.list_tasks() tasks = response.get("tasks", []) if response else [] print(f"Found {len(tasks)} tasks") @@ -46,49 +44,49 @@ async def example_1_list_tasks() -> None: print(f" - {task.get('id')}: {task.get('title')}") -async def example_2_create_task() -> None: +def example_2_create_task() -> None: """Example 2: Create a task.""" print("\n=== Example 2: Create Task ===") - async with DefaultAzureCredential() as credential: - async with InfusionsoftClient(CONNECTION_RUNTIME_URL, credential) as client: + with DefaultAzureCredential() as credential: + with InfusionsoftClient(CONNECTION_RUNTIME_URL, credential) as client: request = CreateTaskRequest( title="SDK sample task", description="Created from the infusionsoft SDK sample.", priority=1, ) - created = await client.create_task_async(input=request) + created = client.create_task(input=request) print(f"Created task: {created.get('id') if created else 'n/a'}") -async def example_3_update_task() -> None: +def example_3_update_task() -> None: """Example 3: Update an existing task.""" print("\n=== Example 3: Update Task ===") - async with DefaultAzureCredential() as credential: - async with InfusionsoftClient(CONNECTION_RUNTIME_URL, credential) as client: + with DefaultAzureCredential() as credential: + with InfusionsoftClient(CONNECTION_RUNTIME_URL, credential) as client: request = CreateTaskRequest( title="Updated SDK sample task", description="Updated from the infusionsoft SDK sample.", ) - updated = await client.update_task_async(input=request, id=1) + updated = client.update_task(input=request, id=1) print(f"Updated task: {updated.get('id') if updated else 'n/a'}") -async def main() -> None: +def main() -> None: """Run Infusionsoft connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: INFUSIONSOFT_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Infusionsoft (Keap) Connector SDK - Sample Usage") + print("Infusionsoft (Keap) sample usage for the Azure Connectors Python SDK") print("=" * 50) try: - await example_1_list_tasks() + example_1_list_tasks() # Uncomment to create or update a task in your Infusionsoft instance. # await example_2_create_task() # await example_3_update_task() @@ -100,4 +98,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_insightly.py b/samples/sample_connector_usage/sample_connector_usage_insightly.py index 15aa4fd..0bf4414 100644 --- a/samples/sample_connector_usage/sample_connector_usage_insightly.py +++ b/samples/sample_connector_usage/sample_connector_usage_insightly.py @@ -1,7 +1,7 @@ """ -Insightly Connector SDK Sample +Insightly sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Insightly connector SDK. +This sample demonstrates how to use the Insightly client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Insightly connection @@ -17,11 +17,9 @@ python sample_connector_usage_insightly.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.insightly import InsightlyClient, TaskRequest @@ -32,13 +30,13 @@ CONNECTION_RUNTIME_URL = os.environ.get("INSIGHTLY_CONNECTION_URL", "") -async def example_1_list_tasks() -> None: +def example_1_list_tasks() -> None: """Example 1: List tasks.""" print("\n=== Example 1: List Tasks ===") - async with DefaultAzureCredential() as credential: - async with InsightlyClient(CONNECTION_RUNTIME_URL, credential) as client: - response = await client.list_tasks_async() + with DefaultAzureCredential() as credential: + with InsightlyClient(CONNECTION_RUNTIME_URL, credential) as client: + response = client.list_tasks() tasks = response.get("tasks", []) if response else [] print(f"Found {len(tasks)} tasks") @@ -46,13 +44,13 @@ async def example_1_list_tasks() -> None: print(f" - {task.get('TASK_ID')}: {task.get('TITLE')}") -async def example_2_list_contacts() -> None: +def example_2_list_contacts() -> None: """Example 2: List contacts.""" print("\n=== Example 2: List Contacts ===") - async with DefaultAzureCredential() as credential: - async with InsightlyClient(CONNECTION_RUNTIME_URL, credential) as client: - response = await client.list_contacts_async() + with DefaultAzureCredential() as credential: + with InsightlyClient(CONNECTION_RUNTIME_URL, credential) as client: + response = client.list_contacts() contacts = response.get("contacts", []) if response else [] print(f"Found {len(contacts)} contacts") @@ -62,35 +60,37 @@ async def example_2_list_contacts() -> None: print(f" - {contact.get('CONTACT_ID')}: {first} {last}".rstrip()) -async def example_3_add_task() -> None: +def example_3_add_task() -> None: """Example 3: Add a task.""" print("\n=== Example 3: Add Task ===") - async with DefaultAzureCredential() as credential: - async with InsightlyClient(CONNECTION_RUNTIME_URL, credential) as client: + with DefaultAzureCredential() as credential: + with InsightlyClient(CONNECTION_RUNTIME_URL, credential) as client: request = TaskRequest( t_i_t_l_e="SDK sample task", d_e_t_a_i_l_s="Created from insightly SDK sample.", s_t_a_t_u_s="NOT STARTED", + c_o_m_p_l_e_t_e_d=False, + p_u_b_l_i_c_l_y_v_i_s_i_b_l_e=False, ) - created = await client.add_task_async(input=request) + created = client.add_task(input=request) print(f"Created task: {created.get('TASK_ID') if created else 'n/a'}") -async def main() -> None: +def main() -> None: """Run Insightly connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: INSIGHTLY_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Insightly Connector SDK - Sample Usage") + print("Insightly sample usage for the Azure Connectors Python SDK") print("=" * 50) try: - await example_1_list_tasks() - await example_2_list_contacts() + example_1_list_tasks() + example_2_list_contacts() # Uncomment to create a task in your Insightly instance. # await example_3_add_task() @@ -101,4 +101,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_jedoxodatahub.py b/samples/sample_connector_usage/sample_connector_usage_jedoxodatahub.py index 8c82d18..4fbffd2 100644 --- a/samples/sample_connector_usage/sample_connector_usage_jedoxodatahub.py +++ b/samples/sample_connector_usage/sample_connector_usage_jedoxodatahub.py @@ -1,9 +1,7 @@ -"""Jedox OData Hub connector SDK sample.""" - -import asyncio +"""Jedox OData Hub sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.jedoxodatahub import JedoxodatahubClient @@ -12,23 +10,23 @@ CONNECTION_RUNTIME_URL = os.environ.get("JEDOXODATAHUB_CONNECTION_URL", "") -async def main() -> None: +def main() -> None: """List Jedox databases.""" if not CONNECTION_RUNTIME_URL: print("Set JEDOXODATAHUB_CONNECTION_URL to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with JedoxodatahubClient( + with JedoxodatahubClient( CONNECTION_RUNTIME_URL, credential, ) as client: - databases = await client.databases_async() + databases = client.list_databases() print(f"Databases: {databases}") except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_jira.py b/samples/sample_connector_usage/sample_connector_usage_jira.py index 48dafdd..88524d3 100644 --- a/samples/sample_connector_usage/sample_connector_usage_jira.py +++ b/samples/sample_connector_usage/sample_connector_usage_jira.py @@ -1,7 +1,7 @@ """ -Jira Connector SDK Sample +Jira sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Jira connector SDK. +This sample demonstrates how to use the Jira client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Jira connection @@ -17,11 +17,9 @@ python sample_connector_usage_jira.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.jira import JiraClient, CreateIssueInput @@ -32,13 +30,13 @@ CONNECTION_RUNTIME_URL = os.environ.get("JIRA_CONNECTION_URL", "") -async def example_1_list_resources() -> list[dict]: +def example_1_list_resources() -> list[dict]: """Example 1: List accessible Jira cloud resources.""" print("\n=== Example 1: List Resources ===") - async with DefaultAzureCredential() as credential: - async with JiraClient(CONNECTION_RUNTIME_URL, credential) as client: - resources_response = await client.list_resources_async() + with DefaultAzureCredential() as credential: + with JiraClient(CONNECTION_RUNTIME_URL, credential) as client: + resources_response = client.list_resources() resources = ( resources_response if isinstance(resources_response, list) @@ -52,15 +50,15 @@ async def example_1_list_resources() -> list[dict]: return resources -async def example_2_list_issues(cloud_id: str) -> None: +def example_2_list_issues(cloud_id: str) -> None: """Example 2: List issues in a Jira site.""" print("\n=== Example 2: List Issues ===") - async with DefaultAzureCredential() as credential: - async with JiraClient(CONNECTION_RUNTIME_URL, credential) as client: + with DefaultAzureCredential() as credential: + with JiraClient(CONNECTION_RUNTIME_URL, credential) as client: del cloud_id - issues_response = await client.list_issues_async() + issues_response = client.list_issues() issues = issues_response.get("issues", []) if issues_response else [] print(f"Found {len(issues)} issues") @@ -68,12 +66,12 @@ async def example_2_list_issues(cloud_id: str) -> None: print(f" - {issue.get('key')}: {issue.get('fields', {}).get('summary')}") -async def example_3_create_issue(cloud_id: str) -> None: +def example_3_create_issue(cloud_id: str) -> None: """Example 3: Create an issue (requires valid project + issue type).""" print("\n=== Example 3: Create Issue ===") - async with DefaultAzureCredential() as credential: - async with JiraClient(CONNECTION_RUNTIME_URL, credential) as client: + with DefaultAzureCredential() as credential: + with JiraClient(CONNECTION_RUNTIME_URL, credential) as client: del cloud_id request = CreateIssueInput( @@ -97,7 +95,7 @@ async def example_3_create_issue(cloud_id: str) -> None: } ) - created = await client.create_issue_async( + created = client.create_issue( input=request, project_key="PROJ", issue_type_ids="10001", @@ -105,23 +103,23 @@ async def example_3_create_issue(cloud_id: str) -> None: print(f"Created issue: {created.get('key') if created else 'n/a'}") -async def main() -> None: +def main() -> None: """Run Jira connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: JIRA_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Jira Connector SDK - Sample Usage") + print("Jira sample usage for the Azure Connectors Python SDK") print("=" * 50) try: - resources = await example_1_list_resources() + resources = example_1_list_resources() if resources: cloud_id = resources[0].get("id") if cloud_id: - await example_2_list_issues(cloud_id) + example_2_list_issues(cloud_id) # Uncomment after setting valid project/issuetype in example_3_create_issue. # await example_3_create_issue(cloud_id) else: @@ -136,4 +134,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_keyvault.py b/samples/sample_connector_usage/sample_connector_usage_keyvault.py index 4886dce..fb24b8b 100644 --- a/samples/sample_connector_usage/sample_connector_usage_keyvault.py +++ b/samples/sample_connector_usage/sample_connector_usage_keyvault.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure Key Vault Connector SDK Sample +Azure Key Vault sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure Key Vault connector SDK to +This sample demonstrates how to use the Azure Key Vault client from the Azure Connectors Python SDK to manage keys and secrets. Prerequisites: @@ -20,10 +20,8 @@ python sample_connector_usage_keyvault.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.keyvault import ( KeyvaultClient, @@ -43,15 +41,15 @@ SECRET_NAME = os.environ.get("KEYVAULT_SECRET_NAME", "my-secret") -async def example_1_list_keys(): +def example_1_list_keys(): """Example 1: List all keys in the vault.""" print("\n=== Example 1: List Keys ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: + with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.list_keys_async() + result = client.list_keys() if result and result.get("value"): keys = result["value"] @@ -67,15 +65,15 @@ async def example_1_list_keys(): print(f"Error: {ex}") -async def example_2_get_key_metadata(): +def example_2_get_key_metadata(): """Example 2: Get metadata for a specific key.""" print("\n=== Example 2: Get Key Metadata ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: + with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_key_metadata_async(key_name=KEY_NAME) + result = client.get_key_metadata(key_name=KEY_NAME) if result: print(f"Key Name: {result.get('name')}") @@ -94,13 +92,13 @@ async def example_2_get_key_metadata(): print(f"Error: {ex}") -async def example_3_encrypt_decrypt(): +def example_3_encrypt_decrypt(): """Example 3: Encrypt and decrypt data using a key.""" print("\n=== Example 3: Encrypt and Decrypt Data ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: + with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Encrypt data plaintext = "Hello, Azure Key Vault!" @@ -110,7 +108,7 @@ async def example_3_encrypt_decrypt(): algorithm="RSA-OAEP", raw_data=plaintext ) - encrypt_result = await client.encrypt_data_async( + encrypt_result = client.encrypt_data( input=encrypt_input, key_name=KEY_NAME ) @@ -124,7 +122,7 @@ async def example_3_encrypt_decrypt(): algorithm="RSA-OAEP", encrypted_data=encrypted ) - decrypt_result = await client.decrypt_data_async( + decrypt_result = client.decrypt_data( input=decrypt_input, key_name=KEY_NAME ) @@ -139,15 +137,15 @@ async def example_3_encrypt_decrypt(): print(f"Error: {ex}") -async def example_4_list_secrets(): +def example_4_list_secrets(): """Example 4: List all secrets in the vault.""" print("\n=== Example 4: List Secrets ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: + with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.list_secrets_async() + result = client.list_secrets() if result and result.get("value"): secrets = result["value"] @@ -163,15 +161,15 @@ async def example_4_list_secrets(): print(f"Error: {ex}") -async def example_5_get_secret(): +def example_5_get_secret(): """Example 5: Get a secret value.""" print("\n=== Example 5: Get Secret ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: + with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_secret_async(secret_name=SECRET_NAME) + result = client.get_secret(secret_name=SECRET_NAME) if result: print(f"Secret Name: {result.get('name')}") @@ -189,15 +187,15 @@ async def example_5_get_secret(): print(f"Error: {ex}") -async def example_6_get_secret_metadata(): +def example_6_get_secret_metadata(): """Example 6: Get secret metadata without the value.""" print("\n=== Example 6: Get Secret Metadata ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: + with KeyvaultClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_secret_metadata_async( + result = client.get_secret_metadata( secret_name=SECRET_NAME ) @@ -217,7 +215,7 @@ async def example_6_get_secret_metadata(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: KEYVAULT_CONNECTION_URL environment variable not set.") @@ -227,11 +225,11 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") # Run read-only examples by default - await example_1_list_keys() - await example_2_get_key_metadata() - await example_4_list_secrets() - await example_5_get_secret() - await example_6_get_secret_metadata() + example_1_list_keys() + example_2_get_key_metadata() + example_4_list_secrets() + example_5_get_secret() + example_6_get_secret_metadata() # Uncomment to run encryption/decryption example: # await example_3_encrypt_decrypt() @@ -240,4 +238,4 @@ async def main(): if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_kusto.py b/samples/sample_connector_usage/sample_connector_usage_kusto.py index 8c83ef4..d78e55e 100644 --- a/samples/sample_connector_usage/sample_connector_usage_kusto.py +++ b/samples/sample_connector_usage/sample_connector_usage_kusto.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Kusto (Azure Data Explorer) Connector SDK Sample +Kusto (Azure Data Explorer) sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Kusto connector SDK. +This sample demonstrates how to use the Kusto client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Kusto (Azure Data Explorer) cluster @@ -22,12 +22,10 @@ python sample_connector_usage_kusto.py """ - -import asyncio import os try: - from azure.identity.aio import DefaultAzureCredential + from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.kusto import ( KustoClient, @@ -66,13 +64,13 @@ ) -async def example_1_simple_kql_query(): +def example_1_simple_kql_query(): """Example 1: Run a simple KQL query.""" print("\n=== Example 1: Simple KQL Query ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: try: query = f"{KUSTO_TABLE} | take 5" @@ -82,7 +80,8 @@ async def example_1_simple_kql_query(): csl=query, ) - results = await client.list_kusto_results_async(input=query_request) + poller = client.begin_list_kusto_results(input=query_request) + results = poller.result() if results and 'value' in results: print(f"Query executed successfully. Found {len(results['value'])} rows:") @@ -97,13 +96,13 @@ async def example_1_simple_kql_query(): print(f"Error: {ex}") -async def example_2_aggregation_query(): +def example_2_aggregation_query(): """Example 2: Run a KQL query with aggregation.""" print("\n=== Example 2: Aggregation Query ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: try: query = f""" {KUSTO_TABLE} @@ -117,7 +116,8 @@ async def example_2_aggregation_query(): csl=query, ) - results = await client.list_kusto_results_async(input=query_request) + poller = client.begin_list_kusto_results(input=query_request) + results = poller.result() if results and 'value' in results: print("Top 5 states by event count:") @@ -134,13 +134,13 @@ async def example_2_aggregation_query(): print(f"Error: {ex}") -async def example_3_time_based_filtering(): +def example_3_time_based_filtering(): """Example 3: Query with time-based filtering.""" print("\n=== Example 3: Time-Based Filtering ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: try: query = f""" {KUSTO_TABLE} @@ -156,7 +156,8 @@ async def example_3_time_based_filtering(): csl=query, ) - results = await client.list_kusto_results_async(input=query_request) + poller = client.begin_list_kusto_results(input=query_request) + results = poller.result() if results and 'value' in results: print("Top 5 event types in the last year:") @@ -173,13 +174,13 @@ async def example_3_time_based_filtering(): print(f"Error: {ex}") -async def example_4_visualize_results(): +def example_4_visualize_results(): """Example 4: Query and visualize results as a chart.""" print("\n=== Example 4: Visualize Query Results ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: try: query = f""" {KUSTO_TABLE} @@ -194,9 +195,10 @@ async def example_4_visualize_results(): chart_type="Time Chart", ) - chart = await client.run_kusto_query_and_visualize_results_async( + poller = client.begin_run_kusto_query_and_visualize_results( input=visualize_request ) + chart = poller.result() if chart: print("Chart data generated successfully") @@ -215,13 +217,13 @@ async def example_4_visualize_results(): print(f"Error: {ex}") -async def example_5_control_command(): +def example_5_control_command(): """Example 5: Run a control command to show database schema.""" print("\n=== Example 5: Control Command (Show Tables) ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: try: command = ".show tables" @@ -231,9 +233,10 @@ async def example_5_control_command(): csl=command, ) - results = await client.list_kusto_show_command_results_async( + poller = client.begin_list_kusto_show_command_results( input=command_request ) + results = poller.result() if results and 'value' in results: print(f"Found {len(results['value'])} tables in database '{KUSTO_DATABASE}':") @@ -250,13 +253,13 @@ async def example_5_control_command(): print(f"Error: {ex}") -async def example_6_table_schema(): +def example_6_table_schema(): """Example 6: Get schema information for a specific table.""" print("\n=== Example 6: Show Table Schema ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: try: command = f".show table {KUSTO_TABLE} schema as json" @@ -266,9 +269,10 @@ async def example_6_table_schema(): csl=command, ) - results = await client.list_kusto_show_command_results_async( + poller = client.begin_list_kusto_show_command_results( input=command_request ) + results = poller.result() if results and 'value' in results and len(results['value']) > 0: print(f"Schema for table '{KUSTO_TABLE}':") @@ -292,13 +296,13 @@ async def example_6_table_schema(): print(f"Error: {ex}") -async def example_7_statistical_analysis(): +def example_7_statistical_analysis(): """Example 7: Statistical analysis with percentiles.""" print("\n=== Example 7: Statistical Analysis ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: try: query = f""" {KUSTO_TABLE} @@ -316,7 +320,8 @@ async def example_7_statistical_analysis(): csl=query, ) - results = await client.list_kusto_results_async(input=query_request) + poller = client.begin_list_kusto_results(input=query_request) + results = poller.result() if results and 'value' in results and len(results['value']) > 0: stats = results['value'][0] @@ -334,13 +339,13 @@ async def example_7_statistical_analysis(): print(f"Error: {ex}") -async def example_8_error_handling(): +def example_8_error_handling(): """Example 8: Demonstrate error handling with invalid query.""" print("\n=== Example 8: Error Handling ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: + with KustoClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Intentionally use an invalid table name query = "NonExistentTable | take 10" @@ -351,7 +356,8 @@ async def example_8_error_handling(): csl=query, ) - results = await client.list_kusto_results_async(input=query_request) + poller = client.begin_list_kusto_results(input=query_request) + results = poller.result() print(f"Unexpected success: {results}") except ConnectorException as ex: @@ -362,24 +368,24 @@ async def example_8_error_handling(): print(f" Message: {ex}") -async def main(): +def main(): """Run all examples.""" - print("Kusto (Azure Data Explorer) Connector SDK - Sample Usage") + print("Kusto (Azure Data Explorer) sample usage for the Azure Connectors Python SDK") print("=" * 60) print() - await example_1_simple_kql_query() - await example_2_aggregation_query() - await example_3_time_based_filtering() - await example_4_visualize_results() - await example_5_control_command() - await example_6_table_schema() - await example_7_statistical_analysis() - await example_8_error_handling() + example_1_simple_kql_query() + example_2_aggregation_query() + example_3_time_based_filtering() + example_4_visualize_results() + example_5_control_command() + example_6_table_schema() + example_7_statistical_analysis() + example_8_error_handling() print("\n" + "=" * 60) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_mailchimp.py b/samples/sample_connector_usage/sample_connector_usage_mailchimp.py index 0fa27e4..8e904f8 100644 --- a/samples/sample_connector_usage/sample_connector_usage_mailchimp.py +++ b/samples/sample_connector_usage/sample_connector_usage_mailchimp.py @@ -1,7 +1,7 @@ """ -Mailchimp Connector SDK Sample +Mailchimp sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Mailchimp connector SDK. +This sample demonstrates how to use the Mailchimp client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a Mailchimp connection @@ -17,14 +17,14 @@ python sample_connector_usage_mailchimp.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.mailchimp import ( + CampaignDefaults, + Contact, MailchimpClient, NewListRequest, NewMemberInListRequest, @@ -36,48 +36,64 @@ CONNECTION_RUNTIME_URL = os.environ.get("MAILCHIMP_CONNECTION_URL", "") -async def example_1_list_campaigns() -> None: +def example_1_list_campaigns() -> None: """Example 1: List campaigns in the account.""" print("\n=== Example 1: List Campaigns ===") - async with DefaultAzureCredential() as credential: - async with MailchimpClient(CONNECTION_RUNTIME_URL, credential) as client: - campaigns = await client.get_campaigns_async() + with DefaultAzureCredential() as credential: + with MailchimpClient(CONNECTION_RUNTIME_URL, credential) as client: + campaigns = client.list_campaigns() print(f"Campaigns: {campaigns}") -async def example_2_get_lists() -> None: +def example_2_get_lists() -> None: """Example 2: Get all audience lists.""" print("\n=== Example 2: Get Lists ===") - async with DefaultAzureCredential() as credential: - async with MailchimpClient(CONNECTION_RUNTIME_URL, credential) as client: - lists = await client.get_lists_async(count=10, offset=0) + with DefaultAzureCredential() as credential: + with MailchimpClient(CONNECTION_RUNTIME_URL, credential) as client: + lists = client.get_lists(count=10, offset=0) print(f"Lists: {lists}") -async def example_3_new_list() -> None: +def example_3_new_list() -> None: """Example 3: Create a new audience list.""" print("\n=== Example 3: New List ===") - async with DefaultAzureCredential() as credential: - async with MailchimpClient(CONNECTION_RUNTIME_URL, credential) as client: - new_list = await client.newlist_async( + with DefaultAzureCredential() as credential: + with MailchimpClient(CONNECTION_RUNTIME_URL, credential) as client: + new_list = client.newlist( input=NewListRequest( name="SDK sample list", permission_reminder="You signed up via the SDK sample.", + contact=Contact( + company="Contoso", + address1="1 Microsoft Way", + city="Redmond", + state="WA", + zip="98052", + country="US", + phone="425-555-0100", + ), + campaign_defaults=CampaignDefaults( + from_name="SDK Sample", + from_email="sample@example.com", + subject="Welcome", + language="en", + ), + email_type_option=True, ), ) print(f"Created list: {new_list}") -async def example_4_add_member() -> None: +def example_4_add_member() -> None: """Example 4: Add a member to an audience list.""" print("\n=== Example 4: Add Member ===") - async with DefaultAzureCredential() as credential: - async with MailchimpClient(CONNECTION_RUNTIME_URL, credential) as client: - member = await client.addmember_async( + with DefaultAzureCredential() as credential: + with MailchimpClient(CONNECTION_RUNTIME_URL, credential) as client: + member = client.addmember( input=NewMemberInListRequest( email_address="sample.user@example.com", status="subscribed", @@ -87,14 +103,14 @@ async def example_4_add_member() -> None: print(f"Added member: {member}") -async def main() -> None: +def main() -> None: """Run Mailchimp connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: MAILCHIMP_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Mailchimp Connector SDK - Sample Usage") + print("Mailchimp sample usage for the Azure Connectors Python SDK") print("=" * 50) try: @@ -112,4 +128,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_meetingroommap.py b/samples/sample_connector_usage/sample_connector_usage_meetingroommap.py index edc113d..1810f70 100644 --- a/samples/sample_connector_usage/sample_connector_usage_meetingroommap.py +++ b/samples/sample_connector_usage/sample_connector_usage_meetingroommap.py @@ -1,9 +1,7 @@ -"""Meeting Room Map connector SDK sample.""" - -import asyncio +"""Meeting Room Map sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.meetingroommap import MeetingroommapClient @@ -12,23 +10,23 @@ CONNECTION_RUNTIME_URL = os.environ.get("MEETINGROOMMAP_CONNECTION_URL", "") -async def main() -> None: +def main() -> None: """List Meeting Room Map location categories.""" if not CONNECTION_RUNTIME_URL: print("Set MEETINGROOMMAP_CONNECTION_URL to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with MeetingroommapClient( + with MeetingroommapClient( CONNECTION_RUNTIME_URL, credential, ) as client: - categories = await client.get_categories_async() + categories = client.list_categories() print(f"Categories: {categories}") except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_microsoftbookings.py b/samples/sample_connector_usage/sample_connector_usage_microsoftbookings.py index ac6fbc9..b7a0e0f 100644 --- a/samples/sample_connector_usage/sample_connector_usage_microsoftbookings.py +++ b/samples/sample_connector_usage/sample_connector_usage_microsoftbookings.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Microsoft Bookings Connector SDK Sample +Microsoft Bookings sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Microsoft Bookings connector SDK to +This sample demonstrates how to use the Microsoft Bookings client from the Azure Connectors Python SDK to manage booking businesses and appointment webhooks. Prerequisites: @@ -20,10 +20,8 @@ python sample_connector_usage_microsoftbookings.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.microsoftbookings import ( MicrosoftbookingsClient, @@ -52,15 +50,15 @@ ) -async def example_1_list_booking_businesses(): +def example_1_list_booking_businesses(): """Example 1: List booking businesses where user is an admin.""" print("\n=== Example 1: List Booking Businesses ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with MicrosoftbookingsClient(CONNECTION_RUNTIME_URL, credential) as client: + with MicrosoftbookingsClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.list_bookings_business_user_as_admin_async() + result = client.list_bookings_business_user_as_admin() if result and result.get("mailboxes"): mailboxes = result["mailboxes"] @@ -77,7 +75,7 @@ async def example_1_list_booking_businesses(): print(f"Error: {ex}") -async def example_2_build_create_webhook(): +def example_2_build_create_webhook(): """Example 2: Build an appointment-created webhook payload.""" print("\n=== Example 2: Build Create Appointment Webhook ===") @@ -88,7 +86,7 @@ async def example_2_build_create_webhook(): print(f"Create webhook payload: {webhook_input.webhook}") -async def example_3_build_update_webhook(): +def example_3_build_update_webhook(): """Example 3: Build an appointment-updated webhook payload.""" print("\n=== Example 3: Build Update Appointment Webhook ===") @@ -98,7 +96,7 @@ async def example_3_build_update_webhook(): print(f"Update webhook payload: {webhook_input.webhook}") -async def example_4_build_cancel_webhook(): +def example_4_build_cancel_webhook(): """Example 4: Build an appointment-cancelled webhook payload.""" print("\n=== Example 4: Build Cancel Appointment Webhook ===") @@ -108,7 +106,7 @@ async def example_4_build_cancel_webhook(): print(f"Cancel webhook payload: {webhook_input.webhook}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: MICROSOFTBOOKINGS_CONNECTION_URL environment variable not set.") @@ -118,16 +116,16 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") # Run read-only example by default - await example_1_list_booking_businesses() + example_1_list_booking_businesses() # The current generated action client exposes payload models but not the # webhook registration trigger operations. - await example_2_build_create_webhook() - await example_3_build_update_webhook() - await example_4_build_cancel_webhook() + example_2_build_create_webhook() + example_3_build_update_webhook() + example_4_build_cancel_webhook() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_microsoftforms.py b/samples/sample_connector_usage/sample_connector_usage_microsoftforms.py index 35f7191..52957a3 100644 --- a/samples/sample_connector_usage/sample_connector_usage_microsoftforms.py +++ b/samples/sample_connector_usage/sample_connector_usage_microsoftforms.py @@ -1,7 +1,7 @@ """ -Microsoft Forms Connector SDK Sample +Microsoft Forms sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Microsoft Forms connector SDK. +This sample demonstrates how to use the Microsoft Forms client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Microsoft Forms connection @@ -19,11 +19,9 @@ python sample_connector_usage_microsoftforms.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.microsoftforms import MicrosoftformsClient @@ -34,13 +32,13 @@ CONNECTION_RUNTIME_URL = os.environ.get("MICROSOFTFORMS_CONNECTION_URL", "") -async def example_1_list_forms() -> list[dict]: +def example_1_list_forms() -> list[dict]: """Example 1: List available forms.""" print("\n=== Example 1: List Forms ===") - async with DefaultAzureCredential() as credential: - async with MicrosoftformsClient(CONNECTION_RUNTIME_URL, credential) as client: - forms_response = await client.list_forms_async() + with DefaultAzureCredential() as credential: + with MicrosoftformsClient(CONNECTION_RUNTIME_URL, credential) as client: + forms_response = client.list_forms() forms = forms_response.get("value", []) if forms_response else [] print(f"Found {len(forms)} forms") @@ -50,13 +48,13 @@ async def example_1_list_forms() -> list[dict]: return forms -async def example_2_get_form_details(form_id: str) -> None: +def example_2_get_form_details(form_id: str) -> None: """Example 2: Get details for one form.""" print("\n=== Example 2: Get Form Details ===") - async with DefaultAzureCredential() as credential: - async with MicrosoftformsClient(CONNECTION_RUNTIME_URL, credential) as client: - details = await client.get_form_details_by_id_async(form_id=form_id) + with DefaultAzureCredential() as credential: + with MicrosoftformsClient(CONNECTION_RUNTIME_URL, credential) as client: + details = client.get_form_details_by_id(form_id=form_id) if not details: print("No details returned") @@ -68,34 +66,34 @@ async def example_2_get_form_details(form_id: str) -> None: print(f"Last Modified: {details.get('modifiedDate')}") -async def example_3_get_questions(form_id: str) -> None: +def example_3_get_questions(form_id: str) -> None: """Example 3: Get form questions.""" print("\n=== Example 3: Get Questions ===") - async with DefaultAzureCredential() as credential: - async with MicrosoftformsClient(CONNECTION_RUNTIME_URL, credential) as client: - await client.get_questions_async(form_id=form_id) + with DefaultAzureCredential() as credential: + with MicrosoftformsClient(CONNECTION_RUNTIME_URL, credential) as client: + client.get_questions(form_id=form_id) print("Question metadata request completed.") -async def main() -> None: +def main() -> None: """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: MICROSOFTFORMS_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Microsoft Forms Connector SDK - Sample Usage") + print("Microsoft Forms sample usage for the Azure Connectors Python SDK") print("=" * 50) try: - forms = await example_1_list_forms() + forms = example_1_list_forms() if forms: first_form_id = forms[0].get("id") if first_form_id: - await example_2_get_form_details(first_form_id) - await example_3_get_questions(first_form_id) + example_2_get_form_details(first_form_id) + example_3_get_questions(first_form_id) else: print("No form id found in first record; skipping detail examples.") else: @@ -108,4 +106,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_monday.py b/samples/sample_connector_usage/sample_connector_usage_monday.py index 7ffe7bd..7196928 100644 --- a/samples/sample_connector_usage/sample_connector_usage_monday.py +++ b/samples/sample_connector_usage/sample_connector_usage_monday.py @@ -1,7 +1,7 @@ """ -Monday.com Connector SDK Sample +Monday.com sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Monday.com connector SDK. +This sample demonstrates how to use the Monday.com client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a Monday.com connection @@ -17,11 +17,9 @@ python sample_connector_usage_monday.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.monday import ( @@ -38,13 +36,13 @@ CONNECTION_RUNTIME_URL = os.environ.get("MONDAY_CONNECTION_URL", "") -async def example_1_create_board() -> None: +def example_1_create_board() -> None: """Example 1: Create a board.""" print("\n=== Example 1: Create Board ===") - async with DefaultAzureCredential() as credential: - async with MondayClient(CONNECTION_RUNTIME_URL, credential) as client: - board = await client.create_board_async( + with DefaultAzureCredential() as credential: + with MondayClient(CONNECTION_RUNTIME_URL, credential) as client: + board = client.create_board( input=CreateBoardInput( workspace_id="123456", board_name="SDK sample board", @@ -54,13 +52,13 @@ async def example_1_create_board() -> None: print(f"Created board: {data}") -async def example_2_create_item() -> None: +def example_2_create_item() -> None: """Example 2: Create an item in a board and group.""" print("\n=== Example 2: Create Item ===") - async with DefaultAzureCredential() as credential: - async with MondayClient(CONNECTION_RUNTIME_URL, credential) as client: - item = await client.create_item_async( + with DefaultAzureCredential() as credential: + with MondayClient(CONNECTION_RUNTIME_URL, credential) as client: + item = client.create_item( input=CreateItemInput( workspace_id="123456", board_id="789012", @@ -72,13 +70,13 @@ async def example_2_create_item() -> None: print(f"Created item: {data}") -async def example_3_update_item_column() -> None: +def example_3_update_item_column() -> None: """Example 3: Update a column value on an item.""" print("\n=== Example 3: Update Item Column ===") - async with DefaultAzureCredential() as credential: - async with MondayClient(CONNECTION_RUNTIME_URL, credential) as client: - updated = await client.update_item_column_async( + with DefaultAzureCredential() as credential: + with MondayClient(CONNECTION_RUNTIME_URL, credential) as client: + updated = client.update_item_column( input=UpdateItemColumnInput( workspace_id="123456", board_id="789012", @@ -93,24 +91,24 @@ async def example_3_update_item_column() -> None: print(f"Updated item column: {data}") -async def example_4_list_workspaces() -> None: +def example_4_list_workspaces() -> None: """Example 4: List the available workspaces.""" print("\n=== Example 4: List Workspaces ===") - async with DefaultAzureCredential() as credential: - async with MondayClient(CONNECTION_RUNTIME_URL, credential) as client: - workspaces = await client.get_workspaces_async() + with DefaultAzureCredential() as credential: + with MondayClient(CONNECTION_RUNTIME_URL, credential) as client: + workspaces = client.get_workspaces() print(f"Workspaces: {workspaces}") -async def main() -> None: +def main() -> None: """Run Monday.com connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: MONDAY_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Monday.com Connector SDK - Sample Usage") + print("Monday.com sample usage for the Azure Connectors Python SDK") print("=" * 50) try: @@ -128,4 +126,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_mq.py b/samples/sample_connector_usage/sample_connector_usage_mq.py index c444da1..f46bc81 100644 --- a/samples/sample_connector_usage/sample_connector_usage_mq.py +++ b/samples/sample_connector_usage/sample_connector_usage_mq.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -IBM MQ Connector SDK Sample +IBM MQ sample for the Azure Connectors Python SDK -This sample demonstrates how to use the IBM MQ connector SDK. +This sample demonstrates how to use the IBM MQ client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with IBM MQ connection @@ -22,10 +22,8 @@ python sample_connector_usage_mq.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.mq import ( MqClient, @@ -45,7 +43,7 @@ DEFAULT_QUEUE = os.environ.get("TEST_MQ_QUEUE", None) -async def example_1_send_message(): +def example_1_send_message(): """Example 1: Send a message to an IBM MQ queue.""" print("\n=== Example 1: Send Message ===") @@ -54,16 +52,16 @@ async def example_1_send_message(): "Hello from Azure Connectors SDK for Python!" ) - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with MqClient(CONNECTION_RUNTIME_URL, credential) as client: + with MqClient(CONNECTION_RUNTIME_URL, credential) as client: try: options = SendValidDataOptions( message=message_content, queue=DEFAULT_QUEUE, ) - result = await client.send_async(input=options) + result = client.send(input=options) if result: print("Message sent successfully:") @@ -78,20 +76,20 @@ async def example_1_send_message(): print(f"Error: {ex}") -async def example_2_browse_message(): +def example_2_browse_message(): """Example 2: Browse (peek) a single message without removing it.""" print("\n=== Example 2: Browse Message ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with MqClient(CONNECTION_RUNTIME_URL, credential) as client: + with MqClient(CONNECTION_RUNTIME_URL, credential) as client: try: options = SingleGetValidOptions( queue=DEFAULT_QUEUE, include_info="true", ) - result = await client.read_async(input=options) + result = client.read(input=options) if result: print("Browsed message:") @@ -109,15 +107,15 @@ async def example_2_browse_message(): print(f"Error: {ex}") -async def example_3_browse_messages_batch(): +def example_3_browse_messages_batch(): """Example 3: Browse multiple messages without removing them.""" print("\n=== Example 3: Browse Messages (Batch) ===") batch_size = int(os.environ.get("TEST_MQ_BATCH_SIZE", "10")) - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with MqClient(CONNECTION_RUNTIME_URL, credential) as client: + with MqClient(CONNECTION_RUNTIME_URL, credential) as client: try: options = MultipleGetValidOptions( queue=DEFAULT_QUEUE, @@ -125,11 +123,12 @@ async def example_3_browse_messages_batch(): include_info="true", ) - result = await client.read_all_async(input=options) + result = client.read_all(input=options) + messages = result.get("value", []) if result else [] - if result and isinstance(result, list): - print(f"Browsed {len(result)} messages:") - for i, msg in enumerate(result[:5]): # Show first 5 + if messages: + print(f"Browsed {len(messages)} messages:") + for i, msg in enumerate(messages[:5]): # Show first 5 msg_id = msg.get("messageId", "N/A") data = msg.get("messageData", "") preview = data[:50] if data else "(empty)" @@ -143,20 +142,20 @@ async def example_3_browse_messages_batch(): print(f"Error: {ex}") -async def example_4_receive_message(): +def example_4_receive_message(): """Example 4: Receive (destructive get) a single message from the queue.""" print("\n=== Example 4: Receive Message (Destructive) ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with MqClient(CONNECTION_RUNTIME_URL, credential) as client: + with MqClient(CONNECTION_RUNTIME_URL, credential) as client: try: options = SingleGetValidOptions( queue=DEFAULT_QUEUE, include_info="true", ) - result = await client.receive_async(input=options) + result = client.receive(input=options) if result: print("Received message (removed from queue):") @@ -174,19 +173,19 @@ async def example_4_receive_message(): print(f"Error: {ex}") -async def example_5_delete_message(): +def example_5_delete_message(): """Example 5: Delete a single message from the queue.""" print("\n=== Example 5: Delete Message ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with MqClient(CONNECTION_RUNTIME_URL, credential) as client: + with MqClient(CONNECTION_RUNTIME_URL, credential) as client: try: options = SingleGetValidOptions( queue=DEFAULT_QUEUE, ) - result = await client.delete_async(input=options) + result = client.delete(input=options) if result: print("Deleted message:") @@ -201,9 +200,9 @@ async def example_5_delete_message(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" - print("IBM MQ Connector SDK - Sample Usage") + print("IBM MQ sample usage for the Azure Connectors Python SDK") print("=" * 60) if not CONNECTION_RUNTIME_URL: @@ -212,15 +211,15 @@ async def main(): print("Format: https://[region].azure-apihub.net/apim/mq/[connection-id]") return - await example_1_send_message() - await example_2_browse_message() - await example_3_browse_messages_batch() - await example_4_receive_message() - await example_5_delete_message() + example_1_send_message() + example_2_browse_message() + example_3_browse_messages_batch() + example_4_receive_message() + example_5_delete_message() print("\n" + "=" * 60) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_msgraphgroupsanduser.py b/samples/sample_connector_usage/sample_connector_usage_msgraphgroupsanduser.py index e987426..23aa2d2 100644 --- a/samples/sample_connector_usage/sample_connector_usage_msgraphgroupsanduser.py +++ b/samples/sample_connector_usage/sample_connector_usage_msgraphgroupsanduser.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -MS Graph Groups & Users Connector SDK Sample +MS Graph Groups & Users sample for the Azure Connectors Python SDK -This sample demonstrates how to use the MS Graph Groups & Users connector SDK. +This sample demonstrates how to use the MS Graph Groups & Users client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with MS Graph Groups & Users connection @@ -21,10 +21,8 @@ python sample_connector_usage_msgraphgroupsanduser.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.msgraphgroupsanduser import MsgraphgroupsanduserClient @@ -36,15 +34,15 @@ ) -async def example_1_list_users(): +def example_1_list_users(): """Example 1: List users in the tenant.""" print("\n=== Example 1: List Users ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: + with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: try: - users = await client.list_users_async() + users = client.list_users() if users and "value" in users: print(f"Found {len(users['value'])} users:") @@ -61,17 +59,17 @@ async def example_1_list_users(): print(f"Error: {ex}") -async def example_2_list_groups(): +def example_2_list_groups(): """Example 2: Search for groups by display name.""" print("\n=== Example 2: List Groups (Search) ===") search_term = os.environ.get("TEST_GROUP_SEARCH", None) - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: + with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: try: - groups = await client.list_groups_by_display_name_search_async( + groups = client.list_groups_by_display_name_search( search=search_term, ) @@ -95,7 +93,7 @@ async def example_2_list_groups(): print(f"Error: {ex}") -async def example_3_get_group_properties(): +def example_3_get_group_properties(): """Example 3: Get properties of a specific group.""" print("\n=== Example 3: Get Group Properties ===") @@ -105,11 +103,11 @@ async def example_3_get_group_properties(): print("You can get a group ID from Example 2 output.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: + with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: try: - group = await client.get_group_properties_async(group_id=group_id) + group = client.get_group_properties(group_id=group_id) if group: print(f"Group properties for '{group.get('displayName', 'Unknown')}':") @@ -128,7 +126,7 @@ async def example_3_get_group_properties(): print(f"Error: {ex}") -async def example_4_list_group_members(): +def example_4_list_group_members(): """Example 4: List direct members of a group.""" print("\n=== Example 4: List Group Members ===") @@ -138,11 +136,11 @@ async def example_4_list_group_members(): print("You can get a group ID from Example 2 output.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: + with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: try: - members = await client.list_direct_group_members_async( + members = client.list_direct_group_members( group_id=group_id, ) @@ -161,15 +159,15 @@ async def example_4_list_group_members(): print(f"Error: {ex}") -async def example_5_list_subscribed_skus(): +def example_5_list_subscribed_skus(): """Example 5: List organization's subscribed license SKUs.""" print("\n=== Example 5: List Subscribed SKUs ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: + with MsgraphgroupsanduserClient(CONNECTION_RUNTIME_URL, credential) as client: try: - skus = await client.list_subscribed_skus_async() + skus = client.list_subscribed_skus() if skus and "value" in skus: print(f"Found {len(skus['value'])} subscribed SKUs:") @@ -186,9 +184,9 @@ async def example_5_list_subscribed_skus(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" - print("MS Graph Groups & Users Connector SDK - Sample Usage") + print("MS Graph Groups & Users sample usage for the Azure Connectors Python SDK") print("=" * 60) if not CONNECTION_RUNTIME_URL: @@ -197,15 +195,15 @@ async def main(): print("Format: https://[region].azure-apihub.net/apim/msgraphgroupsanduser/[connection-id]") return - await example_1_list_users() - await example_2_list_groups() - await example_3_get_group_properties() - await example_4_list_group_members() - await example_5_list_subscribed_skus() + example_1_list_users() + example_2_list_groups() + example_3_get_group_properties() + example_4_list_group_members() + example_5_list_subscribed_skus() print("\n" + "=" * 60) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_office365.py b/samples/sample_connector_usage/sample_connector_usage_office365.py index d1da234..d3617ca 100644 --- a/samples/sample_connector_usage/sample_connector_usage_office365.py +++ b/samples/sample_connector_usage/sample_connector_usage_office365.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Office365 Connector SDK Sample +Office365 sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Office365 connector SDK. +This sample demonstrates how to use the Office365 client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Office365 connection @@ -21,10 +21,8 @@ python sample_connector_usage_office365.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.office365 import ( DraftEmailInput, @@ -40,15 +38,15 @@ ) -async def example_1_get_outlook_categories(): +def example_1_get_outlook_categories(): """Example 1: Get Outlook category names.""" print("\n=== Example 1: Get Outlook Category Names ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: + with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: try: - categories = await client.get_outlook_category_names_async() + categories = client.list_outlook_category_names() if categories and 'value' in categories: print(f"Found {len(categories['value'])} Outlook categories:") @@ -65,26 +63,26 @@ async def example_1_get_outlook_categories(): print(f"Error: {ex}") -async def example_2_send_email(): +def example_2_send_email(): """Example 2: Send an HTML email.""" print("\n=== Example 2: Send Email ===") to_address = os.environ.get("TEST_EMAIL_TO", "@microsoft.com") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: + with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: try: email = SendEmailInput( to=to_address, - subject="Test Email from Office365 Connector SDK", + subject="Test Email from the Azure Connectors Python SDK", body=( "

This is a test email sent from the " - "Python Office365 Connector SDK.

" + "Azure Connectors Python SDK.

" ), ) - await client.send_email_async(email) + client.send_email(email) print(f"Email sent successfully to {to_address}") print("Note: Set TEST_EMAIL_TO environment variable to send to a real address") @@ -94,15 +92,15 @@ async def example_2_send_email(): print(f"Error: {ex}") -async def example_3_get_emails(): +def example_3_get_emails(): """Example 3: Get emails from inbox.""" print("\n=== Example 3: Get Emails from Inbox ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: + with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: try: - emails = await client.get_emails_async() + emails = client.list_emails() if emails and 'value' in emails: print(f"Found {len(emails['value'])} emails:") @@ -122,15 +120,15 @@ async def example_3_get_emails(): print(f"Error: {ex}") -async def example_4_draft_and_send_email(): +def example_4_draft_and_send_email(): """Example 4: Draft an email and then send it.""" print("\n=== Example 4: Draft and Send Email ===") to_address = os.environ.get("TEST_EMAIL_TO", "@microsoft.com") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: + with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: try: draft = DraftEmailInput( to=to_address, @@ -138,14 +136,14 @@ async def example_4_draft_and_send_email(): body="

This email was created as a draft first.

", ) - draft_response = await client.draft_email_async(draft) + draft_response = client.draft_email(draft) print("Draft created successfully") if draft_response and 'Id' in draft_response: message_id = draft_response['Id'] print(f"Draft message ID: {message_id}") - await client.send_draft_email_async(message_id=message_id) + client.send_draft_email(message_id=message_id) print(f"Draft email sent successfully to {to_address}") else: print("Draft created but no ID returned.") @@ -156,17 +154,17 @@ async def example_4_draft_and_send_email(): print(f"Error: {ex}") -async def example_5_error_handling(): +def example_5_error_handling(): """Example 5: Demonstrate error handling.""" print("\n=== Example 5: Error Handling ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: + with Office365Client(CONNECTION_RUNTIME_URL, credential) as client: try: # Attempt to get an email with an invalid ID invalid_message_id = "invalid-message-id-12345" - email = await client.get_email_async(message_id=invalid_message_id) + email = client.get_email(message_id=invalid_message_id) print(f"Unexpected success: {email}") except ConnectorException as ex: @@ -177,21 +175,21 @@ async def example_5_error_handling(): print(f" Message: {ex}") -async def main(): +def main(): """Run all examples.""" - print("Office365 Connector SDK - Sample Usage") + print("Office365 sample usage for the Azure Connectors Python SDK") print("=" * 50) print() - await example_1_get_outlook_categories() - await example_2_send_email() - await example_3_get_emails() - await example_4_draft_and_send_email() - await example_5_error_handling() + example_1_get_outlook_categories() + example_2_send_email() + example_3_get_emails() + example_4_draft_and_send_email() + example_5_error_handling() print("\n" + "=" * 50) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_office365groups.py b/samples/sample_connector_usage/sample_connector_usage_office365groups.py index d504ec3..df6dd88 100644 --- a/samples/sample_connector_usage/sample_connector_usage_office365groups.py +++ b/samples/sample_connector_usage/sample_connector_usage_office365groups.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Office 365 Groups Connector SDK Sample +Office 365 Groups sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Office 365 Groups connector SDK +This sample demonstrates how to use the Office 365 Groups client from the Azure Connectors Python SDK for group management and calendar operations. Prerequisites: @@ -20,10 +20,8 @@ python sample_connector_usage_office365groups.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.office365groups import ( Office365groupsClient, @@ -38,15 +36,15 @@ ) -async def example_1_list_groups(): +def example_1_list_groups(): """Example 1: List all groups in the organization.""" print("\n=== Example 1: List Groups ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: + with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: try: - groups = [item async for item in client.list_groups_async(top=10)] + groups = [item for item in client.list_groups(top=10)] if groups: print(f"Found {len(groups)} groups:") @@ -61,19 +59,19 @@ async def example_1_list_groups(): print(f"Error: {ex}") -async def example_2_list_group_members(): +def example_2_list_group_members(): """Example 2: List members of a specific group.""" print("\n=== Example 2: List Group Members ===") # Replace with your actual group ID GROUP_ID = "your-group-id-here" - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: + with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: try: members = [ - item async for item in client.list_group_members_async( + item for item in client.list_group_members( group_id=GROUP_ID ) ] @@ -91,15 +89,15 @@ async def example_2_list_group_members(): print(f"Error: {ex}") -async def example_3_list_owned_groups(): +def example_3_list_owned_groups(): """Example 3: List groups that I own and belong to.""" print("\n=== Example 3: List My Groups ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: + with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.list_owned_groups_async() + result = client.list_owned_groups() if result and "value" in result: groups = result["value"] @@ -115,16 +113,16 @@ async def example_3_list_owned_groups(): print(f"Error: {ex}") -async def example_4_create_group_event(): +def example_4_create_group_event(): """Example 4: Create a calendar event in a group.""" print("\n=== Example 4: Create Group Event ===") # Replace with your actual group ID GROUP_ID = "your-group-id-here" - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: + with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: try: event_input = UpdateCalendarEventHTMLRequest( subject="Team Standup", @@ -146,7 +144,7 @@ async def example_4_create_group_event(): } ) - result = await client.create_calendar_event_async( + result = client.create_calendar_event( input=event_input, group_id=GROUP_ID ) @@ -164,7 +162,7 @@ async def example_4_create_group_event(): print(f"Error: {ex}") -async def example_5_add_member_to_group(): +def example_5_add_member_to_group(): """Example 5: Add a member to a group.""" print("\n=== Example 5: Add Member to Group ===") @@ -172,11 +170,11 @@ async def example_5_add_member_to_group(): GROUP_ID = "your-group-id-here" USER_UPN = "user@contoso.com" - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: + with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: try: - await client.add_member_to_group_async( + client.add_member_to_group( group_id=GROUP_ID, user_upn=USER_UPN ) @@ -189,16 +187,16 @@ async def example_5_add_member_to_group(): print(f"Error: {ex}") -async def example_6_list_deleted_groups(): +def example_6_list_deleted_groups(): """Example 6: List deleted groups that can be restored.""" print("\n=== Example 6: List Deleted Groups ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: + with Office365groupsClient(CONNECTION_RUNTIME_URL, credential) as client: try: groups = [ - item async for item in client.list_deleted_groups_async() + item for item in client.list_deleted_groups() ] if groups: @@ -214,7 +212,7 @@ async def example_6_list_deleted_groups(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: OFFICE365GROUPS_CONNECTION_URL environment variable not set.") @@ -223,9 +221,9 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_list_groups() - await example_3_list_owned_groups() - await example_6_list_deleted_groups() + example_1_list_groups() + example_3_list_owned_groups() + example_6_list_deleted_groups() # The following examples require valid IDs: # await example_2_list_group_members() @@ -236,4 +234,4 @@ async def main(): if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_office365groupsmail.py b/samples/sample_connector_usage/sample_connector_usage_office365groupsmail.py index 8ecced1..5ddbb43 100644 --- a/samples/sample_connector_usage/sample_connector_usage_office365groupsmail.py +++ b/samples/sample_connector_usage/sample_connector_usage_office365groupsmail.py @@ -1,16 +1,14 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """Sample usage for the Office 365 Groups Mail connector client.""" - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors.office365groupsmail import Office365groupsmailClient -async def main() -> None: +def main() -> None: """Run a simple Office 365 Groups Mail sample flow.""" connection_url = os.getenv("OFFICE365GROUPSMAIL_CONNECTION_URL") if not connection_url: @@ -20,21 +18,21 @@ async def main() -> None: if not group_id: raise ValueError("Set OFFICE365GROUPSMAIL_GROUP_ID environment variable") - async with DefaultAzureCredential() as credential: - async with Office365groupsmailClient(connection_url, credential) as client: + with DefaultAzureCredential() as credential: + with Office365groupsmailClient(connection_url, credential) as client: conversations = [ conversation - async for conversation in client.list_conversations_async( + for conversation in client.list_conversations( group_id=group_id ) ] conversation_count = len(conversations) print(f"Found {conversation_count} conversation(s) in group '{group_id}'.") - groups = await client.list_groups_async() + groups = client.list_groups() group_count = len((groups or {}).get("value", [])) print(f"Current user is in {group_count} Office 365 group(s).") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_office365users.py b/samples/sample_connector_usage/sample_connector_usage_office365users.py index 064b733..f4e4c71 100644 --- a/samples/sample_connector_usage/sample_connector_usage_office365users.py +++ b/samples/sample_connector_usage/sample_connector_usage_office365users.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Office 365 Users Connector SDK Sample +Office 365 Users sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Office 365 Users connector SDK. +This sample demonstrates how to use the Office 365 Users client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Office 365 Users connection @@ -21,10 +21,8 @@ python sample_connector_usage_office365users.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.office365users import Office365usersClient @@ -36,15 +34,15 @@ ) -async def example_1_get_my_profile(): +def example_1_get_my_profile(): """Example 1: Get the current user's profile.""" print("\n=== Example 1: Get My Profile ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: + with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: try: - profile = await client.my_profile_async() + profile = client.my_profile() if profile: print("My Profile:") @@ -62,7 +60,7 @@ async def example_1_get_my_profile(): print(f"Error: {ex}") -async def example_2_get_user_profile(): +def example_2_get_user_profile(): """Example 2: Get a specific user's profile.""" print("\n=== Example 2: Get User Profile ===") @@ -72,11 +70,11 @@ async def example_2_get_user_profile(): print("Example: $env:TEST_USER_ID = 'john.doe@contoso.com'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: + with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: try: - profile = await client.user_profile_async(id=user_id) + profile = client.user_profile(id=user_id) if profile: print(f"User Profile for '{user_id}':") @@ -94,7 +92,7 @@ async def example_2_get_user_profile(): print(f"Error: {ex}") -async def example_3_get_manager(): +def example_3_get_manager(): """Example 3: Get a user's manager.""" print("\n=== Example 3: Get Manager ===") @@ -104,11 +102,11 @@ async def example_3_get_manager(): print("Example: $env:TEST_USER_ID = 'john.doe@contoso.com'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: + with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: try: - manager = await client.manager_async(id=user_id) + manager = client.manager(id=user_id) if manager: print(f"Manager for '{user_id}':") @@ -124,7 +122,7 @@ async def example_3_get_manager(): print(f"Error: {ex}") -async def example_4_get_direct_reports(): +def example_4_get_direct_reports(): """Example 4: Get a user's direct reports.""" print("\n=== Example 4: Get Direct Reports ===") @@ -134,11 +132,11 @@ async def example_4_get_direct_reports(): print("Example: $env:TEST_USER_ID = 'john.doe@contoso.com'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: + with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: try: - reports = await client.direct_reports_async(id=user_id) + reports = client.list_direct_reports(id=user_id) if reports and "value" in reports: print(f"Direct reports for '{user_id}':") @@ -156,7 +154,7 @@ async def example_4_get_direct_reports(): print(f"Error: {ex}") -async def example_5_search_users(): +def example_5_search_users(): """Example 5: Search for users.""" print("\n=== Example 5: Search Users ===") @@ -166,11 +164,11 @@ async def example_5_search_users(): print("Example: $env:TEST_SEARCH_TERM = 'John'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: + with Office365usersClient(CONNECTION_RUNTIME_URL, credential) as client: try: - results = [item async for item in client.search_user_async( + results = [item for item in client.list_search_user( search_term=search_term, top=10, )] @@ -191,9 +189,9 @@ async def example_5_search_users(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" - print("Office 365 Users Connector SDK - Sample Usage") + print("Office 365 Users sample usage for the Azure Connectors Python SDK") print("=" * 60) if not CONNECTION_RUNTIME_URL: @@ -202,15 +200,15 @@ async def main(): print("Format: https://[region].azure-apihub.net/apim/office365users/[connection-id]") return - await example_1_get_my_profile() - await example_2_get_user_profile() - await example_3_get_manager() - await example_4_get_direct_reports() - await example_5_search_users() + example_1_get_my_profile() + example_2_get_user_profile() + example_3_get_manager() + example_4_get_direct_reports() + example_5_search_users() print("\n" + "=" * 60) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_onedrive.py b/samples/sample_connector_usage/sample_connector_usage_onedrive.py index 68cc283..f3dfafa 100644 --- a/samples/sample_connector_usage/sample_connector_usage_onedrive.py +++ b/samples/sample_connector_usage/sample_connector_usage_onedrive.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -OneDrive Connector SDK Sample +OneDrive sample for the Azure Connectors Python SDK -This sample demonstrates how to use the OneDrive connector SDK. +This sample demonstrates how to use the OneDrive client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with OneDrive connection @@ -19,10 +19,8 @@ python sample_connector_usage_onedrive.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.onedrive import OnedriveClient @@ -34,14 +32,14 @@ ) -async def example_1_list_root_folder(): +def example_1_list_root_folder(): """Example 1: List files in root folder.""" print("\n=== Example 1: List Root Folder ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.list_root_folder_async() + with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.list_root_folder() if result and "value" in result: print(f"Found {len(result['value'])} items in root folder:") @@ -52,7 +50,7 @@ async def example_1_list_root_folder(): print("No items found in root folder.") -async def example_2_get_file_metadata(): +def example_2_get_file_metadata(): """Example 2: Get file metadata by path.""" print("\n=== Example 2: Get File Metadata ===") @@ -62,11 +60,11 @@ async def example_2_get_file_metadata(): print("Example: $env:TEST_FILE_PATH = '/Documents/report.docx'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: try: - metadata = await client.get_file_metadata_by_path_async(path=file_path) + metadata = client.get_file_metadata_by_path(path=file_path) if metadata: print(f"File Metadata for '{file_path}':") @@ -81,7 +79,7 @@ async def example_2_get_file_metadata(): print(f"Error getting file metadata: {e}") -async def example_3_download_file(): +def example_3_download_file(): """Example 3: Download file content.""" print("\n=== Example 3: Download File Content ===") @@ -90,11 +88,11 @@ async def example_3_download_file(): print("Set TEST_FILE_PATH environment variable to a file path.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: try: - content = await client.get_file_content_by_path_async(path=file_path) + content = client.get_file_content_by_path(path=file_path) if content: print(f"Downloaded {len(content)} bytes") @@ -110,22 +108,22 @@ async def example_3_download_file(): print(f"Error downloading file: {e}") -async def example_4_list_folder(): +def example_4_list_folder(): """Example 4: List files in a specific folder.""" print("\n=== Example 4: List Folder Contents ===") folder_id = os.environ.get("TEST_FOLDER_ID", "") if not folder_id: print("Set TEST_FOLDER_ID environment variable to a folder ID.") - print("You can get folder IDs from list_root_folder_async results.") + print("You can get folder IDs from list_root_folder results.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: try: entries = [ - item async for item in client.list_folder_async(id=folder_id) + item for item in client.list_folder(id=folder_id) ] if entries: @@ -140,7 +138,7 @@ async def example_4_list_folder(): print(f"Error listing folder: {e}") -async def example_5_search_files(): +def example_5_search_files(): """Example 5: Search for files in a folder.""" print("\n=== Example 5: Search Files ===") @@ -151,11 +149,11 @@ async def example_5_search_files(): print("Set TEST_FOLDER_ID environment variable to search in a folder.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.find_files_async( + result = client.list_find_files( id=folder_id, query=search_query, find_mode="search" @@ -171,7 +169,7 @@ async def example_5_search_files(): print(f"Error searching files: {e}") -async def example_6_create_share_link(): +def example_6_create_share_link(): """Example 6: Create a share link for a file.""" print("\n=== Example 6: Create Share Link ===") @@ -180,11 +178,11 @@ async def example_6_create_share_link(): print("Set TEST_FILE_ID environment variable to create a share link.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.create_share_link_async( + result = client.create_share_link( id=file_id, type_="view" # "view" or "edit" ) @@ -198,7 +196,7 @@ async def example_6_create_share_link(): print(f"Error creating share link: {e}") -async def example_7_file_tags(): +def example_7_file_tags(): """Example 7: Manage file tags.""" print("\n=== Example 7: Manage File Tags ===") @@ -207,12 +205,12 @@ async def example_7_file_tags(): print("Set TEST_FILE_ID environment variable to manage tags.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Get existing tags - tags_result = await client.get_file_tags_async(id=file_id) + tags_result = client.list_file_tags(id=file_id) if tags_result and "tags" in tags_result: print(f"Current tags: {', '.join(tags_result['tags'])}") @@ -221,17 +219,17 @@ async def example_7_file_tags(): # Add a new tag print("Adding tag 'sdk-sample'...") - await client.add_file_tag_async(id=file_id, tag="sdk-sample") + client.add_file_tag(id=file_id, tag="sdk-sample") # Get updated tags - tags_result = await client.get_file_tags_async(id=file_id) + tags_result = client.list_file_tags(id=file_id) if tags_result and "tags" in tags_result: print(f"Updated tags: {', '.join(tags_result['tags'])}") except ConnectorException as e: print(f"Error managing tags: {e}") -async def example_8_copy_file(): +def example_8_copy_file(): """Example 8: Copy a file within OneDrive.""" print("\n=== Example 8: Copy File ===") @@ -242,11 +240,11 @@ async def example_8_copy_file(): print("Set TEST_FILE_ID environment variable to copy a file.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + with OnedriveClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.copy_drive_file_async( + result = client.copy_drive_file( id=file_id, destination=dest_folder, overwrite=False @@ -262,7 +260,7 @@ async def example_8_copy_file(): print(f"Error copying file: {e}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("ERROR: ONEDRIVE_CONNECTION_URL environment variable not set.") @@ -275,19 +273,19 @@ async def main(): print(f"$env:ONEDRIVE_CONNECTION_URL = '{url_example}'") return - print("OneDrive Connector SDK Sample") + print("OneDrive sample for the Azure Connectors Python SDK") print("=" * 50) print(f"Connection URL: {CONNECTION_RUNTIME_URL[:50]}...") try: - await example_1_list_root_folder() - await example_2_get_file_metadata() - await example_3_download_file() - await example_4_list_folder() - await example_5_search_files() - await example_6_create_share_link() - await example_7_file_tags() - await example_8_copy_file() + example_1_list_root_folder() + example_2_get_file_metadata() + example_3_download_file() + example_4_list_folder() + example_5_search_files() + example_6_create_share_link() + example_7_file_tags() + example_8_copy_file() except Exception as e: print(f"\nUnexpected error: {e}") raise @@ -297,4 +295,4 @@ async def main(): if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_onedriveforbusiness.py b/samples/sample_connector_usage/sample_connector_usage_onedriveforbusiness.py index eac3ba7..cb370a1 100644 --- a/samples/sample_connector_usage/sample_connector_usage_onedriveforbusiness.py +++ b/samples/sample_connector_usage/sample_connector_usage_onedriveforbusiness.py @@ -1,72 +1,70 @@ # Copyright (c) Microsoft Corporation. All rights reserved. -"""OneDrive for Business Connector SDK sample.""" - -import asyncio +"""OneDrive for Business sample for the Azure Connectors Python SDK.""" import os from azure.connectors import ConnectorException from azure.connectors.onedriveforbusiness import OnedriveforbusinessClient -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential # Connection runtime URL format: # https://[region].azure-apihub.net/apim/onedriveforbusiness/[connection-id] CONNECTION_RUNTIME_URL = os.environ.get("ONEDRIVEFORBUSINESS_CONNECTION_URL", "") -async def example_list_root_folder() -> None: +def example_list_root_folder() -> None: """List files in the root folder.""" - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnedriveforbusinessClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.list_root_folder_async() + with OnedriveforbusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.list_root_folder() values = result.get("value", []) if result else [] print(f"Found {len(values)} items in root folder.") -async def example_get_file_metadata() -> None: +def example_get_file_metadata() -> None: """Get file metadata by path.""" file_path = os.environ.get("TEST_FILE_PATH", "/Documents/report.docx") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnedriveforbusinessClient(CONNECTION_RUNTIME_URL, credential) as client: - metadata = await client.get_file_metadata_by_path_async(path=file_path) + with OnedriveforbusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + metadata = client.get_file_metadata_by_path(path=file_path) if metadata: print(f"Name: {metadata.get('name')}, Size: {metadata.get('size')} bytes") else: print("No metadata was returned.") -async def example_create_share_link() -> None: +def example_create_share_link() -> None: """Create a share link for a file ID.""" file_id = os.environ.get("TEST_FILE_ID") if not file_id: print("Set TEST_FILE_ID to run the share-link example.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnedriveforbusinessClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.create_share_link_async(id=file_id, type_="view") + with OnedriveforbusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.create_share_link(id=file_id, type_="view") if result: print(f"Share URL: {result.get('webUrl')}") else: print("No share link was returned.") -async def main() -> None: +def main() -> None: """Run sample operations.""" if not CONNECTION_RUNTIME_URL: print("Set ONEDRIVEFORBUSINESS_CONNECTION_URL before running this sample.") return try: - await example_list_root_folder() - await example_get_file_metadata() - await example_create_share_link() + example_list_root_folder() + example_get_file_metadata() + example_create_share_link() except ConnectorException as ex: print(f"Connector error ({ex.status_code}): {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_onenote.py b/samples/sample_connector_usage/sample_connector_usage_onenote.py index a625e65..b98580a 100644 --- a/samples/sample_connector_usage/sample_connector_usage_onenote.py +++ b/samples/sample_connector_usage/sample_connector_usage_onenote.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -OneNote Connector SDK Sample +OneNote sample for the Azure Connectors Python SDK -This sample demonstrates how to use the OneNote connector SDK +This sample demonstrates how to use the OneNote client from the Azure Connectors Python SDK for notebook, section, and page operations. Prerequisites: @@ -20,10 +20,8 @@ python sample_connector_usage_onenote.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.onenote import ( OnenoteClient, @@ -38,15 +36,15 @@ ) -async def example_1_list_notebooks(): +def example_1_list_notebooks(): """Example 1: List recent notebooks.""" print("\n=== Example 1: List Notebooks ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: + with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_notebooks_async() + result = client.list_notebooks() if result and "value" in result: notebooks = result["value"] @@ -62,18 +60,18 @@ async def example_1_list_notebooks(): print(f"Error: {ex}") -async def example_2_list_sections(): +def example_2_list_sections(): """Example 2: List sections in a notebook.""" print("\n=== Example 2: List Sections ===") # Replace with your actual notebook key NOTEBOOK_KEY = "your-notebook-key-here" - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: + with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_sections_in_notebook_async( + result = client.list_sections_in_notebook( notebook_key=NOTEBOOK_KEY ) @@ -91,7 +89,7 @@ async def example_2_list_sections(): print(f"Error: {ex}") -async def example_3_get_pages_in_section(): +def example_3_get_pages_in_section(): """Example 3: Get pages in a section.""" print("\n=== Example 3: Get Pages ===") @@ -99,11 +97,11 @@ async def example_3_get_pages_in_section(): NOTEBOOK_KEY = "your-notebook-key-here" SECTION_ID = "your-section-id-here" - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: + with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: try: - pages = [item async for item in client.get_pages_in_section_async( + pages = [item for item in client.list_pages_in_section( notebook_key=NOTEBOOK_KEY, section_id=SECTION_ID )] @@ -121,20 +119,20 @@ async def example_3_get_pages_in_section(): print(f"Error: {ex}") -async def example_4_create_section(): +def example_4_create_section(): """Example 4: Create a new section in a notebook.""" print("\n=== Example 4: Create Section ===") # Replace with your actual notebook key NOTEBOOK_KEY = "your-notebook-key-here" - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: + with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: try: section_request = CreateSectionRequest(name="SDK Test Section") - result = await client.create_section_in_notebook_async( + result = client.create_section_in_notebook( input=section_request, notebook_key=NOTEBOOK_KEY ) @@ -152,20 +150,20 @@ async def example_4_create_section(): print(f"Error: {ex}") -async def example_5_create_quick_note(): +def example_5_create_quick_note(): """Example 5: Create a page in Quick Notes.""" print("\n=== Example 5: Create Quick Note ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: + with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: try: page_input = ( "Quick Note" "

Created via Azure Connectors Python SDK

" ) - result = await client.create_page_in_quick_notes_async(input=page_input) + result = client.create_page_in_quick_notes(input=page_input) if result: print("Quick note created successfully!") @@ -180,7 +178,7 @@ async def example_5_create_quick_note(): print(f"Error: {ex}") -async def example_6_get_page_content(): +def example_6_get_page_content(): """Example 6: Get page content.""" print("\n=== Example 6: Get Page Content ===") @@ -189,11 +187,11 @@ async def example_6_get_page_content(): SECTION_ID = "your-section-id-here" PAGE_ID = "your-page-id-here" - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: + with OnenoteClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_page_content_async( + result = client.get_page_content( notebook_key=NOTEBOOK_KEY, section_id=SECTION_ID, page_id=PAGE_ID, @@ -212,7 +210,7 @@ async def example_6_get_page_content(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: ONENOTE_CONNECTION_URL environment variable not set.") @@ -221,7 +219,7 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_list_notebooks() + example_1_list_notebooks() # The following examples require valid IDs: # await example_2_list_sections() @@ -234,4 +232,4 @@ async def main(): if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_orderful.py b/samples/sample_connector_usage/sample_connector_usage_orderful.py index d1901bd..2ee38dc 100644 --- a/samples/sample_connector_usage/sample_connector_usage_orderful.py +++ b/samples/sample_connector_usage/sample_connector_usage_orderful.py @@ -1,9 +1,7 @@ -"""Orderful connector SDK sample.""" - -import asyncio +"""Orderful sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.orderful import OrderfulClient @@ -12,20 +10,20 @@ CONNECTION_RUNTIME_URL = os.environ.get("ORDERFUL_CONNECTION_URL", "") -async def main() -> None: +def main() -> None: """List Orderful transactions.""" if not CONNECTION_RUNTIME_URL: print("Set ORDERFUL_CONNECTION_URL to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with OrderfulClient(CONNECTION_RUNTIME_URL, credential) as client: - await client.list_transactions_async() + with OrderfulClient(CONNECTION_RUNTIME_URL, credential) as client: + client.list_transactions() print("Transactions requested.") except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_outlook.py b/samples/sample_connector_usage/sample_connector_usage_outlook.py index 11078a5..704e9f2 100644 --- a/samples/sample_connector_usage/sample_connector_usage_outlook.py +++ b/samples/sample_connector_usage/sample_connector_usage_outlook.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Outlook.com Connector SDK Sample +Outlook.com sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Outlook connector SDK +This sample demonstrates how to use the Outlook client from the Azure Connectors Python SDK to interact with Outlook.com calendars, contacts, and email. Note: This connector is for Outlook.com (personal Microsoft accounts). @@ -24,10 +24,8 @@ python sample_connector_usage_outlook.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.outlook import ( OutlookClient, @@ -42,15 +40,15 @@ ) -async def example_1_list_calendars(): +def example_1_list_calendars(): """Example 1: List available calendars.""" print("\n=== Example 1: List Calendars ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: + with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.calendar_get_tables_async() + result = client.list_calendar_get_tables() if result: calendars = result.get("value", []) @@ -73,15 +71,15 @@ async def example_1_list_calendars(): print(f"Error: {ex}") -async def example_2_list_contact_folders(): +def example_2_list_contact_folders(): """Example 2: List available contact folders.""" print("\n=== Example 2: List Contact Folders ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: + with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.contact_get_tables_async() + result = client.list_contact_get_tables() if result: folders = result.get("value", []) @@ -103,18 +101,18 @@ async def example_2_list_contact_folders(): print(f"Error: {ex}") -async def example_3_get_calendar_events(): +def example_3_get_calendar_events(): """Example 3: Get calendar events.""" print("\n=== Example 3: Get Calendar Events ===") # Calendar ID - use 'Calendar' for default calendar or get ID from Example 1 calendar_id = os.environ.get("OUTLOOK_CALENDAR_ID", "Calendar") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: + with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.calendar_get_items_async( + result = client.list_calendar_get_items( table=calendar_id, top=5 # Get up to 5 events ) @@ -136,18 +134,18 @@ async def example_3_get_calendar_events(): print(f"Error: {ex}") -async def example_4_get_contacts(): +def example_4_get_contacts(): """Example 4: Get contacts from a contact folder.""" print("\n=== Example 4: Get Contacts ===") # Contact folder ID - use 'Contacts' for default folder or get ID from Example 2 folder_id = os.environ.get("OUTLOOK_CONTACTS_FOLDER_ID", "Contacts") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: + with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.contact_get_items_async( + result = client.list_contact_get_items( table=folder_id, top=10 # Get up to 10 contacts ) @@ -172,7 +170,7 @@ async def example_4_get_contacts(): print(f"Error: {ex}") -async def example_5_send_email(): +def example_5_send_email(): """Example 5: Send an email.""" print("\n=== Example 5: Send Email ===") @@ -183,9 +181,9 @@ async def example_5_send_email(): print("Skipping email send example...") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: + with OutlookClient(CONNECTION_RUNTIME_URL, credential) as client: try: email = ClientSendHtmlMessage( to=recipient, @@ -196,7 +194,7 @@ async def example_5_send_email(): importance="Normal" ) - await client.send_email_async(input=email) + client.send_email(input=email) print("Email sent successfully!") print(f" To: {recipient}") @@ -208,9 +206,9 @@ async def example_5_send_email(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" - print("Outlook.com Connector SDK - Sample Usage") + print("Outlook.com sample usage for the Azure Connectors Python SDK") print("=" * 60) if not CONNECTION_RUNTIME_URL: @@ -219,15 +217,15 @@ async def main(): print("Format: https://[region].azure-apihub.net/apim/outlook/[id]") return - await example_1_list_calendars() - await example_2_list_contact_folders() - await example_3_get_calendar_events() - await example_4_get_contacts() - await example_5_send_email() + example_1_list_calendars() + example_2_list_contact_folders() + example_3_get_calendar_events() + example_4_get_contacts() + example_5_send_email() print("\n" + "=" * 60) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_pdfco.py b/samples/sample_connector_usage/sample_connector_usage_pdfco.py index 2a50c50..7678e18 100644 --- a/samples/sample_connector_usage/sample_connector_usage_pdfco.py +++ b/samples/sample_connector_usage/sample_connector_usage_pdfco.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -PDF.co Connector SDK Sample +PDF.co sample for the Azure Connectors Python SDK -This sample demonstrates how to use the PDF.co connector SDK. +This sample demonstrates how to use the PDF.co client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a PDF.co connection @@ -20,11 +20,9 @@ python sample_connector_usage_pdfco.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.pdfco import ( @@ -38,19 +36,19 @@ CONNECTION_RUNTIME_URL = os.environ.get("PDFCO_CONNECTION_URL", "") -async def example_1_html_to_pdf(): +def example_1_html_to_pdf(): """Example 1: Convert an HTML snippet to a PDF.""" print("\n=== Example 1: HTML to PDF ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with PdfcoClient(CONNECTION_RUNTIME_URL, credential) as client: + with PdfcoClient(CONNECTION_RUNTIME_URL, credential) as client: try: request = HtmlToPdfInput( html="

Hello from PDF.co

", ) - result = await client.html_to_pdf_async(input=request) + result = client.html_to_pdf(input=request) print(f"HTML to PDF result: {result}") @@ -60,19 +58,19 @@ async def example_1_html_to_pdf(): print(f"Error: {ex}") -async def example_2_url_to_pdf(): +def example_2_url_to_pdf(): """Example 2: Create a PDF from a public URL.""" print("\n=== Example 2: URL to PDF ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with PdfcoClient(CONNECTION_RUNTIME_URL, credential) as client: + with PdfcoClient(CONNECTION_RUNTIME_URL, credential) as client: try: request = UrlToPdfInput( url="https://example.com", ) - result = await client.url_to_pdf_async(input=request) + result = client.url_to_pdf(input=request) print(f"URL to PDF result: {result}") @@ -82,7 +80,7 @@ async def example_2_url_to_pdf(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: PDFCO_CONNECTION_URL environment variable not set.") @@ -91,11 +89,11 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_html_to_pdf() - await example_2_url_to_pdf() + example_1_html_to_pdf() + example_2_url_to_pdf() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_pipedrive.py b/samples/sample_connector_usage/sample_connector_usage_pipedrive.py index 2052656..9894cfd 100644 --- a/samples/sample_connector_usage/sample_connector_usage_pipedrive.py +++ b/samples/sample_connector_usage/sample_connector_usage_pipedrive.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Pipedrive Connector SDK Sample +Pipedrive sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Pipedrive connector SDK. +This sample demonstrates how to use the Pipedrive client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a Pipedrive connection @@ -19,11 +19,9 @@ python sample_connector_usage_pipedrive.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.pipedrive import ( AddDealRequest, @@ -38,15 +36,15 @@ ) -async def example_1_list_deals(): +def example_1_list_deals(): """Example 1: List deals for the authorized account.""" print("\n=== Example 1: List Deals ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with PipedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + with PipedriveClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.list_deals_async() + result = client.list_deals() deals = (result or {}).get("data", []) if isinstance(result, dict) else [] print(f"Found {len(deals)} deal(s).") @@ -57,15 +55,15 @@ async def example_1_list_deals(): print(f"Error: {ex}") -async def example_2_get_deal(): +def example_2_get_deal(): """Example 2: Retrieve a single deal by id.""" print("\n=== Example 2: Get Deal ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with PipedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + with PipedriveClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_deal_async(deal_id=1) + result = client.get_deal(deal_id=1) print(f"Deal: {result}") except ConnectorException as ex: @@ -74,19 +72,19 @@ async def example_2_get_deal(): print(f"Error: {ex}") -async def example_3_add_deal(): +def example_3_add_deal(): """Example 3: Create a new deal for the authorized account.""" print("\n=== Example 3: Add Deal ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with PipedriveClient(CONNECTION_RUNTIME_URL, credential) as client: + with PipedriveClient(CONNECTION_RUNTIME_URL, credential) as client: try: new_deal = AddDealRequest( title="Sample deal", ) - result = await client.add_deal_async(input=new_deal) + result = client.add_deal(input=new_deal) print(f"Created deal: {result}") except ConnectorException as ex: @@ -95,7 +93,7 @@ async def example_3_add_deal(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: PIPEDRIVE_CONNECTION_URL environment variable not set.") @@ -104,12 +102,12 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_list_deals() - await example_2_get_deal() - await example_3_add_deal() + example_1_list_deals() + example_2_get_deal() + example_3_add_deal() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_planner.py b/samples/sample_connector_usage/sample_connector_usage_planner.py index a085942..1938b4a 100644 --- a/samples/sample_connector_usage/sample_connector_usage_planner.py +++ b/samples/sample_connector_usage/sample_connector_usage_planner.py @@ -1,7 +1,7 @@ """ -Microsoft Planner Connector SDK Sample +Microsoft Planner sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Planner connector SDK. +This sample demonstrates how to use the Planner client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Planner connection @@ -17,10 +17,8 @@ python sample_connector_usage_planner.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors.planner import ( PlannerClient, CreateTaskRequest, @@ -36,16 +34,16 @@ ) -async def example_1_list_my_tasks(): +def example_1_list_my_tasks(): """Example 1: List all tasks assigned to me""" print("\n=== Example 1: List My Tasks ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: client = PlannerClient(CONNECTION_RUNTIME_URL, credential) try: tasks = [ - task async for task in client.list_my_tasks_async() + task for task in client.list_my_tasks() ] if tasks: @@ -59,19 +57,19 @@ async def example_1_list_my_tasks(): print(f"Error: {ex}") -async def example_2_list_group_plans(group_id: str): +def example_2_list_group_plans(group_id: str): """Example 2: List all plans in a group""" print("\n=== Example 2: List Group Plans ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: client = PlannerClient(CONNECTION_RUNTIME_URL, credential) try: - plans = await client.list_group_plans_async(group_id=group_id) + plans = list(client.list_group_plans(group_id=group_id)) - if plans and plans.get('value'): - print(f"Found {len(plans.get('value', []))} plans in group") - for plan in plans.get('value', [])[:5]: # Show first 5 + if plans: + print(f"Found {len(plans)} plans in group") + for plan in plans[:5]: # Show first 5 print(f" - {plan.get('title')} ({plan.get('id')})") else: print("No plans found in group") @@ -80,23 +78,23 @@ async def example_2_list_group_plans(group_id: str): print(f"Error: {ex}") -async def example_3_get_task_details(task_id: str): +def example_3_get_task_details(task_id: str): """Example 3: Get task and task details""" print("\n=== Example 3: Get Task Details ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: client = PlannerClient(CONNECTION_RUNTIME_URL, credential) try: # Get basic task info - task = await client.get_task_async(id=task_id) + task = client.get_task(id=task_id) if task: print(f"Task: {task.get('title')}") print(f" - Percent Complete: {task.get('percentComplete')}%") print(f" - Created: {task.get('createdDateTime')}") # Get detailed task info - details = await client.get_task_details_async(id=task_id) + details = client.get_task_details(id=task_id) if details: print(f" - Description: {details.get('description', 'No description')}") @@ -104,11 +102,11 @@ async def example_3_get_task_details(task_id: str): print(f"Error: {ex}") -async def example_4_create_bucket(group_id: str, plan_id: str): +def example_4_create_bucket(group_id: str, plan_id: str): """Example 4: Create a new bucket in a plan""" print("\n=== Example 4: Create Bucket ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: client = PlannerClient(CONNECTION_RUNTIME_URL, credential) try: @@ -118,7 +116,7 @@ async def example_4_create_bucket(group_id: str, plan_id: str): plan_id=plan_id ) - bucket = await client.create_bucket_async(input=bucket_input) + bucket = client.create_bucket(input=bucket_input) if bucket: print(f"Created bucket: {bucket.get('name')} ({bucket.get('id')})") @@ -127,11 +125,11 @@ async def example_4_create_bucket(group_id: str, plan_id: str): print(f"Error: {ex}") -async def example_5_create_and_update_task(group_id: str, plan_id: str, bucket_id: str): +def example_5_create_and_update_task(group_id: str, plan_id: str, bucket_id: str): """Example 5: Create and update a task""" print("\n=== Example 5: Create and Update Task ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: client = PlannerClient(CONNECTION_RUNTIME_URL, credential) try: @@ -141,10 +139,10 @@ async def example_5_create_and_update_task(group_id: str, plan_id: str, bucket_i plan_id=plan_id, bucket_id=bucket_id, title="Sample Task from SDK", - priority=5 # Medium priority + priority=5, # Medium priority ) - task = await client.create_task_async(input=task_input) + task = client.create_task(input=task_input) if task: task_id = task.get('id') @@ -153,31 +151,31 @@ async def example_5_create_and_update_task(group_id: str, plan_id: str, bucket_i # Update the task update_input = UpdateTaskRequest( title="Updated Sample Task", - percent_complete=50 + percent_complete=50, ) - updated = await client.update_task_async(input=update_input, id=task_id) + updated = client.update_task(input=update_input, id=task_id) if updated: print("Updated task to 50% complete") # Clean up - delete the task - await client.delete_task_async(id=task_id) + client.delete_task(id=task_id) print("Deleted task") except Exception as ex: print(f"Error: {ex}") -async def example_6_get_plan_details(plan_id: str): +def example_6_get_plan_details(plan_id: str): """Example 6: Get plan details""" print("\n=== Example 6: Get Plan Details ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: client = PlannerClient(CONNECTION_RUNTIME_URL, credential) try: - details = await client.get_plan_details_async(id=plan_id) + details = client.get_plan_details(id=plan_id) if details: print(f"Plan ID: {details.get('id')}") @@ -192,14 +190,14 @@ async def example_6_get_plan_details(plan_id: str): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples""" - print("Planner Connector SDK - Sample Usage") + print("Planner sample usage for the Azure Connectors Python SDK") print("=" * 50) print() # Example 1: List my tasks (no parameters needed) - await example_1_list_my_tasks() + example_1_list_my_tasks() # Examples 2-6 require IDs from your Planner # Replace these with actual values from your environment @@ -208,13 +206,13 @@ async def main(): task_id = "" # Task ID if group_id: - await example_2_list_group_plans(group_id) + example_2_list_group_plans(group_id) if task_id: - await example_3_get_task_details(task_id) + example_3_get_task_details(task_id) if plan_id: - await example_6_get_plan_details(plan_id) + example_6_get_plan_details(plan_id) # NOTE: Examples 4 and 5 create resources # Uncomment to run them with valid IDs: @@ -229,8 +227,8 @@ async def main(): if __name__ == "__main__": - asyncio.run(main()) + main() if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_plivo.py b/samples/sample_connector_usage/sample_connector_usage_plivo.py index 02f702d..7144d66 100644 --- a/samples/sample_connector_usage/sample_connector_usage_plivo.py +++ b/samples/sample_connector_usage/sample_connector_usage_plivo.py @@ -1,9 +1,7 @@ -"""Plivo connector SDK sample.""" - -import asyncio +"""Plivo sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.plivo import PlivoClient, SMS @@ -12,11 +10,11 @@ CONNECTION_RUNTIME_URL = os.environ.get("PLIVO_CONNECTION_URL", "") -async def send_sms() -> None: +def send_sms() -> None: """Send an SMS message.""" - async with DefaultAzureCredential() as credential: - async with PlivoClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.send_sms_async( + with DefaultAzureCredential() as credential: + with PlivoClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.send_sms( input=SMS( src="15550000000", dst="15551111111", @@ -27,26 +25,26 @@ async def send_sms() -> None: print(f"Send result: {result}") -async def list_messages() -> None: +def list_messages() -> None: """List messages for an account.""" - async with DefaultAzureCredential() as credential: - async with PlivoClient(CONNECTION_RUNTIME_URL, credential) as client: - messages = await client.list_messages_async(auth_id="PLIVO_AUTH_ID") + with DefaultAzureCredential() as credential: + with PlivoClient(CONNECTION_RUNTIME_URL, credential) as client: + messages = client.list_messages(auth_id="PLIVO_AUTH_ID") print(f"Messages: {messages}") -async def main() -> None: +def main() -> None: """Run Plivo connector examples.""" if not CONNECTION_RUNTIME_URL: print("Set PLIVO_CONNECTION_URL to run this sample.") return try: - await list_messages() - await send_sms() + list_messages() + send_sms() except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_plumsail.py b/samples/sample_connector_usage/sample_connector_usage_plumsail.py index 175cef6..cf86a29 100644 --- a/samples/sample_connector_usage/sample_connector_usage_plumsail.py +++ b/samples/sample_connector_usage/sample_connector_usage_plumsail.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Plumsail Connector SDK Sample +Plumsail sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Plumsail connector SDK. +This sample demonstrates how to use the Plumsail client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a Plumsail connection @@ -20,11 +20,9 @@ python sample_connector_usage_plumsail.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.plumsail import ( @@ -37,15 +35,15 @@ CONNECTION_RUNTIME_URL = os.environ.get("PLUMSAIL_CONNECTION_URL", "") -async def example_1_get_profile(): +def example_1_get_profile(): """Example 1: Get the current account profile.""" print("\n=== Example 1: Get current profile ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with PlumsailClient(CONNECTION_RUNTIME_URL, credential) as client: + with PlumsailClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.profiles_me_get_async() + result = client.profiles_me_get() print(f"Profile result: {result}") @@ -55,22 +53,23 @@ async def example_1_get_profile(): print(f"Error: {ex}") -async def example_2_extract_text_from_pdf(): +def example_2_extract_text_from_pdf(): """Example 2: Extract text content from a PDF document.""" print("\n=== Example 2: Extract text from PDF ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with PlumsailClient(CONNECTION_RUNTIME_URL, credential) as client: + with PlumsailClient(CONNECTION_RUNTIME_URL, credential) as client: try: request = Pdf2TextRequest( document_content="", result_type="Raw", ) - result = await client.flow_v1_documents_jobs_extract_text_from_pdf_async( + poller = client.begin_flow_v1_documents_jobs_extract_text_from_pdf( input=request, ) + result = poller.result() print(f"Extracted text result: {result}") @@ -80,7 +79,7 @@ async def example_2_extract_text_from_pdf(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: PLUMSAIL_CONNECTION_URL environment variable not set.") @@ -89,11 +88,11 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_get_profile() - await example_2_extract_text_from_pdf() + example_1_get_profile() + example_2_extract_text_from_pdf() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_powerbi.py b/samples/sample_connector_usage/sample_connector_usage_powerbi.py index 207fd6c..b3764c7 100644 --- a/samples/sample_connector_usage/sample_connector_usage_powerbi.py +++ b/samples/sample_connector_usage/sample_connector_usage_powerbi.py @@ -1,7 +1,7 @@ """ -Power BI Connector SDK Sample +Power BI sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Power BI connector SDK. +This sample demonstrates how to use the Power BI client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Power BI connection @@ -17,11 +17,9 @@ python sample_connector_usage_powerbi.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.powerbi import PowerbiClient @@ -32,13 +30,13 @@ CONNECTION_RUNTIME_URL = os.environ.get("POWERBI_CONNECTION_URL", "") -async def example_1_list_groups() -> list[dict]: +def example_1_list_groups() -> list[dict]: """Example 1: List Power BI workspaces (groups).""" print("\n=== Example 1: List Groups ===") - async with DefaultAzureCredential() as credential: - async with PowerbiClient(CONNECTION_RUNTIME_URL, credential) as client: - groups_response = await client.list_groups_async() + with DefaultAzureCredential() as credential: + with PowerbiClient(CONNECTION_RUNTIME_URL, credential) as client: + groups_response = client.list_groups() groups = groups_response.get("value", []) if groups_response else [] print(f"Found {len(groups)} groups") @@ -48,13 +46,13 @@ async def example_1_list_groups() -> list[dict]: return groups -async def example_2_list_datasets(group_id: str) -> list[dict]: +def example_2_list_datasets(group_id: str) -> list[dict]: """Example 2: List datasets in a specific workspace.""" print("\n=== Example 2: List Datasets ===") - async with DefaultAzureCredential() as credential: - async with PowerbiClient(CONNECTION_RUNTIME_URL, credential) as client: - datasets_response = await client.list_datasets_async(groupid=group_id) + with DefaultAzureCredential() as credential: + with PowerbiClient(CONNECTION_RUNTIME_URL, credential) as client: + datasets_response = client.list_datasets(groupid=group_id) datasets = datasets_response.get("value", []) if datasets_response else [] print(f"Found {len(datasets)} datasets in group '{group_id}'") @@ -64,39 +62,39 @@ async def example_2_list_datasets(group_id: str) -> list[dict]: return datasets -async def example_3_refresh_dataset(group_id: str, dataset_id: str) -> None: +def example_3_refresh_dataset(group_id: str, dataset_id: str) -> None: """Example 3: Trigger dataset refresh.""" print("\n=== Example 3: Refresh Dataset ===") - async with DefaultAzureCredential() as credential: - async with PowerbiClient(CONNECTION_RUNTIME_URL, credential) as client: - await client.refresh_dataset_async(groupid=group_id, datasetid=dataset_id) + with DefaultAzureCredential() as credential: + with PowerbiClient(CONNECTION_RUNTIME_URL, credential) as client: + client.refresh_dataset(groupid=group_id, datasetid=dataset_id) print(f"Refresh requested for dataset '{dataset_id}'") -async def main() -> None: +def main() -> None: """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: POWERBI_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Power BI Connector SDK - Sample Usage") + print("Power BI sample usage for the Azure Connectors Python SDK") print("=" * 50) try: - groups = await example_1_list_groups() + groups = example_1_list_groups() if groups: first_group_id = groups[0].get("id") if first_group_id: - datasets = await example_2_list_datasets(first_group_id) + datasets = example_2_list_datasets(first_group_id) # Optional: trigger a refresh if at least one dataset exists. if datasets: first_dataset_id = datasets[0].get("id") if first_dataset_id: - await example_3_refresh_dataset(first_group_id, first_dataset_id) + example_3_refresh_dataset(first_group_id, first_dataset_id) else: print("No group id found in first group record; skipping dataset examples.") else: @@ -109,4 +107,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_projectplace.py b/samples/sample_connector_usage/sample_connector_usage_projectplace.py index 5ebace4..0cfc037 100644 --- a/samples/sample_connector_usage/sample_connector_usage_projectplace.py +++ b/samples/sample_connector_usage/sample_connector_usage_projectplace.py @@ -1,7 +1,7 @@ """ -Projectplace Connector SDK Sample +Projectplace sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Projectplace connector SDK. +This sample demonstrates how to use the Projectplace client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a Projectplace connection @@ -17,11 +17,9 @@ python sample_connector_usage_projectplace.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.projectplace import ( @@ -36,23 +34,23 @@ CONNECTION_RUNTIME_URL = os.environ.get("PROJECTPLACE_CONNECTION_URL", "") -async def example_1_list_boards() -> None: +def example_1_list_boards() -> None: """Example 1: List the boards the user has access to.""" print("\n=== Example 1: List Boards ===") - async with DefaultAzureCredential() as credential: - async with ProjectplaceClient(CONNECTION_RUNTIME_URL, credential) as client: - boards = await client.list_boards_async() + with DefaultAzureCredential() as credential: + with ProjectplaceClient(CONNECTION_RUNTIME_URL, credential) as client: + boards = client.list_boards() print(f"Boards: {boards}") -async def example_2_create_card() -> None: +def example_2_create_card() -> None: """Example 2: Create a card on a board.""" print("\n=== Example 2: Create Card ===") - async with DefaultAzureCredential() as credential: - async with ProjectplaceClient(CONNECTION_RUNTIME_URL, credential) as client: - card = await client.create_card_async( + with DefaultAzureCredential() as credential: + with ProjectplaceClient(CONNECTION_RUNTIME_URL, credential) as client: + card = client.create_card( input=CreateCardInput( column_id=123456, title="SDK sample card", @@ -63,27 +61,27 @@ async def example_2_create_card() -> None: print(f"Created card: {card}") -async def example_3_move_card() -> None: +def example_3_move_card() -> None: """Example 3: Move a card to another column.""" print("\n=== Example 3: Move Card ===") - async with DefaultAzureCredential() as credential: - async with ProjectplaceClient(CONNECTION_RUNTIME_URL, credential) as client: - card = await client.move_card_async( + with DefaultAzureCredential() as credential: + with ProjectplaceClient(CONNECTION_RUNTIME_URL, credential) as client: + card = client.move_card( input=MoveCardInput(card_id=123456, column_id=654321), board_id=789012, ) print(f"Moved card: {card}") -async def main() -> None: +def main() -> None: """Run Projectplace connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: PROJECTPLACE_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Projectplace Connector SDK - Sample Usage") + print("Projectplace sample usage for the Azure Connectors Python SDK") print("=" * 50) try: @@ -100,4 +98,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_replicon.py b/samples/sample_connector_usage/sample_connector_usage_replicon.py index 33f6952..575e626 100644 --- a/samples/sample_connector_usage/sample_connector_usage_replicon.py +++ b/samples/sample_connector_usage/sample_connector_usage_replicon.py @@ -1,9 +1,7 @@ -"""Replicon connector SDK sample.""" - -import asyncio +"""Replicon sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.replicon import RepliconClient @@ -12,20 +10,20 @@ CONNECTION_RUNTIME_URL = os.environ.get("REPLICON_CONNECTION_URL", "") -async def main() -> None: +def main() -> None: """Get Replicon tenant endpoint details.""" if not CONNECTION_RUNTIME_URL: print("Set REPLICON_CONNECTION_URL to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with RepliconClient(CONNECTION_RUNTIME_URL, credential) as client: - endpoint = await client.get_my_tenant_endpoint_details_async() + with RepliconClient(CONNECTION_RUNTIME_URL, credential) as client: + endpoint = client.get_my_tenant_endpoint_details() print(f"Tenant endpoint: {endpoint}") except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_revai.py b/samples/sample_connector_usage/sample_connector_usage_revai.py index c692c2f..b4522d5 100644 --- a/samples/sample_connector_usage/sample_connector_usage_revai.py +++ b/samples/sample_connector_usage/sample_connector_usage_revai.py @@ -1,9 +1,7 @@ -"""Rev.ai connector SDK sample.""" - -import asyncio +"""Rev.ai sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.revai import RevaiClient, TranscriptionInput @@ -12,39 +10,40 @@ CONNECTION_RUNTIME_URL = os.environ.get("REVAI_CONNECTION_URL", "") -async def get_account() -> None: +def get_account() -> None: """Get account information.""" - async with DefaultAzureCredential() as credential: - async with RevaiClient(CONNECTION_RUNTIME_URL, credential) as client: - account = await client.account_get_async() + with DefaultAzureCredential() as credential: + with RevaiClient(CONNECTION_RUNTIME_URL, credential) as client: + account = client.account_get() print(f"Account: {account}") -async def submit_transcription() -> None: +def submit_transcription() -> None: """Submit an audio file for transcription.""" - async with DefaultAzureCredential() as credential: - async with RevaiClient(CONNECTION_RUNTIME_URL, credential) as client: - job = await client.transcription_async( + with DefaultAzureCredential() as credential: + with RevaiClient(CONNECTION_RUNTIME_URL, credential) as client: + job = client.transcription( input=TranscriptionInput( source_config={"url": "https://example.com/audio.wav"}, metadata="connector-sdk-sample", + notification_config={"url": "https://example.com/webhook"}, ), ) print(f"Transcription job: {job}") -async def main() -> None: +def main() -> None: """Run Rev.ai connector examples.""" if not CONNECTION_RUNTIME_URL: print("Set REVAI_CONNECTION_URL to run this sample.") return try: - await get_account() - await submit_transcription() + get_account() + submit_transcription() except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_rss.py b/samples/sample_connector_usage/sample_connector_usage_rss.py index b7094b9..7848965 100644 --- a/samples/sample_connector_usage/sample_connector_usage_rss.py +++ b/samples/sample_connector_usage/sample_connector_usage_rss.py @@ -1,16 +1,14 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """Sample usage for the RSS connector client.""" - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors.rss import RssClient -async def main() -> None: +def main() -> None: """Run a simple RSS sample flow.""" connection_url = os.getenv("RSS_CONNECTION_URL") if not connection_url: @@ -18,15 +16,15 @@ async def main() -> None: feed_url = os.getenv("RSS_FEED_URL", "https://devblogs.microsoft.com/python/feed/") - async with DefaultAzureCredential() as credential: - async with RssClient(connection_url, credential) as client: - items = await client.list_feed_items_async( + with DefaultAzureCredential() as credential: + with RssClient(connection_url, credential) as client: + items = client.list_feed_items( feed_url=feed_url, since_property="PublishDate", ) print(f"Retrieved {len(items or [])} item(s) from '{feed_url}'.") - latest_items = await client.list_feed_items_async( + latest_items = client.list_feed_items( feed_url=feed_url, since_property="PublishDate", ) @@ -35,4 +33,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_salesforce.py b/samples/sample_connector_usage/sample_connector_usage_salesforce.py index 44b3445..86fa11c 100644 --- a/samples/sample_connector_usage/sample_connector_usage_salesforce.py +++ b/samples/sample_connector_usage/sample_connector_usage_salesforce.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Salesforce Connector SDK Sample +Salesforce sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Salesforce connector SDK. +This sample demonstrates how to use the Salesforce client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Salesforce connection @@ -21,10 +21,8 @@ python sample_connector_usage_salesforce.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.salesforce import ExecuteSoqlQueryParameters, SalesforceClient @@ -36,15 +34,15 @@ ) -async def example_1_get_tables(): +def example_1_get_tables(): """Example 1: List Salesforce object types.""" print("\n=== Example 1: Get Tables ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SalesforceClient(CONNECTION_RUNTIME_URL, credential) as client: + with SalesforceClient(CONNECTION_RUNTIME_URL, credential) as client: try: - tables = [item async for item in client.get_tables_async()] + tables = [item for item in client.list_tables()] if tables: print(f"Found {len(tables)} table(s):") @@ -62,15 +60,15 @@ async def example_1_get_tables(): print(f"Error: {ex}") -async def example_2_get_records(): +def example_2_get_records(): """Example 2: Read records from Account table.""" print("\n=== Example 2: Get Account Records ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SalesforceClient(CONNECTION_RUNTIME_URL, credential) as client: + with SalesforceClient(CONNECTION_RUNTIME_URL, credential) as client: try: - records = [item async for item in client.get_items_async( + records = [item for item in client.list_items( table="account", top=5, select="Id,Name,Phone", @@ -92,18 +90,18 @@ async def example_2_get_records(): print(f"Error: {ex}") -async def example_3_execute_soql(): +def example_3_execute_soql(): """Example 3: Execute a SOQL query.""" print("\n=== Example 3: Execute SOQL Query ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SalesforceClient(CONNECTION_RUNTIME_URL, credential) as client: + with SalesforceClient(CONNECTION_RUNTIME_URL, credential) as client: try: query_input = ExecuteSoqlQueryParameters( query="SELECT Id, Name FROM Account LIMIT 5", ) - result = await client.execute_soql_query_async(input=query_input) + result = client.execute_soql_query(input=query_input) if result: records = result.get("records", []) @@ -119,7 +117,7 @@ async def example_3_execute_soql(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: SALESFORCE_CONNECTION_URL environment variable not set.") @@ -128,12 +126,12 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_get_tables() - await example_2_get_records() - await example_3_execute_soql() + example_1_get_tables() + example_2_get_records() + example_3_execute_soql() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_seismicplanner.py b/samples/sample_connector_usage/sample_connector_usage_seismicplanner.py index a37e224..a6d0447 100644 --- a/samples/sample_connector_usage/sample_connector_usage_seismicplanner.py +++ b/samples/sample_connector_usage/sample_connector_usage_seismicplanner.py @@ -1,9 +1,7 @@ -"""Seismic Planner connector SDK sample.""" - -import asyncio +"""Seismic Planner sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.seismicplanner import SeismicplannerClient @@ -13,23 +11,23 @@ SPACE_ID = os.environ.get("SEISMICPLANNER_SPACE_ID", "") -async def main() -> None: +def main() -> None: """List projects in a Seismic Planner space.""" if not CONNECTION_RUNTIME_URL or not SPACE_ID: print("Set SEISMICPLANNER_CONNECTION_URL and SEISMICPLANNER_SPACE_ID to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with SeismicplannerClient( + with SeismicplannerClient( CONNECTION_RUNTIME_URL, credential, ) as client: - projects = await client.get_projects_async(space_id=SPACE_ID) + projects = list(client.list_projects(space_id=SPACE_ID)) print(f"Projects: {projects}") except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_sendgrid.py b/samples/sample_connector_usage/sample_connector_usage_sendgrid.py index 9b68e57..36fa0fb 100644 --- a/samples/sample_connector_usage/sample_connector_usage_sendgrid.py +++ b/samples/sample_connector_usage/sample_connector_usage_sendgrid.py @@ -1,7 +1,7 @@ """ -SendGrid Connector SDK Sample +SendGrid sample for the Azure Connectors Python SDK -This sample demonstrates how to use the SendGrid connector SDK. +This sample demonstrates how to use the SendGrid client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a SendGrid connection @@ -17,11 +17,9 @@ python sample_connector_usage_sendgrid.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.sendgrid import ( @@ -35,61 +33,62 @@ CONNECTION_RUNTIME_URL = os.environ.get("SENDGRID_CONNECTION_URL", "") -async def example_1_send_email() -> None: +def example_1_send_email() -> None: """Example 1: Send an email.""" print("\n=== Example 1: Send Email ===") - async with DefaultAzureCredential() as credential: - async with SendgridClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.send_email_async( + with DefaultAzureCredential() as credential: + with SendgridClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.send_email( input=EmailRequest( from_="sender@example.com", to="recipient@example.com", subject="Hello from the SDK sample", - text="This message was sent via the SendGrid connector SDK.", + text="This message was sent via the SendGrid client from the Azure Connectors Python SDK.", + ishtml=False, ), ) print(f"Send result: {result}") -async def example_2_list_recipient_lists() -> None: +def example_2_list_recipient_lists() -> None: """Example 2: List recipient lists.""" print("\n=== Example 2: List Recipient Lists ===") - async with DefaultAzureCredential() as credential: - async with SendgridClient(CONNECTION_RUNTIME_URL, credential) as client: - lists = await client.list_recipient_lists_async() + with DefaultAzureCredential() as credential: + with SendgridClient(CONNECTION_RUNTIME_URL, credential) as client: + lists = client.list_recipient_lists() print(f"Recipient lists: {lists}") -async def example_3_list_recipients() -> None: +def example_3_list_recipients() -> None: """Example 3: List recipients.""" print("\n=== Example 3: List Recipients ===") - async with DefaultAzureCredential() as credential: - async with SendgridClient(CONNECTION_RUNTIME_URL, credential) as client: - recipients = await client.list_recipients_async() + with DefaultAzureCredential() as credential: + with SendgridClient(CONNECTION_RUNTIME_URL, credential) as client: + recipients = client.list_recipients() print(f"Recipients: {recipients}") -async def example_4_get_bounce() -> None: +def example_4_get_bounce() -> None: """Example 4: Get a bounce record for an email address.""" print("\n=== Example 4: Get Bounce ===") - async with DefaultAzureCredential() as credential: - async with SendgridClient(CONNECTION_RUNTIME_URL, credential) as client: - bounce = await client.get_bounce_async(email="recipient@example.com") + with DefaultAzureCredential() as credential: + with SendgridClient(CONNECTION_RUNTIME_URL, credential) as client: + bounce = client.list_bounce(email="recipient@example.com") print(f"Bounce: {bounce}") -async def main() -> None: +def main() -> None: """Run SendGrid connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: SENDGRID_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("SendGrid Connector SDK - Sample Usage") + print("SendGrid sample usage for the Azure Connectors Python SDK") print("=" * 50) try: @@ -107,4 +106,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_servicebus.py b/samples/sample_connector_usage/sample_connector_usage_servicebus.py index 74ba5bf..79ea3cc 100644 --- a/samples/sample_connector_usage/sample_connector_usage_servicebus.py +++ b/samples/sample_connector_usage/sample_connector_usage_servicebus.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Azure Service Bus Connector SDK Sample +Azure Service Bus sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Azure Service Bus connector SDK +This sample demonstrates how to use the Azure Service Bus client from the Azure Connectors Python SDK to send and receive messages from Azure Service Bus queues and topics. Prerequisites: @@ -24,11 +24,9 @@ python sample_connector_usage_servicebus.py """ - -import asyncio import json import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.servicebus import ( ServicebusClient, @@ -48,7 +46,7 @@ SUBSCRIPTION_NAME = os.environ.get("SERVICEBUS_SUBSCRIPTION_NAME", "") -async def example_1_send_message_to_queue(): +def example_1_send_message_to_queue(): """Example 1: Send a single message to a Service Bus queue.""" print("\n=== Example 1: Send Message to Queue ===") @@ -57,9 +55,9 @@ async def example_1_send_message_to_queue(): print("Example: $env:SERVICEBUS_QUEUE_NAME = 'my-queue'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Create a message message = ServiceBusMessage( @@ -74,7 +72,7 @@ async def example_1_send_message_to_queue(): correlation_id="corr-abc-123" ) - await client.send_message_async( + client.send_message( input=message, entity_name=QUEUE_NAME ) @@ -90,7 +88,7 @@ async def example_1_send_message_to_queue(): print(f"Error: {ex}") -async def example_2_receive_message_from_queue(): +def example_2_receive_message_from_queue(): """Example 2: Receive one queue message with a peek lock.""" print("\n=== Example 2: Receive Message from Queue ===") @@ -98,11 +96,11 @@ async def example_2_receive_message_from_queue(): print("Set SERVICEBUS_QUEUE_NAME environment variable.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_messages_from_queue_with_peek_lock_async( + result = client.list_messages_from_queue_with_peek_lock( queue_name=QUEUE_NAME, max_message_count=1, ) @@ -124,7 +122,7 @@ async def example_2_receive_message_from_queue(): print(f"Error: {ex}") -async def example_3_receive_with_peek_lock(): +def example_3_receive_with_peek_lock(): """Example 3: Receive a message with peek-lock and complete it.""" print("\n=== Example 3: Receive with Peek-Lock and Complete ===") @@ -132,12 +130,12 @@ async def example_3_receive_with_peek_lock(): print("Set SERVICEBUS_QUEUE_NAME environment variable.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Receive message with peek-lock (message is locked, not removed) - result = await client.get_messages_from_queue_with_peek_lock_async( + result = client.list_messages_from_queue_with_peek_lock( queue_name=QUEUE_NAME, max_message_count=1, ) @@ -155,7 +153,7 @@ async def example_3_receive_with_peek_lock(): # Complete the message (remove from queue) if lock_token: - await client.complete_message_in_queue_async( + client.complete_message_in_queue( queue_name=QUEUE_NAME, lock_token=lock_token, ) @@ -169,7 +167,7 @@ async def example_3_receive_with_peek_lock(): print(f"Error: {ex}") -async def example_4_receive_and_abandon(): +def example_4_receive_and_abandon(): """Example 4: Receive a message and abandon it (return to queue).""" print("\n=== Example 4: Receive and Abandon Message ===") @@ -177,11 +175,11 @@ async def example_4_receive_and_abandon(): print("Set SERVICEBUS_QUEUE_NAME environment variable.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_messages_from_queue_with_peek_lock_async( + result = client.list_messages_from_queue_with_peek_lock( queue_name=QUEUE_NAME, max_message_count=1, ) @@ -195,7 +193,7 @@ async def example_4_receive_and_abandon(): # Abandon the message (return to queue for retry) if lock_token: - await client.abandon_message_in_queue_async( + client.abandon_message_in_queue( queue_name=QUEUE_NAME, lock_token=lock_token, ) @@ -209,7 +207,7 @@ async def example_4_receive_and_abandon(): print(f"Error: {ex}") -async def example_5_send_message_to_topic(): +def example_5_send_message_to_topic(): """Example 5: Send a message to a Service Bus topic.""" print("\n=== Example 5: Send Message to Topic ===") @@ -218,9 +216,9 @@ async def example_5_send_message_to_topic(): print("Example: $env:SERVICEBUS_TOPIC_NAME = 'my-topic'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: try: message = ServiceBusMessage( content_data=json.dumps({ @@ -232,7 +230,7 @@ async def example_5_send_message_to_topic(): label="user-event" ) - await client.send_message_async( + client.send_message( input=message, entity_name=TOPIC_NAME ) @@ -246,7 +244,7 @@ async def example_5_send_message_to_topic(): print(f"Error: {ex}") -async def example_6_receive_from_topic_subscription(): +def example_6_receive_from_topic_subscription(): """Example 6: Receive a message from a topic subscription.""" print("\n=== Example 6: Receive from Topic Subscription ===") @@ -254,11 +252,11 @@ async def example_6_receive_from_topic_subscription(): print("Set SERVICEBUS_TOPIC_NAME and SERVICEBUS_SUBSCRIPTION_NAME.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_messages_from_topic_with_peek_lock_async( + result = client.list_messages_from_topic_with_peek_lock( topic_name=TOPIC_NAME, subscription_name=SUBSCRIPTION_NAME, max_message_count=1, @@ -279,7 +277,7 @@ async def example_6_receive_from_topic_subscription(): print(f"Error: {ex}") -async def example_7_dead_letter_message(): +def example_7_dead_letter_message(): """Example 7: Move a message to the dead-letter queue.""" print("\n=== Example 7: Dead-Letter a Message ===") @@ -287,11 +285,11 @@ async def example_7_dead_letter_message(): print("Set SERVICEBUS_QUEUE_NAME environment variable.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_messages_from_queue_with_peek_lock_async( + result = client.list_messages_from_queue_with_peek_lock( queue_name=QUEUE_NAME, max_message_count=1, ) @@ -305,7 +303,7 @@ async def example_7_dead_letter_message(): # Move to dead-letter queue if lock_token: - await client.dead_letter_message_in_queue_async( + client.dead_letter_message_in_queue( queue_name=QUEUE_NAME, lock_token=lock_token, dead_letter_reason="Processing failed", @@ -321,7 +319,7 @@ async def example_7_dead_letter_message(): print(f"Error: {ex}") -async def example_8_batch_receive(): +def example_8_batch_receive(): """Example 8: Receive multiple messages in batch.""" print("\n=== Example 8: Batch Receive Messages ===") @@ -329,11 +327,11 @@ async def example_8_batch_receive(): print("Set SERVICEBUS_QUEUE_NAME environment variable.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: + with ServicebusClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_messages_from_queue_with_peek_lock_async( + result = client.list_messages_from_queue_with_peek_lock( queue_name=QUEUE_NAME, max_message_count=5, ) @@ -352,7 +350,7 @@ async def example_8_batch_receive(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: SERVICEBUS_CONNECTION_URL environment variable not set.") @@ -365,21 +363,21 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") # Queue operations - await example_1_send_message_to_queue() - await example_2_receive_message_from_queue() - await example_3_receive_with_peek_lock() - await example_4_receive_and_abandon() + example_1_send_message_to_queue() + example_2_receive_message_from_queue() + example_3_receive_with_peek_lock() + example_4_receive_and_abandon() # Topic operations - await example_5_send_message_to_topic() - await example_6_receive_from_topic_subscription() + example_5_send_message_to_topic() + example_6_receive_from_topic_subscription() # Advanced operations - await example_7_dead_letter_message() - await example_8_batch_receive() + example_7_dead_letter_message() + example_8_batch_receive() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_sharepoint.py b/samples/sample_connector_usage/sample_connector_usage_sharepoint.py index 30db737..c0ec7d8 100644 --- a/samples/sample_connector_usage/sample_connector_usage_sharepoint.py +++ b/samples/sample_connector_usage/sample_connector_usage_sharepoint.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -SharePoint Online Connector SDK Sample +SharePoint Online sample for the Azure Connectors Python SDK -This sample demonstrates how to use the SharePoint Online connector SDK. +This sample demonstrates how to use the SharePoint Online client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with SharePoint Online connection @@ -23,12 +23,10 @@ python sample_connector_usage_sharepoint.py """ - -import asyncio import os try: - from azure.identity.aio import DefaultAzureCredential + from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.sharepointonline import ( PatchItemInput, @@ -55,15 +53,15 @@ ) -async def example_1_get_lists(): +def example_1_get_lists(): """Example 1: Get all lists and libraries from a SharePoint site.""" print("\n=== Example 1: Get Lists and Libraries ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: + with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: try: - lists = await client.get_tables_async(dataset=SHAREPOINT_SITE_URL) + lists = client.list_tables(dataset=SHAREPOINT_SITE_URL) if lists and 'value' in lists: print(f"Found {len(lists['value'])} lists and libraries:") @@ -81,17 +79,17 @@ async def example_1_get_lists(): print(f"Error: {ex}") -async def example_2_get_list_items(): +def example_2_get_list_items(): """Example 2: Get items from a SharePoint list.""" print("\n=== Example 2: Get List Items ===") list_name = os.environ.get("TEST_LIST_NAME", "18050732-97a3-4509-b510-a094a5a35947") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: + with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: try: - items = [item async for item in client.get_items_async( + items = [item for item in client.list_items( dataset=SHAREPOINT_SITE_URL, table=list_name, )] @@ -115,21 +113,21 @@ async def example_2_get_list_items(): print(f"Error: {ex}") -async def example_3_create_list_item(): +def example_3_create_list_item(): """Example 3: Create a new item in a SharePoint list.""" print("\n=== Example 3: Create List Item ===") list_name = os.environ.get("TEST_LIST_NAME", "Tasks") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: + with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: try: new_item = PostItemInput( additional_properties={'Title': 'Test Task from Python SDK'}, ) - created = await client.post_item_async( + created = client.post_item( dataset=SHAREPOINT_SITE_URL, table=list_name, input=new_item, @@ -141,7 +139,7 @@ async def example_3_create_list_item(): print(f"Title: {created.get('Title', 'N/A')}") # Clean up: delete the item we just created - await client.delete_item_async( + client.delete_item( dataset=SHAREPOINT_SITE_URL, table=list_name, id=int(item_id), @@ -158,22 +156,22 @@ async def example_3_create_list_item(): print(f"Error: {ex}") -async def example_4_update_list_item(): +def example_4_update_list_item(): """Example 4: Create, update, and delete a list item.""" print("\n=== Example 4: Update List Item (Full CRUD) ===") list_name = os.environ.get("TEST_LIST_NAME", "Tasks") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: + with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: try: # CREATE print("Creating item...") new_item = PostItemInput( additional_properties={'Title': 'Task to Update'}, ) - created = await client.post_item_async( + created = client.post_item( dataset=SHAREPOINT_SITE_URL, table=list_name, input=new_item, @@ -183,7 +181,7 @@ async def example_4_update_list_item(): # READ print("Reading item...") - item = await client.get_item_async( + item = client.get_item( dataset=SHAREPOINT_SITE_URL, table=list_name, id=int(item_id), @@ -195,7 +193,7 @@ async def example_4_update_list_item(): updates = PatchItemInput( additional_properties={'Title': 'Updated Task Title'}, ) - await client.patch_item_async( + client.patch_item( dataset=SHAREPOINT_SITE_URL, table=list_name, id=int(item_id), @@ -203,7 +201,7 @@ async def example_4_update_list_item(): ) # Verify update - updated_item = await client.get_item_async( + updated_item = client.get_item( dataset=SHAREPOINT_SITE_URL, table=list_name, id=int(item_id), @@ -212,7 +210,7 @@ async def example_4_update_list_item(): # DELETE print("Deleting item...") - await client.delete_item_async( + client.delete_item( dataset=SHAREPOINT_SITE_URL, table=list_name, id=int(item_id), @@ -226,20 +224,20 @@ async def example_4_update_list_item(): print(f"Error: {ex}") -async def example_5_query_with_filters(): +def example_5_query_with_filters(): """Example 5: Query list items with OData filters.""" print("\n=== Example 5: Query with Filters ===") list_name = os.environ.get("TEST_LIST_NAME", "Tasks") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: + with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Create some test items first print("Creating test items...") for i in range(3): - await client.post_item_async( + client.post_item( dataset=SHAREPOINT_SITE_URL, table=list_name, input=PostItemInput( @@ -250,7 +248,7 @@ async def example_5_query_with_filters(): # Query with filters print("\nQuerying items (ordered by creation date, top 5)...") - items = [item async for item in client.get_items_async( + items = [item for item in client.list_items( dataset=SHAREPOINT_SITE_URL, table=list_name, filter=None, @@ -269,7 +267,7 @@ async def example_5_query_with_filters(): print("\nCleaning up test items...") for item in items[:3]: if 'Test Item' in item.get('Title', ''): - await client.delete_item_async( + client.delete_item( dataset=SHAREPOINT_SITE_URL, table=list_name, id=int(item['Id']), @@ -283,17 +281,17 @@ async def example_5_query_with_filters(): print(f"Error: {ex}") -async def example_6_file_operations(): +def example_6_file_operations(): """Example 6: File operations - list folders and get file metadata.""" print("\n=== Example 6: File Operations ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: + with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: try: # List root folder print("Listing root folder...") - root_folder = await client.list_root_folder_async(dataset=SHAREPOINT_SITE_URL) + root_folder = client.list_root_folder(dataset=SHAREPOINT_SITE_URL) if root_folder and 'value' in root_folder: print(f"Found {len(root_folder['value'])} items in root folder:") @@ -307,7 +305,7 @@ async def example_6_file_operations(): # List a specific folder (Shared Documents is common) print("\nListing 'Shared Documents' folder...") - folder = await client.list_folder_async( + folder = client.list_folder( dataset=SHAREPOINT_SITE_URL, id='/Shared Documents', ) @@ -330,19 +328,19 @@ async def example_6_file_operations(): print(f"Error: {ex}") -async def example_7_error_handling(): +def example_7_error_handling(): """Example 7: Demonstrate error handling.""" print("\n=== Example 7: Error Handling ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: + with SharepointonlineClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Attempt to get an item with an invalid ID invalid_item_id = 99999 list_name = os.environ.get("TEST_LIST_NAME", "Tasks") - item = await client.get_item_async( + item = client.get_item( dataset=SHAREPOINT_SITE_URL, table=list_name, id=invalid_item_id, @@ -357,23 +355,23 @@ async def example_7_error_handling(): print(f" Message: {ex}") -async def main(): +def main(): """Run all examples.""" - print("SharePoint Online Connector SDK - Sample Usage") + print("SharePoint Online sample usage for the Azure Connectors Python SDK") print("=" * 50) print() - await example_1_get_lists() - await example_2_get_list_items() - await example_3_create_list_item() - await example_4_update_list_item() - await example_5_query_with_filters() - await example_6_file_operations() - await example_7_error_handling() + example_1_get_lists() + example_2_get_list_items() + example_3_create_list_item() + example_4_update_list_item() + example_5_query_with_filters() + example_6_file_operations() + example_7_error_handling() print("\n" + "=" * 50) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_shifts.py b/samples/sample_connector_usage/sample_connector_usage_shifts.py index 49b179b..01930a4 100644 --- a/samples/sample_connector_usage/sample_connector_usage_shifts.py +++ b/samples/sample_connector_usage/sample_connector_usage_shifts.py @@ -1,7 +1,7 @@ """ -Shifts Connector SDK Sample +Shifts sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Shifts connector SDK. +This sample demonstrates how to use the Shifts client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Shifts connection @@ -17,11 +17,9 @@ python sample_connector_usage_shifts.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.shifts import ShiftsClient @@ -32,14 +30,13 @@ CONNECTION_RUNTIME_URL = os.environ.get("SHIFTS_CONNECTION_URL", "") -async def example_1_list_teams() -> list[dict]: +def example_1_list_teams() -> list[dict]: """Example 1: List joined teams.""" print("\n=== Example 1: List Teams ===") - async with DefaultAzureCredential() as credential: - async with ShiftsClient(CONNECTION_RUNTIME_URL, credential) as client: - teams_response = await client.get_all_teams_async() - teams = teams_response.get("value", []) if teams_response else [] + with DefaultAzureCredential() as credential: + with ShiftsClient(CONNECTION_RUNTIME_URL, credential) as client: + teams = list(client.list_all_teams()) print(f"Found {len(teams)} teams") for team in teams[:10]: @@ -48,13 +45,13 @@ async def example_1_list_teams() -> list[dict]: return teams -async def example_2_get_schedule(team_id: str) -> None: +def example_2_get_schedule(team_id: str) -> None: """Example 2: Get a team's schedule.""" print("\n=== Example 2: Get Schedule ===") - async with DefaultAzureCredential() as credential: - async with ShiftsClient(CONNECTION_RUNTIME_URL, credential) as client: - schedule = await client.get_schedule_async(team_id=team_id) + with DefaultAzureCredential() as credential: + with ShiftsClient(CONNECTION_RUNTIME_URL, credential) as client: + schedule = client.get_schedule(team_id=team_id) if not schedule: print("No schedule returned") @@ -65,13 +62,13 @@ async def example_2_get_schedule(team_id: str) -> None: print(f"Provision Status: {schedule.get('provisionStatus')}") -async def example_3_list_shifts(team_id: str) -> None: +def example_3_list_shifts(team_id: str) -> None: """Example 3: List shifts for a team.""" print("\n=== Example 3: List Shifts ===") - async with DefaultAzureCredential() as credential: - async with ShiftsClient(CONNECTION_RUNTIME_URL, credential) as client: - shifts_response = [item async for item in client.list_shifts_async(team_id=team_id, top=10)] + with DefaultAzureCredential() as credential: + with ShiftsClient(CONNECTION_RUNTIME_URL, credential) as client: + shifts_response = [item for item in client.list_shifts(team_id=team_id, top=10)] shifts = shifts_response if shifts_response else [] print(f"Found {len(shifts)} shifts") @@ -79,23 +76,23 @@ async def example_3_list_shifts(team_id: str) -> None: print(f" - {shift.get('id')} assigned to {shift.get('userId')}") -async def main() -> None: +def main() -> None: """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: SHIFTS_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Shifts Connector SDK - Sample Usage") + print("Shifts sample usage for the Azure Connectors Python SDK") print("=" * 50) try: - teams = await example_1_list_teams() + teams = example_1_list_teams() if teams: first_team_id = teams[0].get("id") if first_team_id: - await example_2_get_schedule(first_team_id) - await example_3_list_shifts(first_team_id) + example_2_get_schedule(first_team_id) + example_3_list_shifts(first_team_id) else: print("No team id found in first record; skipping team-specific examples.") else: @@ -108,4 +105,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_signinghub.py b/samples/sample_connector_usage/sample_connector_usage_signinghub.py index ab7e9f0..86786b1 100644 --- a/samples/sample_connector_usage/sample_connector_usage_signinghub.py +++ b/samples/sample_connector_usage/sample_connector_usage_signinghub.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -SigningHub Connector SDK Sample +SigningHub sample for the Azure Connectors Python SDK -This sample demonstrates how to use the SigningHub connector SDK. +This sample demonstrates how to use the SigningHub client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a SigningHub connection @@ -20,16 +20,15 @@ python sample_connector_usage_signinghub.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.signinghub import ( SigninghubClient, CheckBoxFieldRequest, + FieldDimension, ) # Connection runtime URL format: @@ -37,15 +36,15 @@ CONNECTION_RUNTIME_URL = os.environ.get("SIGNINGHUB_CONNECTION_URL", "") -async def example_1_get_contacts(): +def example_1_get_contacts(): """Example 1: Retrieve contacts for the current user.""" print("\n=== Example 1: Get Contacts ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SigninghubClient(CONNECTION_RUNTIME_URL, credential) as client: + with SigninghubClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.contacts_get_async( + result = client.list_contacts_get( record_per_page=10, page_no=1, ) @@ -58,17 +57,24 @@ async def example_1_get_contacts(): print(f"Error: {ex}") -async def example_2_add_check_box_field(): +def example_2_add_check_box_field(): """Example 2: Add a checkbox field to a document in a package.""" print("\n=== Example 2: Add CheckBox Field ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SigninghubClient(CONNECTION_RUNTIME_URL, credential) as client: + with SigninghubClient(CONNECTION_RUNTIME_URL, credential) as client: try: - request = CheckBoxFieldRequest() + request = CheckBoxFieldRequest( + order=1, + page_no=1, + dimensions=FieldDimension(x=120.0, y=220.0, width=18.0, height=18.0), + field_name="Approve", + value="false", + validation_rule="none", + ) - result = await client.checkbox_add_check_box_async( + result = client.checkbox_add_check_box( input=request, package_id=12345, document_id=67890, @@ -82,15 +88,15 @@ async def example_2_add_check_box_field(): print(f"Error: {ex}") -async def example_3_delete_attachment(): +def example_3_delete_attachment(): """Example 3: Delete an attachment from a document.""" print("\n=== Example 3: Delete Attachment ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SigninghubClient(CONNECTION_RUNTIME_URL, credential) as client: + with SigninghubClient(CONNECTION_RUNTIME_URL, credential) as client: try: - await client.attachment_delete_attachment_async( + client.attachment_delete_attachment( package_id=12345, document_id=67890, attachment_id=13579, @@ -104,7 +110,7 @@ async def example_3_delete_attachment(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: SIGNINGHUB_CONNECTION_URL environment variable not set.") @@ -113,12 +119,12 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_get_contacts() - await example_2_add_check_box_field() - await example_3_delete_attachment() + example_1_get_contacts() + example_2_add_check_box_field() + example_3_delete_attachment() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_slack.py b/samples/sample_connector_usage/sample_connector_usage_slack.py index 4937b4b..19e1bf0 100644 --- a/samples/sample_connector_usage/sample_connector_usage_slack.py +++ b/samples/sample_connector_usage/sample_connector_usage_slack.py @@ -1,7 +1,7 @@ """ -Slack Connector SDK Sample +Slack sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Slack connector SDK. +This sample demonstrates how to use the Slack client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Slack connection @@ -17,11 +17,9 @@ python sample_connector_usage_slack.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.slack import PostMessageRequest, SlackClient @@ -32,13 +30,13 @@ CONNECTION_RUNTIME_URL = os.environ.get("SLACK_CONNECTION_URL", "") -async def example_1_list_channels() -> None: +def example_1_list_channels() -> None: """Example 1: List channels.""" print("\n=== Example 1: List Channels ===") - async with DefaultAzureCredential() as credential: - async with SlackClient(CONNECTION_RUNTIME_URL, credential) as client: - channels_response = [item async for item in client.list_channels_async()] + with DefaultAzureCredential() as credential: + with SlackClient(CONNECTION_RUNTIME_URL, credential) as client: + channels_response = [item for item in client.list_channels()] channels = channels_response if channels_response else [] print(f"Found {len(channels)} channels") @@ -46,13 +44,13 @@ async def example_1_list_channels() -> None: print(f" - {channel.get('name')} ({channel.get('id')})") -async def example_2_create_channel() -> None: +def example_2_create_channel() -> None: """Example 2: Create a channel.""" print("\n=== Example 2: Create Channel ===") - async with DefaultAzureCredential() as credential: - async with SlackClient(CONNECTION_RUNTIME_URL, credential) as client: - created = await client.create_channel_async( + with DefaultAzureCredential() as credential: + with SlackClient(CONNECTION_RUNTIME_URL, credential) as client: + created = client.create_channel( name="sdk-sample-channel", is_private=False, ) @@ -60,38 +58,38 @@ async def example_2_create_channel() -> None: print(f"Created channel: {channel.get('name')} ({channel.get('id')})") -async def example_3_post_message() -> None: +def example_3_post_message() -> None: """Example 3: Post a message to a channel.""" print("\n=== Example 3: Post Message ===") - async with DefaultAzureCredential() as credential: - async with SlackClient(CONNECTION_RUNTIME_URL, credential) as client: + with DefaultAzureCredential() as credential: + with SlackClient(CONNECTION_RUNTIME_URL, credential) as client: payload = PostMessageRequest( channel="#general", text="Hello from Slack Python SDK sample", ) - posted = await client.post_message_async(input=payload) + posted = client.post_message(input=payload) print( f"Posted: ok={posted.get('ok') if posted else None}, " f"ts={posted.get('ts') if posted else None}" ) -async def main() -> None: +def main() -> None: """Run Slack connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: SLACK_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Slack Connector SDK - Sample Usage") + print("Slack sample usage for the Azure Connectors Python SDK") print("=" * 50) try: - await example_1_list_channels() + example_1_list_channels() # Uncomment after confirming your app has channel-create permission. # await example_2_create_channel() - await example_3_post_message() + example_3_post_message() except ConnectorException as ex: print(f"Connector error: {ex}") @@ -100,4 +98,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_smtp.py b/samples/sample_connector_usage/sample_connector_usage_smtp.py index f3a6e98..d2f9fd8 100644 --- a/samples/sample_connector_usage/sample_connector_usage_smtp.py +++ b/samples/sample_connector_usage/sample_connector_usage_smtp.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -SMTP Connector SDK Sample +SMTP sample for the Azure Connectors Python SDK -This sample demonstrates how to use the SMTP connector SDK. +This sample demonstrates how to use the SMTP client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with SMTP connection @@ -19,11 +19,9 @@ python sample_connector_usage_smtp.py """ - -import asyncio import base64 import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.smtp import ( SmtpClient, @@ -39,7 +37,7 @@ ) -async def example_1_send_basic_email(): +def example_1_send_basic_email(): """Example 1: Send a basic email.""" print("\n=== Example 1: Send Basic Email ===") @@ -52,9 +50,9 @@ async def example_1_send_basic_email(): print(" $env:TEST_SMTP_TO = 'recipient@example.com'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: + with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: try: email = Email( from_=sender, @@ -63,7 +61,7 @@ async def example_1_send_basic_email(): body="Hello! This is a test email sent via the Azure Connectors SDK for Python.", ) - await client.send_email_async(input=email) + client.send_email(input=email) print("Email sent successfully:") print(f" From: {sender}") @@ -76,7 +74,7 @@ async def example_1_send_basic_email(): print(f"Error: {ex}") -async def example_2_send_email_with_cc_bcc(): +def example_2_send_email_with_cc_bcc(): """Example 2: Send an email with CC and BCC recipients.""" print("\n=== Example 2: Send Email with CC/BCC ===") @@ -93,9 +91,9 @@ async def example_2_send_email_with_cc_bcc(): print(" $env:TEST_SMTP_BCC = 'bcc@example.com' (optional)") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: + with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: try: email = Email( from_=sender, @@ -106,7 +104,7 @@ async def example_2_send_email_with_cc_bcc(): body="This email demonstrates CC and BCC functionality.", ) - await client.send_email_async(input=email) + client.send_email(input=email) print("Email sent successfully:") print(f" From: {sender}") @@ -122,7 +120,7 @@ async def example_2_send_email_with_cc_bcc(): print(f"Error: {ex}") -async def example_3_send_html_email(): +def example_3_send_html_email(): """Example 3: Send an HTML-formatted email.""" print("\n=== Example 3: Send HTML Email ===") @@ -135,9 +133,9 @@ async def example_3_send_html_email(): print(" $env:TEST_SMTP_TO = 'recipient@example.com'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: + with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: try: html_body = """ @@ -169,7 +167,7 @@ async def example_3_send_html_email(): body=html_body.strip(), ) - await client.send_email_async(input=email) + client.send_email(input=email) print("HTML email sent successfully:") print(f" From: {sender}") @@ -182,7 +180,7 @@ async def example_3_send_html_email(): print(f"Error: {ex}") -async def example_4_send_email_with_attachment(): +def example_4_send_email_with_attachment(): """Example 4: Send an email with an attachment.""" print("\n=== Example 4: Send Email with Attachment ===") @@ -195,9 +193,9 @@ async def example_4_send_email_with_attachment(): print(" $env:TEST_SMTP_TO = 'recipient@example.com'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: + with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Create a sample text file content file_content = "This is a sample attachment created by Azure Connectors SDK." @@ -217,7 +215,7 @@ async def example_4_send_email_with_attachment(): attachments=[attachment], ) - await client.send_email_async(input=email) + client.send_email(input=email) print("Email with attachment sent successfully:") print(f" From: {sender}") @@ -230,7 +228,7 @@ async def example_4_send_email_with_attachment(): print(f"Error: {ex}") -async def example_5_send_email_with_options(): +def example_5_send_email_with_options(): """Example 5: Send an email with importance and receipts.""" print("\n=== Example 5: Send Email with Options ===") @@ -243,9 +241,9 @@ async def example_5_send_email_with_options(): print(" $env:TEST_SMTP_TO = 'recipient@example.com'") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: + with SmtpClient(CONNECTION_RUNTIME_URL, credential) as client: try: email = Email( from_=sender, @@ -257,7 +255,7 @@ async def example_5_send_email_with_options(): delivery_receipt=sender, ) - await client.send_email_async(input=email) + client.send_email(input=email) print("Email with options sent successfully:") print(f" From: {sender}") @@ -272,9 +270,9 @@ async def example_5_send_email_with_options(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" - print("SMTP Connector SDK - Sample Usage") + print("SMTP sample usage for the Azure Connectors Python SDK") print("=" * 60) if not CONNECTION_RUNTIME_URL: @@ -283,15 +281,15 @@ async def main(): print("Format: https://[region].azure-apihub.net/apim/smtp/[connection-id]") return - await example_1_send_basic_email() - await example_2_send_email_with_cc_bcc() - await example_3_send_html_email() - await example_4_send_email_with_attachment() - await example_5_send_email_with_options() + example_1_send_basic_email() + example_2_send_email_with_cc_bcc() + example_3_send_html_email() + example_4_send_email_with_attachment() + example_5_send_email_with_options() print("\n" + "=" * 60) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_sql.py b/samples/sample_connector_usage/sample_connector_usage_sql.py index c57c6b4..3125b79 100644 --- a/samples/sample_connector_usage/sample_connector_usage_sql.py +++ b/samples/sample_connector_usage/sample_connector_usage_sql.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -SQL Server Connector SDK Sample +SQL Server sample for the Azure Connectors Python SDK -This sample demonstrates how to use the SQL Server connector SDK. +This sample demonstrates how to use the SQL Server client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a SQL Server connection @@ -21,11 +21,9 @@ python sample_connector_usage_sql.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.sql import ( SqlClient, @@ -48,14 +46,14 @@ TABLE = os.environ.get("SQL_TABLE", "") -async def example_1_list_servers_and_databases(): +def example_1_list_servers_and_databases(): """Example 1: Discover servers, databases, and tables.""" print("\n=== Example 1: List Servers, Databases, and Tables ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SqlClient(CONNECTION_RUNTIME_URL, credential) as client: - servers = await client.get_servers_async() + with SqlClient(CONNECTION_RUNTIME_URL, credential) as client: + servers = client.list_servers() server_values = servers.get("value", []) if servers else [] print(f"Found {len(server_values)} server(s).") @@ -63,7 +61,7 @@ async def example_1_list_servers_and_databases(): print("Set SQL_SERVER to list databases and tables.") return - databases = await client.get_databases_async(server=SERVER) + databases = client.list_databases(server=SERVER) database_values = databases.get("value", []) if databases else [] print(f"Found {len(database_values)} database(s) on '{SERVER}'.") @@ -71,14 +69,15 @@ async def example_1_list_servers_and_databases(): print("Set SQL_DATABASE to list tables.") return - tables = await client.get_tables_async(server=SERVER, database=DATABASE) - table_values = tables.get("value", []) if tables else [] + table_values = list( + client.list_tables(server=SERVER, database=DATABASE) + ) print(f"Found {len(table_values)} table(s) in '{DATABASE}'.") for table in table_values[:10]: print(f" - {table.get('DisplayName', table.get('Name', 'N/A'))}") -async def example_2_read_rows(): +def example_2_read_rows(): """Example 2: Read rows from a table.""" print("\n=== Example 2: Get Rows ===") @@ -86,11 +85,11 @@ async def example_2_read_rows(): print("Set SQL_SERVER, SQL_DATABASE, and SQL_TABLE to run this example.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SqlClient(CONNECTION_RUNTIME_URL, credential) as client: + with SqlClient(CONNECTION_RUNTIME_URL, credential) as client: try: - rows = [item async for item in client.get_items_async( + rows = [item for item in client.list_items( server=SERVER, database=DATABASE, table=TABLE, @@ -102,7 +101,7 @@ async def example_2_read_rows(): print(f"Connector error: {ex}") -async def example_3_insert_update_delete_row(): +def example_3_insert_update_delete_row(): """Example 3: Insert, update, and delete a row.""" print("\n=== Example 3: Insert, Update, and Delete a Row ===") @@ -110,11 +109,11 @@ async def example_3_insert_update_delete_row(): print("Set SQL_SERVER, SQL_DATABASE, and SQL_TABLE to run this example.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SqlClient(CONNECTION_RUNTIME_URL, credential) as client: + with SqlClient(CONNECTION_RUNTIME_URL, credential) as client: try: - inserted = await client.post_item_async( + inserted = client.post_item( input=PostItemInput( additional_properties={"Name": "Contoso", "Status": "Active"}, ), @@ -128,7 +127,7 @@ async def example_3_insert_update_delete_row(): if not row_id: return - await client.patch_item_async( + client.patch_item( input=PatchItemInput(additional_properties={"Status": "Updated"}), server=SERVER, database=DATABASE, @@ -137,7 +136,7 @@ async def example_3_insert_update_delete_row(): ) print(f"Updated row id: {row_id}") - await client.delete_item_async( + client.delete_item( server=SERVER, database=DATABASE, table=TABLE, @@ -148,7 +147,7 @@ async def example_3_insert_update_delete_row(): print(f"Connector error: {ex}") -async def example_4_query_and_procedures(): +def example_4_query_and_procedures(): """Example 4: Execute a pass-through query and stored procedures.""" print("\n=== Example 4: Query and Stored Procedures ===") @@ -156,11 +155,11 @@ async def example_4_query_and_procedures(): print("Set SQL_SERVER and SQL_DATABASE to run this example.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with SqlClient(CONNECTION_RUNTIME_URL, credential) as client: + with SqlClient(CONNECTION_RUNTIME_URL, credential) as client: try: - query_result = await client.execute_pass_through_native_query_async( + query_result = client.execute_pass_through_native_query( input=SqlPassThroughNativeQueryBody(query="SELECT TOP 1 * FROM sys.tables"), server=SERVER, database=DATABASE, @@ -168,7 +167,7 @@ async def example_4_query_and_procedures(): result_sets = (query_result or {}).get("resultSets", {}) print(f"Query returned {len(result_sets)} result set(s).") - procedures = await client.get_procedures_v2_async( + procedures = client.list_procedures_v2( server=SERVER, database=DATABASE, ) @@ -178,7 +177,7 @@ async def example_4_query_and_procedures(): if procedure_values: procedure_name = procedure_values[0].get("Name") if procedure_name: - await client.execute_procedure_async( + client.execute_procedure( input=ExecuteProcedureInput(), server=SERVER, database=DATABASE, @@ -189,7 +188,7 @@ async def example_4_query_and_procedures(): print(f"Connector error: {ex}") -async def main(): +def main(): """Run all SQL Server connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: SQL_CONNECTION_URL environment variable is not set.") @@ -198,13 +197,13 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_list_servers_and_databases() - await example_2_read_rows() - await example_3_insert_update_delete_row() - await example_4_query_and_procedures() + example_1_list_servers_and_databases() + example_2_read_rows() + example_3_insert_update_delete_row() + example_4_query_and_procedures() print("\n=== SQL Server sample completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_starmind.py b/samples/sample_connector_usage/sample_connector_usage_starmind.py index 8aa5c7e..4a4c87d 100644 --- a/samples/sample_connector_usage/sample_connector_usage_starmind.py +++ b/samples/sample_connector_usage/sample_connector_usage_starmind.py @@ -1,9 +1,7 @@ -"""Starmind connector SDK sample.""" - -import asyncio +"""Starmind sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.starmind import FindExpertsInput, StarmindClient @@ -12,39 +10,39 @@ CONNECTION_RUNTIME_URL = os.environ.get("STARMIND_CONNECTION_URL", "") -async def find_questions() -> None: +def find_questions() -> None: """Find questions matching a query.""" - async with DefaultAzureCredential() as credential: - async with StarmindClient(CONNECTION_RUNTIME_URL, credential) as client: - questions = await client.find_questions_async( + with DefaultAzureCredential() as credential: + with StarmindClient(CONNECTION_RUNTIME_URL, credential) as client: + questions = client.find_questions( query="distributed systems", limit=10, ) print(f"Questions: {questions}") -async def find_experts() -> None: +def find_experts() -> None: """Find experts for a topic.""" - async with DefaultAzureCredential() as credential: - async with StarmindClient(CONNECTION_RUNTIME_URL, credential) as client: - experts = await client.find_experts_async( + with DefaultAzureCredential() as credential: + with StarmindClient(CONNECTION_RUNTIME_URL, credential) as client: + experts = client.find_experts( input=FindExpertsInput(text_query="distributed systems"), ) print(f"Experts: {experts}") -async def main() -> None: +def main() -> None: """Run Starmind connector examples.""" if not CONNECTION_RUNTIME_URL: print("Set STARMIND_CONNECTION_URL to run this sample.") return try: - await find_questions() - await find_experts() + find_questions() + find_experts() except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_starrezrestv1.py b/samples/sample_connector_usage/sample_connector_usage_starrezrestv1.py index 62a007f..2651ac6 100644 --- a/samples/sample_connector_usage/sample_connector_usage_starrezrestv1.py +++ b/samples/sample_connector_usage/sample_connector_usage_starrezrestv1.py @@ -1,9 +1,7 @@ -"""StarRez REST V1 connector SDK sample.""" - -import asyncio +"""StarRez REST V1 sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.starrezrestv1 import SelectBookingInput, Starrezrestv1Client @@ -12,22 +10,23 @@ CONNECTION_RUNTIME_URL = os.environ.get("STARREZRESTV1_CONNECTION_URL", "") -async def main() -> None: +def main() -> None: """List up to ten StarRez bookings.""" if not CONNECTION_RUNTIME_URL: print("Set STARREZRESTV1_CONNECTION_URL to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with Starrezrestv1Client( + with Starrezrestv1Client( CONNECTION_RUNTIME_URL, credential, ) as client: - bookings = await client.select_booking_async( + bookings = client.list_select_booking( input=SelectBookingInput( return_empty_array_on_no_result=True, page_size=10, + page_index=1, ) ) print(f"Bookings: {bookings}") @@ -36,4 +35,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_tallyfy.py b/samples/sample_connector_usage/sample_connector_usage_tallyfy.py index 6d89419..213cdbd 100644 --- a/samples/sample_connector_usage/sample_connector_usage_tallyfy.py +++ b/samples/sample_connector_usage/sample_connector_usage_tallyfy.py @@ -1,9 +1,7 @@ -"""Tallyfy connector SDK sample.""" - -import asyncio +"""Tallyfy sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.tallyfy import CreateRunInput, TallyfyClient @@ -12,19 +10,19 @@ CONNECTION_RUNTIME_URL = os.environ.get("TALLYFY_CONNECTION_URL", "") -async def list_organizations() -> None: +def list_organizations() -> None: """List organizations available to the current user.""" - async with DefaultAzureCredential() as credential: - async with TallyfyClient(CONNECTION_RUNTIME_URL, credential) as client: - organizations = await client.get_user_organizations_async() + with DefaultAzureCredential() as credential: + with TallyfyClient(CONNECTION_RUNTIME_URL, credential) as client: + organizations = client.get_user_organizations() print(f"Organizations: {organizations}") -async def create_run() -> None: +def create_run() -> None: """Create a run from a checklist.""" - async with DefaultAzureCredential() as credential: - async with TallyfyClient(CONNECTION_RUNTIME_URL, credential) as client: - run = await client.create_run_async( + with DefaultAzureCredential() as credential: + with TallyfyClient(CONNECTION_RUNTIME_URL, credential) as client: + run = client.create_run( input=CreateRunInput( name="Quarterly review", checklist_id="CHECKLIST_ID", @@ -35,18 +33,18 @@ async def create_run() -> None: print(f"Created run: {run}") -async def main() -> None: +def main() -> None: """Run Tallyfy connector examples.""" if not CONNECTION_RUNTIME_URL: print("Set TALLYFY_CONNECTION_URL to run this sample.") return try: - await list_organizations() - await create_run() + list_organizations() + create_run() except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_teams.py b/samples/sample_connector_usage/sample_connector_usage_teams.py index 484d6ae..8ab0442 100644 --- a/samples/sample_connector_usage/sample_connector_usage_teams.py +++ b/samples/sample_connector_usage/sample_connector_usage_teams.py @@ -1,7 +1,7 @@ """ -Microsoft Teams Connector SDK Sample +Microsoft Teams sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Teams connector SDK. +This sample demonstrates how to use the Teams client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Teams connection @@ -14,9 +14,7 @@ Usage: python sample_teams_usage.py """ - -import asyncio -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors.teams import TeamsClient # Connection runtime URL format: @@ -24,54 +22,54 @@ CONNECTION_RUNTIME_URL = "" -async def example_1_list_joined_teams(): +def example_1_list_joined_teams(): """Example 1: List all Teams you're a member of""" print("\n=== Example 1: List Joined Teams ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: client = TeamsClient(CONNECTION_RUNTIME_URL, credential) try: - teams = await client.get_all_teams_async() + teams = list(client.list_all_teams()) - print(f"Found {len(teams.get('value', []))} teams") - for team in teams.get('value', [])[:3]: # Show first 3 + print(f"Found {len(teams)} teams") + for team in teams[:3]: # Show first 3 print(f" - {team.get('displayName')} ({team.get('id')})") except Exception as ex: print(f"Error: {ex}") -async def example_2_list_associated_teams(): +def example_2_list_associated_teams(): """Example 2: List associated teams (direct membership + shared channels)""" print("\n=== Example 2: List Associated Teams ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: client = TeamsClient(CONNECTION_RUNTIME_URL, credential) try: - teams = await client.get_all_associated_teams_async() + teams = list(client.list_all_associated_teams()) - print(f"Found {len(teams.get('value', []))} associated teams") - for team in teams.get('value', [])[:3]: # Show first 3 + print(f"Found {len(teams)} associated teams") + for team in teams[:3]: # Show first 3 print(f" - {team.get('displayName')}") except Exception as ex: print(f"Error: {ex}") -async def main(): +def main(): """Run all examples""" - print("Teams Connector SDK - Sample Usage") + print("Teams sample usage for the Azure Connectors Python SDK") print("=" * 50) print() - await example_1_list_joined_teams() - await example_2_list_associated_teams() + example_1_list_joined_teams() + example_2_list_associated_teams() print("\n" + "=" * 50) print("Sample completed!") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_textrequest.py b/samples/sample_connector_usage/sample_connector_usage_textrequest.py index e66cb0c..242c085 100644 --- a/samples/sample_connector_usage/sample_connector_usage_textrequest.py +++ b/samples/sample_connector_usage/sample_connector_usage_textrequest.py @@ -1,7 +1,7 @@ """ -TextRequest Connector SDK Sample +TextRequest sample for the Azure Connectors Python SDK -This sample demonstrates how to use the TextRequest connector SDK. +This sample demonstrates how to use the TextRequest client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a TextRequest connection @@ -17,11 +17,9 @@ python sample_connector_usage_textrequest.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.textrequest import ( @@ -39,15 +37,15 @@ DASHBOARD_ID = int(os.environ.get("TEXTREQUEST_DASHBOARD_ID", "0")) -async def example_1_send_message() -> None: +def example_1_send_message() -> None: """Example 1: Send a message to a contact by phone number.""" print("\n=== Example 1: Send Message ===") - async with DefaultAzureCredential() as credential: - async with TextrequestClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.send_message_by_phone_number_async( + with DefaultAzureCredential() as credential: + with TextrequestClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.send_message_by_phone_number( input=SendMessageByPhoneNumberInput( - body="Hello from the TextRequest connector SDK.", + body="Hello from the TextRequest client in the Azure Connectors Python SDK.", sender_name="Support Team", ), dashboard_id=DASHBOARD_ID, @@ -56,27 +54,29 @@ async def example_1_send_message() -> None: print(f"Send result: {result}") -async def example_2_get_conversations() -> None: +def example_2_get_conversations() -> None: """Example 2: List all conversations for the dashboard.""" print("\n=== Example 2: Get Conversations ===") - async with DefaultAzureCredential() as credential: - async with TextrequestClient(CONNECTION_RUNTIME_URL, credential) as client: - conversations = await client.get_conversations_async( - dashboard_id=DASHBOARD_ID, - page=1, - page_size=20, + with DefaultAzureCredential() as credential: + with TextrequestClient(CONNECTION_RUNTIME_URL, credential) as client: + conversations = list( + client.list_conversations( + dashboard_id=DASHBOARD_ID, + page=1, + page_size=20, + ) ) print(f"Conversations: {conversations}") -async def example_3_create_contact() -> None: +def example_3_create_contact() -> None: """Example 3: Create or update a contact.""" print("\n=== Example 3: Create Contact ===") - async with DefaultAzureCredential() as credential: - async with TextrequestClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.create_contact_async( + with DefaultAzureCredential() as credential: + with TextrequestClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.create_contact( input=CreateContactInput( first_name="Ada", last_name="Lovelace", @@ -88,24 +88,24 @@ async def example_3_create_contact() -> None: print(f"Contact result: {result}") -async def example_4_get_dashboards() -> None: +def example_4_get_dashboards() -> None: """Example 4: Get all dashboards in the account.""" print("\n=== Example 4: Get Dashboards ===") - async with DefaultAzureCredential() as credential: - async with TextrequestClient(CONNECTION_RUNTIME_URL, credential) as client: - dashboards = await client.get_dashboards_async(page=1, page_size=20) + with DefaultAzureCredential() as credential: + with TextrequestClient(CONNECTION_RUNTIME_URL, credential) as client: + dashboards = list(client.list_dashboards(page=1, page_size=20)) print(f"Dashboards: {dashboards}") -async def main() -> None: +def main() -> None: """Run TextRequest connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: TEXTREQUEST_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("TextRequest Connector SDK - Sample Usage") + print("TextRequest sample usage for the Azure Connectors Python SDK") print("=" * 50) try: @@ -124,4 +124,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_ticketmaster.py b/samples/sample_connector_usage/sample_connector_usage_ticketmaster.py index 5dab6ca..33d68b3 100644 --- a/samples/sample_connector_usage/sample_connector_usage_ticketmaster.py +++ b/samples/sample_connector_usage/sample_connector_usage_ticketmaster.py @@ -1,9 +1,7 @@ -"""Ticketmaster connector SDK sample.""" - -import asyncio +"""Ticketmaster sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.ticketmaster import TicketmasterClient @@ -12,20 +10,20 @@ CONNECTION_RUNTIME_URL = os.environ.get("TICKETMASTER_CONNECTION_URL", "") -async def main() -> None: +def main() -> None: """List Ticketmaster attractions.""" if not CONNECTION_RUNTIME_URL: print("Set TICKETMASTER_CONNECTION_URL to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with TicketmasterClient(CONNECTION_RUNTIME_URL, credential) as client: - attractions = await client.attractions_get_async() + with TicketmasterClient(CONNECTION_RUNTIME_URL, credential) as client: + attractions = client.attractions_get() print(f"Attractions: {attractions}") except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_todo.py b/samples/sample_connector_usage/sample_connector_usage_todo.py index 2398c3d..c48bbff 100644 --- a/samples/sample_connector_usage/sample_connector_usage_todo.py +++ b/samples/sample_connector_usage/sample_connector_usage_todo.py @@ -1,7 +1,7 @@ """ -Microsoft To Do Connector SDK Sample +Microsoft To Do sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Microsoft To Do connector SDK. +This sample demonstrates how to use the Microsoft To Do client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Microsoft To Do connection @@ -17,11 +17,9 @@ python sample_connector_usage_todo.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.todo import CreateToDo, CreateToDoList, TodoClient, UpdateToDo @@ -32,13 +30,13 @@ CONNECTION_RUNTIME_URL = os.environ.get("TODO_CONNECTION_URL", "") -async def example_1_list_lists() -> list[dict]: +def example_1_list_lists() -> list[dict]: """Example 1: List all to-do lists.""" print("\n=== Example 1: List To-Do Lists ===") - async with DefaultAzureCredential() as credential: - async with TodoClient(CONNECTION_RUNTIME_URL, credential) as client: - lists_response = await client.get_all_todo_lists_async() + with DefaultAzureCredential() as credential: + with TodoClient(CONNECTION_RUNTIME_URL, credential) as client: + lists_response = client.list_all_todo_lists() lists = lists_response.get("value", []) if lists_response else [] print(f"Found {len(lists)} lists") @@ -48,14 +46,14 @@ async def example_1_list_lists() -> list[dict]: return lists -async def example_2_create_list() -> str | None: +def example_2_create_list() -> str | None: """Example 2: Create a to-do list.""" print("\n=== Example 2: Create To-Do List ===") - async with DefaultAzureCredential() as credential: - async with TodoClient(CONNECTION_RUNTIME_URL, credential) as client: + with DefaultAzureCredential() as credential: + with TodoClient(CONNECTION_RUNTIME_URL, credential) as client: request = CreateToDoList(display_name="SDK Sample List") - created = await client.create_to_do_list_async(input=request) + created = client.create_to_do_list(input=request) if not created: print("No list was created") @@ -66,14 +64,14 @@ async def example_2_create_list() -> str | None: return list_id -async def example_3_create_and_update_todo(list_id: str) -> None: +def example_3_create_and_update_todo(list_id: str) -> None: """Example 3: Create and update a to-do item.""" print("\n=== Example 3: Create And Update To-Do ===") - async with DefaultAzureCredential() as credential: - async with TodoClient(CONNECTION_RUNTIME_URL, credential) as client: + with DefaultAzureCredential() as credential: + with TodoClient(CONNECTION_RUNTIME_URL, credential) as client: create_request = CreateToDo(title="SDK sample task", status="notStarted") - created_todo = await client.create_to_do_async(input=create_request, folder_id=list_id) + created_todo = client.create_to_do(input=create_request, folder_id=list_id) if not created_todo: print("No to-do item returned from create operation") @@ -86,7 +84,7 @@ async def example_3_create_and_update_todo(list_id: str) -> None: return update_request = UpdateToDo(title="SDK sample task (updated)", status="inProgress") - updated_todo = await client.update_to_do_async( + updated_todo = client.update_to_do( input=update_request, folder_id=list_id, id=todo_id, @@ -94,22 +92,22 @@ async def example_3_create_and_update_todo(list_id: str) -> None: print(f"Updated title: {updated_todo.get('title') if updated_todo else 'n/a'}") -async def main() -> None: +def main() -> None: """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: TODO_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Microsoft To Do Connector SDK - Sample Usage") + print("Microsoft To Do sample usage for the Azure Connectors Python SDK") print("=" * 50) try: - await example_1_list_lists() - list_id = await example_2_create_list() + example_1_list_lists() + list_id = example_2_create_list() if list_id: - await example_3_create_and_update_todo(list_id) + example_3_create_and_update_todo(list_id) else: print("Skipping to-do create/update because no list id was returned.") @@ -120,4 +118,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_trello.py b/samples/sample_connector_usage/sample_connector_usage_trello.py index 8204414..f440a60 100644 --- a/samples/sample_connector_usage/sample_connector_usage_trello.py +++ b/samples/sample_connector_usage/sample_connector_usage_trello.py @@ -1,7 +1,7 @@ """ -Trello Connector SDK Sample +Trello sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Trello connector SDK. +This sample demonstrates how to use the Trello client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a Trello connection @@ -17,11 +17,9 @@ python sample_connector_usage_trello.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.trello import CreateBoard, CreateCard, CreateList, TrelloClient @@ -32,39 +30,39 @@ CONNECTION_RUNTIME_URL = os.environ.get("TRELLO_CONNECTION_URL", "") -async def example_1_list_boards() -> None: +def example_1_list_boards() -> None: """Example 1: List boards available to the current member.""" print("\n=== Example 1: List Boards ===") - async with DefaultAzureCredential() as credential: - async with TrelloClient(CONNECTION_RUNTIME_URL, credential) as client: - boards = await client.list_boards_simple_async() + with DefaultAzureCredential() as credential: + with TrelloClient(CONNECTION_RUNTIME_URL, credential) as client: + boards = client.list_boards_simple() print(f"Boards: {boards}") -async def example_2_create_board() -> None: +def example_2_create_board() -> None: """Example 2: Create a board.""" print("\n=== Example 2: Create Board ===") - async with DefaultAzureCredential() as credential: - async with TrelloClient(CONNECTION_RUNTIME_URL, credential) as client: - board = await client.create_board_async( + with DefaultAzureCredential() as credential: + with TrelloClient(CONNECTION_RUNTIME_URL, credential) as client: + board = client.create_board( input=CreateBoard( name="SDK sample board", - desc="Created from the Trello connector SDK sample.", + desc="Created by the Trello client in the Azure Connectors Python SDK.", default_lists="false", ) ) print(f"Created board: {board}") -async def example_3_create_list() -> None: +def example_3_create_list() -> None: """Example 3: Create a list on an existing board.""" print("\n=== Example 3: Create List ===") - async with DefaultAzureCredential() as credential: - async with TrelloClient(CONNECTION_RUNTIME_URL, credential) as client: - created_list = await client.create_list_async( + with DefaultAzureCredential() as credential: + with TrelloClient(CONNECTION_RUNTIME_URL, credential) as client: + created_list = client.create_list( input=CreateList( name="SDK sample list", id_board="board-id", @@ -74,31 +72,31 @@ async def example_3_create_list() -> None: print(f"Created list: {created_list}") -async def example_4_create_card() -> None: +def example_4_create_card() -> None: """Example 4: Create a card in an existing list.""" print("\n=== Example 4: Create Card ===") - async with DefaultAzureCredential() as credential: - async with TrelloClient(CONNECTION_RUNTIME_URL, credential) as client: - card = await client.create_card_async( + with DefaultAzureCredential() as credential: + with TrelloClient(CONNECTION_RUNTIME_URL, credential) as client: + card = client.create_card( input=CreateCard( id_list="list-id", name="SDK sample card", - desc="Created from the Trello connector SDK sample.", + desc="Created by the Trello client in the Azure Connectors Python SDK.", ), board_id="board-id", ) print(f"Created card: {card}") -async def main() -> None: +def main() -> None: """Run Trello connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: TRELLO_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Trello Connector SDK - Sample Usage") + print("Trello sample usage for the Azure Connectors Python SDK") print("=" * 50) try: @@ -116,4 +114,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_twitter.py b/samples/sample_connector_usage/sample_connector_usage_twitter.py index 4d4f944..312766d 100644 --- a/samples/sample_connector_usage/sample_connector_usage_twitter.py +++ b/samples/sample_connector_usage/sample_connector_usage_twitter.py @@ -1,9 +1,7 @@ -"""Twitter connector SDK sample.""" - -import asyncio +"""Twitter sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.twitter import TwitterClient @@ -12,40 +10,40 @@ CONNECTION_RUNTIME_URL = os.environ.get("TWITTER_CONNECTION_URL", "") -async def list_user_timeline() -> None: +def list_user_timeline() -> None: """List recent posts from a user's timeline.""" - async with DefaultAzureCredential() as credential: - async with TwitterClient(CONNECTION_RUNTIME_URL, credential) as client: - timeline = await client.user_timeline_async( + with DefaultAzureCredential() as credential: + with TwitterClient(CONNECTION_RUNTIME_URL, credential) as client: + timeline = client.list_user_timeline( user_name="Azure", max_results=10, ) print(f"Timeline: {timeline}") -async def search_posts() -> None: +def search_posts() -> None: """Search recent posts.""" - async with DefaultAzureCredential() as credential: - async with TwitterClient(CONNECTION_RUNTIME_URL, credential) as client: - results = await client.search_tweet_async( + with DefaultAzureCredential() as credential: + with TwitterClient(CONNECTION_RUNTIME_URL, credential) as client: + results = client.list_search_tweet( search_query="Azure Logic Apps", max_results=10, ) print(f"Search results: {results}") -async def main() -> None: +def main() -> None: """Run Twitter connector examples.""" if not CONNECTION_RUNTIME_URL: print("Set TWITTER_CONNECTION_URL to run this sample.") return try: - await list_user_timeline() - await search_posts() + list_user_timeline() + search_posts() except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_typeform.py b/samples/sample_connector_usage/sample_connector_usage_typeform.py index 26b42d6..4f13e4d 100644 --- a/samples/sample_connector_usage/sample_connector_usage_typeform.py +++ b/samples/sample_connector_usage/sample_connector_usage_typeform.py @@ -1,9 +1,7 @@ -"""Typeform connector SDK sample.""" - -import asyncio +"""Typeform sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.typeform import TypeformClient @@ -12,20 +10,20 @@ CONNECTION_RUNTIME_URL = os.environ.get("TYPEFORM_CONNECTION_URL", "") -async def main() -> None: +def main() -> None: """List Typeform forms.""" if not CONNECTION_RUNTIME_URL: print("Set TYPEFORM_CONNECTION_URL to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with TypeformClient(CONNECTION_RUNTIME_URL, credential) as client: - forms = await client.list_forms_async() + with TypeformClient(CONNECTION_RUNTIME_URL, credential) as client: + forms = client.list_forms() print(f"Forms: {forms}") except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_universalprint.py b/samples/sample_connector_usage/sample_connector_usage_universalprint.py index 100b777..5d52939 100644 --- a/samples/sample_connector_usage/sample_connector_usage_universalprint.py +++ b/samples/sample_connector_usage/sample_connector_usage_universalprint.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Universal Print Connector SDK Sample +Universal Print sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Universal Print connector SDK. +This sample demonstrates how to use the Universal Print client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a Universal Print connection @@ -19,12 +19,10 @@ python sample_connector_usage_universalprint.py """ - -import asyncio import os from pathlib import Path -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.universalprint import UniversalprintClient @@ -36,15 +34,15 @@ ) -async def example_1_list_recent_shares(): +def example_1_list_recent_shares(): """Example 1: List recently used printer shares.""" print("\n=== Example 1: List Recent Printer Shares ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with UniversalprintClient(CONNECTION_RUNTIME_URL, credential) as client: + with UniversalprintClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.list_recent_shares_async() + result = client.list_recent_shares() shares = (result or {}).get("value", []) if isinstance(result, dict) else [] print(f"Found {len(shares)} recent printer share(s).") @@ -57,18 +55,18 @@ async def example_1_list_recent_shares(): print(f"Error: {ex}") -async def example_2_print_file(): +def example_2_print_file(): """Example 2: Print a PDF to a printer share.""" print("\n=== Example 2: Print File ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: pdf_file_path = Path( os.environ.get("UNIVERSALPRINT_PDF_PATH", "document.pdf") ) - async with UniversalprintClient(CONNECTION_RUNTIME_URL, credential) as client: + with UniversalprintClient(CONNECTION_RUNTIME_URL, credential) as client: try: - await client.print_file_async( + client.print_file( input=pdf_file_path.read_bytes(), printer="your-printer-share-id", file_name=pdf_file_path.name, @@ -85,7 +83,7 @@ async def example_2_print_file(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: UNIVERSALPRINT_CONNECTION_URL environment variable not set.") @@ -94,11 +92,11 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_list_recent_shares() - await example_2_print_file() + example_1_list_recent_shares() + example_2_print_file() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_waywedo.py b/samples/sample_connector_usage/sample_connector_usage_waywedo.py index 800942b..2b63431 100644 --- a/samples/sample_connector_usage/sample_connector_usage_waywedo.py +++ b/samples/sample_connector_usage/sample_connector_usage_waywedo.py @@ -1,9 +1,7 @@ -"""Way We Do connector SDK sample.""" - -import asyncio +"""Way We Do sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.waywedo import WaywedoClient @@ -12,20 +10,20 @@ CONNECTION_RUNTIME_URL = os.environ.get("WAYWEDO_CONNECTION_URL", "") -async def main() -> None: +def main() -> None: """Find Way We Do checklists.""" if not CONNECTION_RUNTIME_URL: print("Set WAYWEDO_CONNECTION_URL to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with WaywedoClient(CONNECTION_RUNTIME_URL, credential) as client: - checklists = await client.find_checklist_async() + with WaywedoClient(CONNECTION_RUNTIME_URL, credential) as client: + checklists = client.list_find_checklist() print(f"Checklists: {checklists}") except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_wdatp.py b/samples/sample_connector_usage/sample_connector_usage_wdatp.py index 5ce8043..99c1c26 100644 --- a/samples/sample_connector_usage/sample_connector_usage_wdatp.py +++ b/samples/sample_connector_usage/sample_connector_usage_wdatp.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Windows Defender ATP (Microsoft Defender for Endpoint) Connector SDK Sample +Windows Defender ATP (Microsoft Defender for Endpoint) sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Windows Defender ATP connector SDK +This sample demonstrates how to use the Windows Defender ATP client from the Azure Connectors Python SDK to interact with Microsoft Defender for Endpoint for security operations. Prerequisites: @@ -21,10 +21,8 @@ python sample_connector_usage_wdatp.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.wdatp import ( WdatpClient, @@ -40,15 +38,15 @@ ) -async def example_1_list_alerts(): +def example_1_list_alerts(): """Example 1: List recent security alerts.""" print("\n=== Example 1: List Security Alerts ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: + with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: try: - alerts = [item async for item in client.get_alerts_async( + alerts = [item for item in client.list_alerts( top=5, orderby="alertCreationTime desc" )] @@ -68,16 +66,16 @@ async def example_1_list_alerts(): print(f"Error: {ex}") -async def example_2_get_machines(): +def example_2_get_machines(): """Example 2: List machines in the organization.""" print("\n=== Example 2: List Machines ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: + with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: try: machines = [ - item async for item in client.get_machines_async(top=10) + item for item in client.list_machines(top=10) ] if machines: @@ -96,19 +94,19 @@ async def example_2_get_machines(): print(f"Error: {ex}") -async def example_3_advanced_hunting(): +def example_3_advanced_hunting(): """Example 3: Run an advanced hunting query.""" print("\n=== Example 3: Advanced Hunting Query ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: + with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Query for device information query = "DeviceInfo | take 5 | project DeviceName, OSPlatform, PublicIP" input_data = AdvancedHuntingInput(query=query) - result = await client.advanced_hunting_async(input=input_data) + result = client.advanced_hunting(input=input_data) if result and result.get("results"): print(f"Query returned {len(result['results'])} results:") @@ -126,7 +124,7 @@ async def example_3_advanced_hunting(): print(f"Error: {ex}") -async def example_4_update_alert(): +def example_4_update_alert(): """Example 4: Update an alert status.""" print("\n=== Example 4: Update Alert Status ===") @@ -137,9 +135,9 @@ async def example_4_update_alert(): print("Skipping this example.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: + with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: try: input_data = PatchAlertInput( status="InProgress", @@ -147,7 +145,7 @@ async def example_4_update_alert(): classification="TruePositive" ) - result = await client.patch_alert_async( + result = client.patch_alert( input=input_data, alert_id=alert_id ) @@ -162,7 +160,7 @@ async def example_4_update_alert(): print(f"Error: {ex}") -async def example_5_get_file_stats(): +def example_5_get_file_stats(): """Example 5: Get file statistics by SHA1 hash.""" print("\n=== Example 5: Get File Statistics ===") @@ -173,11 +171,11 @@ async def example_5_get_file_stats(): print("Skipping this example.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: + with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_file_stats_async(file_id=file_sha1) + result = client.get_file_stats(file_id=file_sha1) print(f"File statistics for {file_sha1}:") print(f" Global prevalence: {result.get('globallyPrevalence', 'N/A')}") @@ -190,15 +188,15 @@ async def example_5_get_file_stats(): print(f"Error: {ex}") -async def example_6_machine_actions(): +def example_6_machine_actions(): """Example 6: List recent machine actions.""" print("\n=== Example 6: List Machine Actions ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: + with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: try: - machine_actions = [item async for item in client.get_machine_actions_async( + machine_actions = [item for item in client.list_machine_actions( top=5, orderby="creationDateTimeUtc desc" )] @@ -218,16 +216,16 @@ async def example_6_machine_actions(): print(f"Error: {ex}") -async def example_7_investigations(): +def example_7_investigations(): """Example 7: List automated investigations.""" print("\n=== Example 7: List Investigations ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: + with WdatpClient(CONNECTION_RUNTIME_URL, credential) as client: try: investigations = [ - item async for item in client.get_investigations_async(top=5) + item for item in client.list_investigations(top=5) ] if investigations: @@ -245,7 +243,7 @@ async def example_7_investigations(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: WDATP_CONNECTION_URL environment variable not set.") @@ -258,18 +256,18 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") # Read operations - await example_1_list_alerts() - await example_2_get_machines() - await example_3_advanced_hunting() - await example_5_get_file_stats() - await example_6_machine_actions() - await example_7_investigations() + example_1_list_alerts() + example_2_get_machines() + example_3_advanced_hunting() + example_5_get_file_stats() + example_6_machine_actions() + example_7_investigations() # Update operations (requires specific IDs) - await example_4_update_alert() + example_4_update_alert() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_webex.py b/samples/sample_connector_usage/sample_connector_usage_webex.py index b7669fe..c918dc9 100644 --- a/samples/sample_connector_usage/sample_connector_usage_webex.py +++ b/samples/sample_connector_usage/sample_connector_usage_webex.py @@ -1,7 +1,7 @@ """ -Webex Connector SDK Sample +Webex sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Webex connector SDK. +This sample demonstrates how to use the Webex client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a Webex connection @@ -17,11 +17,9 @@ python sample_connector_usage_webex.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.webex import ( @@ -36,61 +34,61 @@ CONNECTION_RUNTIME_URL = os.environ.get("WEBEX_CONNECTION_URL", "") -async def example_1_send_message() -> None: +def example_1_send_message() -> None: """Example 1: Send a message to a space.""" print("\n=== Example 1: Send Message ===") - async with DefaultAzureCredential() as credential: - async with WebexClient(CONNECTION_RUNTIME_URL, credential) as client: - result = await client.send_message_async( + with DefaultAzureCredential() as credential: + with WebexClient(CONNECTION_RUNTIME_URL, credential) as client: + result = client.send_message( input=SendMessageInput( room_id="ROOM_ID", - text="Hello from the Webex connector SDK.", + text="Hello from the Webex client in the Azure Connectors Python SDK.", ), ) print(f"Send result: {result}") -async def example_2_get_spaces() -> None: +def example_2_get_spaces() -> None: """Example 2: List spaces.""" print("\n=== Example 2: Get Spaces ===") - async with DefaultAzureCredential() as credential: - async with WebexClient(CONNECTION_RUNTIME_URL, credential) as client: - spaces = await client.get_spaces_async() + with DefaultAzureCredential() as credential: + with WebexClient(CONNECTION_RUNTIME_URL, credential) as client: + spaces = client.list_spaces() print(f"Spaces: {spaces}") -async def example_3_create_space() -> None: +def example_3_create_space() -> None: """Example 3: Create a space.""" print("\n=== Example 3: Create Space ===") - async with DefaultAzureCredential() as credential: - async with WebexClient(CONNECTION_RUNTIME_URL, credential) as client: - space = await client.create_space_async( + with DefaultAzureCredential() as credential: + with WebexClient(CONNECTION_RUNTIME_URL, credential) as client: + space = client.create_space( input=CreateSpaceInput(title="My New Space"), ) print(f"Created space: {space}") -async def example_4_get_my_own_details() -> None: +def example_4_get_my_own_details() -> None: """Example 4: Get details about the authenticated user.""" print("\n=== Example 4: Get My Own Details ===") - async with DefaultAzureCredential() as credential: - async with WebexClient(CONNECTION_RUNTIME_URL, credential) as client: - me = await client.get_my_own_details_async() + with DefaultAzureCredential() as credential: + with WebexClient(CONNECTION_RUNTIME_URL, credential) as client: + me = client.get_my_own_details() print(f"My details: {me}") -async def main() -> None: +def main() -> None: """Run Webex connector examples.""" if not CONNECTION_RUNTIME_URL: print("Error: WEBEX_CONNECTION_URL environment variable not set.") print("Set it to your connection runtime URL from Azure Portal.") return - print("Webex Connector SDK - Sample Usage") + print("Webex sample usage for the Azure Connectors Python SDK") print("=" * 50) try: @@ -108,4 +106,4 @@ async def main() -> None: if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_wordonlinebusiness.py b/samples/sample_connector_usage/sample_connector_usage_wordonlinebusiness.py index 4f9f6fa..acd3ccf 100644 --- a/samples/sample_connector_usage/sample_connector_usage_wordonlinebusiness.py +++ b/samples/sample_connector_usage/sample_connector_usage_wordonlinebusiness.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Word Online (Business) Connector SDK Sample +Word Online (Business) sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Word Online (Business) connector SDK. +This sample demonstrates how to use the Word Online (Business) client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with Word Online (Business) connection @@ -20,10 +20,8 @@ python sample_connector_usage_wordonlinebusiness.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.wordonlinebusiness import ( WordonlinebusinessClient, @@ -42,7 +40,7 @@ FILE = os.environ.get("WORDONLINEBUSINESS_FILE", "") -async def example_1_populate_word_template(): +def example_1_populate_word_template(): """Example 1: Populate a Microsoft Word template. Reads a Microsoft Word template and fills template fields with dynamic values @@ -50,9 +48,9 @@ async def example_1_populate_word_template(): """ print("\n=== Example 1: Populate Word Template ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Create input with template field values # The additional_properties dict contains the template field mappings @@ -65,7 +63,7 @@ async def example_1_populate_word_template(): } ) - result = await client.create_file_item_async( + result = client.create_file_item( input=input_data, source=SOURCE, drive=DRIVE, @@ -80,16 +78,16 @@ async def example_1_populate_word_template(): print(f"Error: {ex}") -async def example_2_create_word_document(): +def example_2_create_word_document(): """Example 2: Create a Word document with content. Creates a new Microsoft Word file with the given content. """ print("\n=== Example 2: Create Word Document ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Create document content content = ContentBody( @@ -97,7 +95,7 @@ async def example_2_create_word_document(): "It can include multiple paragraphs and formatting." ) - result = await client.create_word_file_with_content_async( + result = client.create_word_file_with_content( input=content, file_name="MyDocument.docx" ) @@ -114,20 +112,20 @@ async def example_2_create_word_document(): print(f"Error: {ex}") -async def example_3_create_word_document_without_filename(): +def example_3_create_word_document_without_filename(): """Example 3: Create a Word document without specifying filename. Creates a new Microsoft Word file with auto-generated filename. """ print("\n=== Example 3: Create Word Document (Auto-named) ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: try: content = ContentBody(content="Auto-generated document content.") - result = await client.create_word_file_with_content_async(input=content) + result = client.create_word_file_with_content(input=content) if result: print(f"Document created: {result}") @@ -140,18 +138,18 @@ async def example_3_create_word_document_without_filename(): print(f"Error: {ex}") -async def example_4_convert_word_to_pdf(): +def example_4_convert_word_to_pdf(): """Example 4: Convert a Word document to PDF. Gets a PDF version of a selected Word file. """ print("\n=== Example 4: Convert Word to PDF ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_file_pdf_async( + result = client.get_file_pdf( source=SOURCE, drive=DRIVE, file=FILE @@ -165,18 +163,18 @@ async def example_4_convert_word_to_pdf(): print(f"Error: {ex}") -async def example_5_convert_with_sensitivity_labels(): +def example_5_convert_with_sensitivity_labels(): """Example 5: Convert Word to PDF with sensitivity label extraction. Converts a Word document to PDF while extracting sensitivity label metadata. """ print("\n=== Example 5: Convert with Sensitivity Labels ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: + with WordonlinebusinessClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_file_pdf_async( + result = client.get_file_pdf( source=SOURCE, drive=DRIVE, file=FILE, @@ -192,7 +190,7 @@ async def example_5_convert_with_sensitivity_labels(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: WORDONLINEBUSINESS_CONNECTION_URL environment variable not set.") @@ -205,14 +203,14 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_populate_word_template() - await example_2_create_word_document() - await example_3_create_word_document_without_filename() - await example_4_convert_word_to_pdf() - await example_5_convert_with_sensitivity_labels() + example_1_populate_word_template() + example_2_create_word_document() + example_3_create_word_document_without_filename() + example_4_convert_word_to_pdf() + example_5_convert_with_sensitivity_labels() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_wordpress.py b/samples/sample_connector_usage/sample_connector_usage_wordpress.py index 88e2928..0379474 100644 --- a/samples/sample_connector_usage/sample_connector_usage_wordpress.py +++ b/samples/sample_connector_usage/sample_connector_usage_wordpress.py @@ -1,9 +1,7 @@ -"""WordPress connector SDK sample.""" - -import asyncio +"""WordPress sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.wordpress import CreatePostModel, WordpressClient @@ -12,19 +10,19 @@ CONNECTION_RUNTIME_URL = os.environ.get("WORDPRESS_CONNECTION_URL", "") -async def list_sites() -> None: +def list_sites() -> None: """List WordPress sites available to the connection.""" - async with DefaultAzureCredential() as credential: - async with WordpressClient(CONNECTION_RUNTIME_URL, credential) as client: - sites = await client.list_sites_async() + with DefaultAzureCredential() as credential: + with WordpressClient(CONNECTION_RUNTIME_URL, credential) as client: + sites = client.list_sites() print(f"Sites: {sites}") -async def create_post() -> None: +def create_post() -> None: """Create a draft WordPress post.""" - async with DefaultAzureCredential() as credential: - async with WordpressClient(CONNECTION_RUNTIME_URL, credential) as client: - post = await client.create_async( + with DefaultAzureCredential() as credential: + with WordpressClient(CONNECTION_RUNTIME_URL, credential) as client: + post = client.create( input=CreatePostModel( title="Generated connector sample", content="Created with the Azure Connectors Python SDK.", @@ -35,18 +33,18 @@ async def create_post() -> None: print(f"Created post: {post}") -async def main() -> None: +def main() -> None: """Run WordPress connector examples.""" if not CONNECTION_RUNTIME_URL: print("Set WORDPRESS_CONNECTION_URL to run this sample.") return try: - await list_sites() - await create_post() + list_sites() + create_post() except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_yammer.py b/samples/sample_connector_usage/sample_connector_usage_yammer.py index 3ff626c..73f285f 100644 --- a/samples/sample_connector_usage/sample_connector_usage_yammer.py +++ b/samples/sample_connector_usage/sample_connector_usage_yammer.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Yammer (Viva Engage) Connector SDK Sample +Yammer (Viva Engage) sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Yammer connector SDK to interact with +This sample demonstrates how to use the Yammer client from the Azure Connectors Python SDK to interact with Viva Engage (formerly Yammer) networks, groups, messages, and users. Prerequisites: @@ -20,10 +20,8 @@ python sample_connector_usage_yammer.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.yammer import ( YammerClient, @@ -38,15 +36,15 @@ ) -async def example_1_get_networks(): +def example_1_get_networks(): """Example 1: Get all networks the user belongs to.""" print("\n=== Example 1: Get Networks ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: + with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: try: - networks = await client.get_networks_async() + networks = client.list_networks() if networks: print(f"Found {len(networks)} network(s):") @@ -61,16 +59,16 @@ async def example_1_get_networks(): print(f"Error: {ex}") -async def example_2_get_groups(): +def example_2_get_groups(): """Example 2: Get groups in the network.""" print("\n=== Example 2: Get Groups ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: + with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Get only groups the user belongs to - groups = await client.get_groups_async(mine=1) + groups = client.list_groups(mine=1) if groups: print(f"Found {len(groups)} group(s):") @@ -85,17 +83,17 @@ async def example_2_get_groups(): print(f"Error: {ex}") -async def example_3_get_messages(): +def example_3_get_messages(): """Example 3: Get messages from the network.""" print("\n=== Example 3: Get All Messages ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: + with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Get recent messages (limit to 10) messages = [ - item async for item in client.get_all_messages_async(limit=10) + item for item in client.list_all_messages(limit=10) ] if messages: @@ -112,16 +110,16 @@ async def example_3_get_messages(): print(f"Error: {ex}") -async def example_4_get_following_feed(): +def example_4_get_following_feed(): """Example 4: Get messages from the Following feed.""" print("\n=== Example 4: Get Following Feed ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: + with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: try: messages = [ - item async for item in client.get_messages_following_async( + item for item in client.list_messages_following( limit=5 ) ] @@ -141,13 +139,13 @@ async def example_4_get_following_feed(): print(f"Error: {ex}") -async def example_5_post_message(): +def example_5_post_message(): """Example 5: Post a message to All Company feed.""" print("\n=== Example 5: Post Message ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: + with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Create message request (group_id=0 posts to All Company) message = PostOperationRequest( @@ -156,7 +154,7 @@ async def example_5_post_message(): title="SDK Test Message" ) - result = await client.post_message_async(input=message) + result = client.post_message(input=message) if result: print("Message posted successfully!") @@ -171,17 +169,17 @@ async def example_5_post_message(): print(f"Error: {ex}") -async def example_6_get_user_details(): +def example_6_get_user_details(): """Example 6: Get user profile details.""" print("\n=== Example 6: Get User Details ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: + with YammerClient(CONNECTION_RUNTIME_URL, credential) as client: try: # Replace with an actual user ID user_id = 123456789 - user = await client.get_user_details_by_id_async(user_id=user_id) + user = client.get_user_details_by_id(user_id=user_id) if user: print("User details:") @@ -198,7 +196,7 @@ async def example_6_get_user_details(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: YAMMER_CONNECTION_URL environment variable not set.") @@ -207,16 +205,16 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_get_networks() - await example_2_get_groups() - await example_3_get_messages() - await example_4_get_following_feed() + example_1_get_networks() + example_2_get_groups() + example_3_get_messages() + example_4_get_following_feed() # Uncomment to test posting (be careful in production!) # await example_5_post_message() - await example_6_get_user_details() + example_6_get_user_details() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_zendesk.py b/samples/sample_connector_usage/sample_connector_usage_zendesk.py index c605279..93a9d98 100644 --- a/samples/sample_connector_usage/sample_connector_usage_zendesk.py +++ b/samples/sample_connector_usage/sample_connector_usage_zendesk.py @@ -1,9 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. """ -Zendesk Connector SDK Sample +Zendesk sample for the Azure Connectors Python SDK -This sample demonstrates how to use the Zendesk connector SDK. +This sample demonstrates how to use the Zendesk client from the Azure Connectors Python SDK. Prerequisites: 1. Azure subscription with a Zendesk connection @@ -19,11 +19,9 @@ python sample_connector_usage_zendesk.py """ - -import asyncio import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.zendesk import ( Item, @@ -38,15 +36,15 @@ ) -async def example_1_get_tables(): +def example_1_get_tables(): """Example 1: List the available Zendesk tables (object types).""" print("\n=== Example 1: Get Tables ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ZendeskClient(CONNECTION_RUNTIME_URL, credential) as client: + with ZendeskClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.get_tables_async() + result = client.list_tables() tables = (result or {}).get("value", []) if isinstance(result, dict) else [] print(f"Found {len(tables)} table(s).") @@ -59,15 +57,15 @@ async def example_1_get_tables(): print(f"Error: {ex}") -async def example_2_get_items(): +def example_2_get_items(): """Example 2: Retrieve items from a Zendesk table.""" print("\n=== Example 2: Get Items ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ZendeskClient(CONNECTION_RUNTIME_URL, credential) as client: + with ZendeskClient(CONNECTION_RUNTIME_URL, credential) as client: try: - items = [item async for item in client.get_items_async( + items = [item for item in client.list_items( table="tickets", top=10, )] @@ -80,13 +78,13 @@ async def example_2_get_items(): print(f"Error: {ex}") -async def example_3_create_item(): +def example_3_create_item(): """Example 3: Create a new item in a Zendesk table.""" print("\n=== Example 3: Create Item ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ZendeskClient(CONNECTION_RUNTIME_URL, credential) as client: + with ZendeskClient(CONNECTION_RUNTIME_URL, credential) as client: try: new_item = Item( dynamic_properties={ @@ -95,7 +93,7 @@ async def example_3_create_item(): }, ) - result = await client.post_item_async(input=new_item, table="tickets") + result = client.post_item(input=new_item, table="tickets") print(f"Created item: {result}") except ConnectorException as ex: @@ -104,15 +102,15 @@ async def example_3_create_item(): print(f"Error: {ex}") -async def example_4_search_articles(): +def example_4_search_articles(): """Example 4: Search Zendesk Help Center articles.""" print("\n=== Example 4: Search Articles ===") - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: - async with ZendeskClient(CONNECTION_RUNTIME_URL, credential) as client: + with ZendeskClient(CONNECTION_RUNTIME_URL, credential) as client: try: - result = await client.search_articles_async( + result = client.list_search_articles( query="password reset", locale="en-us", ) @@ -126,7 +124,7 @@ async def example_4_search_articles(): print(f"Error: {ex}") -async def main(): +def main(): """Run all examples.""" if not CONNECTION_RUNTIME_URL: print("Error: ZENDESK_CONNECTION_URL environment variable not set.") @@ -135,13 +133,13 @@ async def main(): print(f"Using connection URL: {CONNECTION_RUNTIME_URL[:50]}...") - await example_1_get_tables() - await example_2_get_items() - await example_3_create_item() - await example_4_search_articles() + example_1_get_tables() + example_2_get_items() + example_3_create_item() + example_4_search_articles() print("\n=== All examples completed ===") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_zeptomail.py b/samples/sample_connector_usage/sample_connector_usage_zeptomail.py index 9f81cab..5c51e9c 100644 --- a/samples/sample_connector_usage/sample_connector_usage_zeptomail.py +++ b/samples/sample_connector_usage/sample_connector_usage_zeptomail.py @@ -1,9 +1,7 @@ -"""Zoho ZeptoMail connector SDK sample.""" - -import asyncio +"""Zoho ZeptoMail sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.zeptomail import ZeptomailClient @@ -12,23 +10,23 @@ CONNECTION_RUNTIME_URL = os.environ.get("ZEPTOMAIL_CONNECTION_URL", "") -async def main() -> None: +def main() -> None: """List the configured ZeptoMail mail agents.""" if not CONNECTION_RUNTIME_URL: print("Set ZEPTOMAIL_CONNECTION_URL to run this sample.") return - async with DefaultAzureCredential() as credential: + with DefaultAzureCredential() as credential: try: - async with ZeptomailClient( + with ZeptomailClient( CONNECTION_RUNTIME_URL, credential, ) as client: - mail_agents = await client.get_mail_agent_async() + mail_agents = client.get_mail_agent() print(f"Mail agents: {mail_agents}") except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/samples/sample_connector_usage/sample_connector_usage_zohosign.py b/samples/sample_connector_usage/sample_connector_usage_zohosign.py index 5179497..3aa68aa 100644 --- a/samples/sample_connector_usage/sample_connector_usage_zohosign.py +++ b/samples/sample_connector_usage/sample_connector_usage_zohosign.py @@ -1,11 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. -"""Zoho Sign connector SDK sample.""" - -import asyncio +"""Zoho Sign sample for the Azure Connectors Python SDK.""" import os -from azure.identity.aio import DefaultAzureCredential +from azure.identity import DefaultAzureCredential from azure.connectors import ConnectorException from azure.connectors.zohosign import ZohosignClient @@ -15,38 +13,38 @@ REQUEST_ID = os.environ.get("ZOHOSIGN_REQUEST_ID", "") -async def list_templates() -> None: +def list_templates() -> None: """List available Zoho Sign templates.""" - async with DefaultAzureCredential() as credential: - async with ZohosignClient(CONNECTION_RUNTIME_URL, credential) as client: - templates = await client.get_templates_async() + with DefaultAzureCredential() as credential: + with ZohosignClient(CONNECTION_RUNTIME_URL, credential) as client: + templates = client.list_templates() print(f"Templates: {templates}") -async def get_document() -> None: +def get_document() -> None: """Get a Zoho Sign document request.""" if not REQUEST_ID: print("Set ZOHOSIGN_REQUEST_ID to retrieve a document request.") return - async with DefaultAzureCredential() as credential: - async with ZohosignClient(CONNECTION_RUNTIME_URL, credential) as client: - document = await client.get_document_async(request_id=int(REQUEST_ID)) + with DefaultAzureCredential() as credential: + with ZohosignClient(CONNECTION_RUNTIME_URL, credential) as client: + document = client.get_document(request_id=int(REQUEST_ID)) print(f"Document: {document}") -async def main() -> None: +def main() -> None: """Run the Zoho Sign examples.""" if not CONNECTION_RUNTIME_URL: print("Error: ZOHOSIGN_CONNECTION_URL environment variable not set.") return try: - await list_templates() - await get_document() + list_templates() + get_document() except ConnectorException as ex: print(f"Connector error: {ex}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/scripts/generate_api_reference.py b/scripts/generate_api_reference.py index 0c45f93..23d1d41 100644 --- a/scripts/generate_api_reference.py +++ b/scripts/generate_api_reference.py @@ -58,7 +58,7 @@ def _defined_public_names(source_path: Path) -> list[str]: def _module_title(source_path: Path, names: list[str]) -> str: """Create a readable navigation title for a source module.""" client_names = [name for name in names if name.endswith("Client")] - if source_path.parent == PACKAGE_ROOT and len(client_names) == 1: + if source_path.parent in {PACKAGE_ROOT, PACKAGE_ROOT / "aio"} and len(client_names) == 1: return client_names[0] return source_path.stem.replace("_", " ").title() @@ -107,12 +107,28 @@ def _generate_reference() -> None: navigation = mkdocs_gen_files.Nav() navigation["Home"] = "index.md" navigation[("Guides", "Connection setup")] = "connection-setup.md" + navigation[("Guides", "Long-running operations")] = "long-running-operations.md" + navigation[("Guides", "Sync/aio migration")] = "migration-sync-aio.md" navigation[("Guides", "SDK-type bindings")] = "sdk-type-bindings.md" + navigation[("Design", "Azure SDK guidelines")] = "azure-sdk-guidelines.md" + navigation[("Design", "Generated contract")] = "generated-contract.md" navigation[("API reference",)] = "api/index.md" sections = ( ("Core SDK", "core", PACKAGE_ROOT / "sdk", "azure.connectors.sdk"), - ("Connectors", "connectors", PACKAGE_ROOT, "azure.connectors"), + ( + "Async core SDK", + "core-aio", + PACKAGE_ROOT / "sdk" / "aio", + "azure.connectors.sdk.aio", + ), + ("Sync connectors", "connectors", PACKAGE_ROOT, "azure.connectors"), + ( + "Async connectors", + "connectors-aio", + PACKAGE_ROOT / "aio", + "azure.connectors.aio", + ), ) for navigation_title, section, directory, package_name in sections: diff --git a/scripts/validate_api_docs.py b/scripts/validate_api_docs.py index 697e4b0..2638157 100644 --- a/scripts/validate_api_docs.py +++ b/scripts/validate_api_docs.py @@ -55,7 +55,9 @@ def validate_api_docs(site_directory: Path) -> list[str]: sections = ( ("core", PACKAGE_ROOT / "sdk"), + ("core-aio", PACKAGE_ROOT / "sdk" / "aio"), ("connectors", PACKAGE_ROOT), + ("connectors-aio", PACKAGE_ROOT / "aio"), ) for section, source_directory in sections: @@ -89,10 +91,14 @@ def main() -> int: return 1 connector_count = len(_source_module_names(PACKAGE_ROOT)) + aio_connector_count = len(_source_module_names(PACKAGE_ROOT / "aio")) core_count = len(_source_module_names(PACKAGE_ROOT / "sdk")) + aio_core_count = len(_source_module_names(PACKAGE_ROOT / "sdk" / "aio")) print( "API documentation validation passed: " - f"{core_count} core modules and {connector_count} connector modules.", + f"{core_count} sync core modules, {aio_core_count} aio core modules, " + f"{connector_count} sync connector modules, and " + f"{aio_connector_count} aio connector modules.", ) return 0 diff --git a/scripts/validate_connector_samples.py b/scripts/validate_connector_samples.py index 98b1bb0..0c6a11c 100644 --- a/scripts/validate_connector_samples.py +++ b/scripts/validate_connector_samples.py @@ -17,6 +17,9 @@ from types import ModuleType, UnionType from typing import Any, Literal, Union, get_args, get_origin, get_type_hints +from azure.core.async_paging import AsyncItemPaged +from azure.core.paging import ItemPaged + @dataclass(frozen=True) class ValidationIssue: @@ -37,12 +40,23 @@ def __init__(self, path: Path, modules: dict[str, ModuleType]) -> None: self.imported_symbols: dict[str, Any] = {} self.client_variables: dict[str, type[Any]] = {} self.variable_types: dict[str, type[Any]] = {} + self.credential_modes: dict[str, str] = {} + self.scoped_sync_credentials: set[int] = set() self.scoped_async_credentials: set[int] = set() + self.awaited_calls: set[int] = set() self.issues: list[ValidationIssue] = [] def visit_ImportFrom(self, node: ast.ImportFrom) -> None: """Resolve imports from concrete connector modules.""" module_name = node.module or "" + if module_name in {"azure.identity", "azure.identity.aio"}: + mode = "async" if module_name.endswith(".aio") else "sync" + for imported_name in node.names: + if imported_name.name == "DefaultAzureCredential": + local_name = imported_name.asname or imported_name.name + self.credential_modes[local_name] = mode + return + if not module_name.startswith("azure.connectors"): return @@ -139,13 +153,40 @@ def visit_AsyncWith(self, node: ast.AsyncWith) -> None: if ( isinstance(item.context_expr, ast.Call) and isinstance(item.context_expr.func, ast.Name) - and item.context_expr.func.id == "DefaultAzureCredential" + and self.credential_modes.get(item.context_expr.func.id) == "async" ): self.scoped_async_credentials.add(id(item.context_expr)) client_type = self._client_type_from_expression(item.context_expr) - if client_type is not None and isinstance(item.optional_vars, ast.Name): - self.client_variables[item.optional_vars.id] = client_type + if client_type is not None: + if not self._is_async_client(client_type): + self._add_issue( + item.context_expr, + "synchronous connector clients must use a context manager", + ) + elif isinstance(item.optional_vars, ast.Name): + self.client_variables[item.optional_vars.id] = client_type + self.generic_visit(node) + + def visit_With(self, node: ast.With) -> None: + """Track generated clients introduced by synchronous context managers.""" + for item in node.items: + if ( + isinstance(item.context_expr, ast.Call) + and isinstance(item.context_expr.func, ast.Name) + and self.credential_modes.get(item.context_expr.func.id) == "sync" + ): + self.scoped_sync_credentials.add(id(item.context_expr)) + + client_type = self._client_type_from_expression(item.context_expr) + if client_type is not None: + if self._is_async_client(client_type): + self._add_issue( + item.context_expr, + "asynchronous connector clients must use an async context manager", + ) + elif isinstance(item.optional_vars, ast.Name): + self.client_variables[item.optional_vars.id] = client_type self.generic_visit(node) def visit_ListComp(self, node: ast.ListComp) -> None: @@ -172,6 +213,10 @@ def _visit_comprehension( client_variables = self.client_variables.copy() try: for generator in node.generators: + self._validate_pageable_iteration( + generator.iter, + is_async=bool(generator.is_async), + ) self.visit(generator.iter) for target in ast.walk(generator.target): if isinstance(target, ast.Name) and isinstance(target.ctx, ast.Store): @@ -193,10 +238,26 @@ def visit_Await(self, node: ast.Await) -> None: """Reject awaiting a generated pageable operation instead of iterating it.""" call = node.value if isinstance(call, ast.Call) and isinstance(call.func, ast.Attribute): + self.awaited_calls.add(id(call)) client_type = self._client_type_for_receiver(call.func.value) method = getattr(client_type, call.func.attr, None) - if inspect.isasyncgenfunction(method): + pageable_type = self._get_pageable_type(method) + if pageable_type is AsyncItemPaged: self._add_issue(node, f"'{call.func.attr}' must be consumed with async for") + elif pageable_type is ItemPaged: + self._add_issue(node, f"'{call.func.attr}' must be consumed with for") + elif method is not None and not inspect.iscoroutinefunction(method): + self._add_issue(node, f"synchronous method '{call.func.attr}' cannot be awaited") + self.generic_visit(node) + + def visit_AsyncFor(self, node: ast.AsyncFor) -> None: + """Require asynchronous iteration only for asynchronous pagers.""" + self._validate_pageable_iteration(node.iter, is_async=True) + self.generic_visit(node) + + def visit_For(self, node: ast.For) -> None: + """Require synchronous iteration only for synchronous pagers.""" + self._validate_pageable_iteration(node.iter, is_async=False) self.generic_visit(node) def visit_BoolOp(self, node: ast.BoolOp) -> None: @@ -211,13 +272,25 @@ def visit_Call(self, node: ast.Call) -> None: """Validate generated model construction and client method calls.""" if ( isinstance(node.func, ast.Name) - and node.func.id == "DefaultAzureCredential" - and id(node) not in self.scoped_async_credentials + and node.func.id in self.credential_modes ): - self._add_issue( - node, - "DefaultAzureCredential must use an async context manager", - ) + credential_mode = self.credential_modes[node.func.id] + if ( + credential_mode == "async" + and id(node) not in self.scoped_async_credentials + ): + self._add_issue( + node, + "asynchronous DefaultAzureCredential must use an async context manager", + ) + elif ( + credential_mode == "sync" + and id(node) not in self.scoped_sync_credentials + ): + self._add_issue( + node, + "synchronous DefaultAzureCredential must use a context manager", + ) if isinstance(node.func, ast.Name): target = self.imported_symbols.get(node.func.id) @@ -235,6 +308,14 @@ def visit_Call(self, node: ast.Call) -> None: ) else: self._validate_signature(node, method, include_instance=True) + if ( + inspect.iscoroutinefunction(method) + and id(node) not in self.awaited_calls + ): + self._add_issue( + node, + f"asynchronous method '{method_name}' must be awaited", + ) else: receiver_type = self._infer_static_type(node.func.value) if receiver_type in {list, dict, set, tuple} and not hasattr( @@ -262,6 +343,58 @@ def _client_type_for_receiver(self, node: ast.AST) -> type[Any] | None: return self.client_variables.get(node.id) return self._client_type_from_expression(node) + @staticmethod + def _is_async_client(client_type: type[Any]) -> bool: + """Return whether a generated client belongs to the aio package.""" + return client_type.__module__.startswith("azure.connectors.aio.") + + @staticmethod + def _get_pageable_type(method: Any) -> type[Any] | None: + """Resolve the Azure Core pager type returned by a generated method.""" + if method is None: + return None + + try: + method_module = importlib.import_module(method.__module__) + return_annotation = get_type_hints( + method, + globalns=vars(method_module), + ).get("return") + except (NameError, TypeError): + return_annotation = inspect.signature(method).return_annotation + + return_origin = get_origin(return_annotation) or return_annotation + if return_origin in {ItemPaged, AsyncItemPaged}: + return return_origin + return None + + def _validate_pageable_iteration( + self, + expression: ast.AST, + *, + is_async: bool, + ) -> None: + """Validate that a generated pager uses its matching iteration mode.""" + if not isinstance(expression, ast.Call) or not isinstance( + expression.func, + ast.Attribute, + ): + return + + client_type = self._client_type_for_receiver(expression.func.value) + method = getattr(client_type, expression.func.attr, None) + pageable_type = self._get_pageable_type(method) + if pageable_type is ItemPaged and is_async: + self._add_issue( + expression, + f"'{expression.func.attr}' must be consumed with for", + ) + elif pageable_type is AsyncItemPaged and not is_async: + self._add_issue( + expression, + f"'{expression.func.attr}' must be consumed with async for", + ) + def _infer_static_type(self, node: ast.AST) -> type[Any] | None: """Infer the type of a literal, simple name, environment value, or cast.""" if isinstance(node, ast.Name): @@ -498,14 +631,26 @@ def _type_matches_annotation(value_type: type[Any], annotation: Any) -> bool: def load_connector_modules(source_root: Path) -> dict[str, ModuleType]: """Import connector modules from the checked-out source tree.""" connector_package = importlib.import_module("azure.connectors") + aio_package = importlib.import_module("azure.connectors.aio") modules: dict[str, ModuleType] = { "azure.connectors": connector_package, + "azure.connectors.aio": aio_package, } - for module_path in sorted((source_root / "azure" / "connectors").glob("*.py")): + connector_root = source_root / "azure" / "connectors" + module_paths = [ + *connector_root.glob("*.py"), + *(connector_root / "aio").glob("*.py"), + ] + for module_path in sorted(module_paths): if module_path.name == "__init__.py": continue - module_name = f"azure.connectors.{module_path.stem}" + package_name = ( + "azure.connectors.aio" + if module_path.parent.name == "aio" + else "azure.connectors" + ) + module_name = f"{package_name}.{module_path.stem}" module = importlib.import_module(module_name) resolved_path = Path(module.__file__ or "").resolve() if resolved_path != module_path.resolve(): @@ -522,8 +667,12 @@ def validate_samples(repo_root: Path) -> tuple[list[Path], list[ValidationIssue] source_root = repo_root / "src" sys.path.insert(0, str(source_root)) modules = load_connector_modules(source_root) + sample_root = repo_root / "samples" / "sample_connector_usage" sample_paths = sorted( - (repo_root / "samples" / "sample_connector_usage").glob("*.py") + [ + *sample_root.glob("sample_connector_usage_*.py"), + *(sample_root / "aio").glob("sample_connector_usage_*.py"), + ] ) issues: list[ValidationIssue] = [] diff --git a/src/azure/connectors/__init__.py b/src/azure/connectors/__init__.py index 7edc931..a370097 100644 --- a/src/azure/connectors/__init__.py +++ b/src/azure/connectors/__init__.py @@ -1,586 +1,45 @@ # Copyright (c) Microsoft Corporation. All rights reserved. -""" -Azure Connectors SDK for Python. +"""Shared runtime contracts for the Azure Connectors SDK for Python.""" -This package provides infrastructure for calling Azure Connectors -from Python applications, including authentication, HTTP clients, and -strongly-typed generated connector clients. -""" +from importlib import import_module +from typing import Any +from ._client_registry import CLIENT_REGISTRY from .sdk.client_base import ConnectorClientBase from .sdk.exceptions import ConnectorException from .sdk.http_client import ConnectorHttpClient, ConnectorResponse from .sdk.response import ConnectorResponseHook, ConnectorResponseSnapshot -from .sdk.trigger_payload import TriggerCallbackPayload, TriggerCallbackBody +from .sdk.trigger_payload import TriggerCallbackBody, TriggerCallbackPayload -# Generated connector clients — some may have import errors from incomplete -# code generation (e.g., undefined type references). Wrap each import so -# a single broken connector doesn't prevent the SDK core from loading. -# See: https://github.com/Azure/connectors-python-sdk/issues/13 -try: - from .arm import ArmClient -except (ImportError, NameError): - ArmClient = None # type: ignore[assignment,misc] -try: - from .azureautomation import AzureautomationClient -except (ImportError, NameError): - AzureautomationClient = None # type: ignore[assignment,misc] -try: - from .azuredatafactory import AzuredatafactoryClient -except (ImportError, NameError): - AzuredatafactoryClient = None # type: ignore[assignment,misc] -try: - from .azuredigitaltwins import AzuredigitaltwinsClient -except (ImportError, NameError): - AzuredigitaltwinsClient = None # type: ignore[assignment,misc] -try: - from .kusto import KustoClient -except (ImportError, NameError): - KustoClient = None # type: ignore[assignment,misc] -try: - from .office365 import Office365Client -except (ImportError, NameError): - Office365Client = None # type: ignore[assignment,misc] -try: - from .sharepointonline import SharepointonlineClient -except (ImportError, NameError): - SharepointonlineClient = None # type: ignore[assignment,misc] -try: - from .teams import TeamsClient -except (ImportError, NameError): - TeamsClient = None # type: ignore[assignment,misc] -try: - from .msgraphgroupsanduser import MsgraphgroupsanduserClient -except (ImportError, NameError): - MsgraphgroupsanduserClient = None # type: ignore[assignment,misc] -try: - from .office365users import Office365usersClient -except (ImportError, NameError): - Office365usersClient = None # type: ignore[assignment,misc] -try: - from .office365groups import Office365groupsClient -except (ImportError, NameError): - Office365groupsClient = None # type: ignore[assignment,misc] -try: - from .office365groupsmail import Office365groupsmailClient -except (ImportError, NameError): - Office365groupsmailClient = None # type: ignore[assignment,misc] -try: - from .azureblob import AzureblobClient -except (ImportError, NameError): - AzureblobClient = None # type: ignore[assignment,misc] -try: - from .box import BoxClient -except (ImportError, NameError): - BoxClient = None # type: ignore[assignment,misc] -try: - from .dropbox import DropboxClient -except (ImportError, NameError): - DropboxClient = None # type: ignore[assignment,misc] -try: - from .mq import MqClient -except (ImportError, NameError): - MqClient = None # type: ignore[assignment,misc] -try: - from .onedrive import OnedriveClient -except (ImportError, NameError): - OnedriveClient = None # type: ignore[assignment,misc] -try: - from .onedriveforbusiness import OnedriveforbusinessClient -except (ImportError, NameError): - OnedriveforbusinessClient = None # type: ignore[assignment,misc] -try: - from .onenote import OnenoteClient -except (ImportError, NameError): - OnenoteClient = None # type: ignore[assignment,misc] -try: - from .planner import PlannerClient -except (ImportError, NameError): - PlannerClient = None # type: ignore[assignment,misc] -try: - from .azuread import AzureadClient -except (ImportError, NameError): - AzureadClient = None # type: ignore[assignment,misc] -try: - from .smtp import SmtpClient -except (ImportError, NameError): - SmtpClient = None # type: ignore[assignment,misc] -try: - from .excelonlinebusiness import ExcelonlinebusinessClient -except (ImportError, NameError): - ExcelonlinebusinessClient = None # type: ignore[assignment,misc] -try: - from .excelonline import ExcelonlineClient -except (ImportError, NameError): - ExcelonlineClient = None # type: ignore[assignment,misc] -try: - from .azurequeues import AzurequeuesClient -except (ImportError, NameError): - AzurequeuesClient = None # type: ignore[assignment,misc] -try: - from .azuretables import AzuretablesClient -except (ImportError, NameError): - AzuretablesClient = None # type: ignore[assignment,misc] -try: - from .azurevm import AzurevmClient -except (ImportError, NameError): - AzurevmClient = None # type: ignore[assignment,misc] -try: - from .documentdb import DocumentdbClient -except (ImportError, NameError): - DocumentdbClient = None # type: ignore[assignment,misc] -try: - from .eventhubs import EventhubsClient -except (ImportError, NameError): - EventhubsClient = None # type: ignore[assignment,misc] -try: - from .ftp import FtpClient -except (ImportError, NameError): - FtpClient = None # type: ignore[assignment,misc] -try: - from .keyvault import KeyvaultClient -except (ImportError, NameError): - KeyvaultClient = None # type: ignore[assignment,misc] -try: - from .microsoftbookings import MicrosoftbookingsClient -except (ImportError, NameError): - MicrosoftbookingsClient = None # type: ignore[assignment,misc] -try: - from .outlook import OutlookClient -except (ImportError, NameError): - OutlookClient = None # type: ignore[assignment,misc] -try: - from .commondataservice import CommondataserviceClient -except (ImportError, NameError): - CommondataserviceClient = None # type: ignore[assignment,misc] -try: - from .servicebus import ServicebusClient -except (ImportError, NameError): - ServicebusClient = None # type: ignore[assignment,misc] -try: - from .wdatp import WdatpClient -except (ImportError, NameError): - WdatpClient = None # type: ignore[assignment,misc] -try: - from .wordonlinebusiness import WordonlinebusinessClient -except (ImportError, NameError): - WordonlinebusinessClient = None # type: ignore[assignment,misc] -try: - from .yammer import YammerClient -except (ImportError, NameError): - YammerClient = None # type: ignore[assignment,misc] -try: - from .azuremonitorlogs import AzuremonitorlogsClient -except (ImportError, NameError): - AzuremonitorlogsClient = None # type: ignore[assignment,misc] +__version__ = "0.5.0b1" -try: - from .docusign import DocusignClient -except (ImportError, NameError): - DocusignClient = None # type: ignore[assignment,misc] -try: - from .github import GithubClient -except (ImportError, NameError): - GithubClient = None # type: ignore[assignment,misc] +def __getattr__(name: str) -> Any: + """Load a generated connector client when requested from the package root.""" + module_name = CLIENT_REGISTRY.get(name) + if module_name is None: + raise AttributeError(f"Module '{__name__}' has no attribute '{name}'.") -try: - from .googlecalendar import GooglecalendarClient -except (ImportError, NameError): - GooglecalendarClient = None # type: ignore[assignment,misc] + client_type = getattr(import_module(f".{module_name}", __name__), name) + globals()[name] = client_type + return client_type -try: - from .googletasks import GoogletasksClient -except (ImportError, NameError): - GoogletasksClient = None # type: ignore[assignment,misc] -try: - from .googledrive import GoogledriveClient -except (ImportError, NameError): - GoogledriveClient = None # type: ignore[assignment,misc] +def __dir__() -> list[str]: + """List core exports and lazily available connector clients.""" + return sorted(set(globals()) | CLIENT_REGISTRY.keys()) -try: - from .jira import JiraClient -except (ImportError, NameError): - JiraClient = None # type: ignore[assignment,misc] - -try: - from .microsoftforms import MicrosoftformsClient -except (ImportError, NameError): - MicrosoftformsClient = None # type: ignore[assignment,misc] - -try: - from .powerbi import PowerbiClient -except (ImportError, NameError): - PowerbiClient = None # type: ignore[assignment,misc] - -try: - from .rss import RssClient -except (ImportError, NameError): - RssClient = None # type: ignore[assignment,misc] - -try: - from .salesforce import SalesforceClient -except (ImportError, NameError): - SalesforceClient = None # type: ignore[assignment,misc] - -try: - from .shifts import ShiftsClient -except (ImportError, NameError): - ShiftsClient = None # type: ignore[assignment,misc] - -try: - from .slack import SlackClient -except (ImportError, NameError): - SlackClient = None # type: ignore[assignment,misc] - -try: - from .todo import TodoClient -except (ImportError, NameError): - TodoClient = None # type: ignore[assignment,misc] - -try: - from .insightly import InsightlyClient -except (ImportError, NameError): - InsightlyClient = None # type: ignore[assignment,misc] - -try: - from .infusionsoft import InfusionsoftClient -except (ImportError, NameError): - InfusionsoftClient = None # type: ignore[assignment,misc] - -try: - from .freshservice import FreshserviceClient -except (ImportError, NameError): - FreshserviceClient = None # type: ignore[assignment,misc] - -try: - from .monday import MondayClient -except (ImportError, NameError): - MondayClient = None # type: ignore[assignment,misc] - -try: - from .projectplace import ProjectplaceClient -except (ImportError, NameError): - ProjectplaceClient = None # type: ignore[assignment,misc] - -try: - from .mailchimp import MailchimpClient -except (ImportError, NameError): - MailchimpClient = None # type: ignore[assignment,misc] - -try: - from .sendgrid import SendgridClient -except (ImportError, NameError): - SendgridClient = None # type: ignore[assignment,misc] - -try: - from .webex import WebexClient -except (ImportError, NameError): - WebexClient = None # type: ignore[assignment,misc] -try: - from .campfire import CampfireClient -except (ImportError, NameError): - CampfireClient = None # type: ignore[assignment,misc] -try: - from .clicksendsms import ClicksendsmsClient -except (ImportError, NameError): - ClicksendsmsClient = None # type: ignore[assignment,misc] -try: - from .textrequest import TextrequestClient -except (ImportError, NameError): - TextrequestClient = None # type: ignore[assignment,misc] - -try: - from .twitter import TwitterClient -except (ImportError, NameError): - TwitterClient = None # type: ignore[assignment,misc] - -try: - from .wordpress import WordpressClient -except (ImportError, NameError): - WordpressClient = None # type: ignore[assignment,misc] - -try: - from .plivo import PlivoClient -except (ImportError, NameError): - PlivoClient = None # type: ignore[assignment,misc] - -try: - from .revai import RevaiClient -except (ImportError, NameError): - RevaiClient = None # type: ignore[assignment,misc] - -try: - from .starmind import StarmindClient -except (ImportError, NameError): - StarmindClient = None # type: ignore[assignment,misc] - -try: - from .tallyfy import TallyfyClient -except (ImportError, NameError): - TallyfyClient = None # type: ignore[assignment,misc] - -try: - from .universalprint import UniversalprintClient -except (ImportError, NameError): - UniversalprintClient = None # type: ignore[assignment,misc] - -try: - from .azureeventgrid import AzureeventgridClient -except (ImportError, NameError): - AzureeventgridClient = None # type: ignore[assignment,misc] - -try: - from .azureiotcentral import AzureiotcentralClient -except (ImportError, NameError): - AzureiotcentralClient = None # type: ignore[assignment,misc] - -try: - from .cloudmersiveconvert import CloudmersiveconvertClient -except (ImportError, NameError): - CloudmersiveconvertClient = None # type: ignore[assignment,misc] - -try: - from .dynamicsax import DynamicsaxClient -except (ImportError, NameError): - DynamicsaxClient = None # type: ignore[assignment,misc] - -try: - from .pdfco import PdfcoClient -except (ImportError, NameError): - PdfcoClient = None # type: ignore[assignment,misc] - -try: - from .plumsail import PlumsailClient -except (ImportError, NameError): - PlumsailClient = None # type: ignore[assignment,misc] - -try: - from .sql import SqlClient -except (ImportError, NameError): - SqlClient = None # type: ignore[assignment,misc] - -try: - from .zendesk import ZendeskClient -except (ImportError, NameError): - ZendeskClient = None # type: ignore[assignment,misc] - -try: - from .pipedrive import PipedriveClient -except (ImportError, NameError): - PipedriveClient = None # type: ignore[assignment,misc] - -try: - from .trello import TrelloClient -except (ImportError, NameError): - TrelloClient = None # type: ignore[assignment,misc] - -try: - from .docuware import DocuwareClient -except (ImportError, NameError): - DocuwareClient = None # type: ignore[assignment,misc] - -try: - from .signinghub import SigninghubClient -except (ImportError, NameError): - SigninghubClient = None # type: ignore[assignment,misc] - -try: - from .zohosign import ZohosignClient -except (ImportError, NameError): - ZohosignClient = None # type: ignore[assignment,misc] - -try: - from .zeptomail import ZeptomailClient -except (ImportError, NameError): - ZeptomailClient = None # type: ignore[assignment,misc] - -try: - from .eventbrite import EventbriteClient -except (ImportError, NameError): - EventbriteClient = None # type: ignore[assignment,misc] - -try: - from .formstackforms import FormstackformsClient -except (ImportError, NameError): - FormstackformsClient = None # type: ignore[assignment,misc] - -try: - from .typeform import TypeformClient -except (ImportError, NameError): - TypeformClient = None # type: ignore[assignment,misc] - -try: - from .ticketmaster import TicketmasterClient -except (ImportError, NameError): - TicketmasterClient = None # type: ignore[assignment,misc] - -try: - from .seismicplanner import SeismicplannerClient -except (ImportError, NameError): - SeismicplannerClient = None # type: ignore[assignment,misc] - -try: - from .waywedo import WaywedoClient -except (ImportError, NameError): - WaywedoClient = None # type: ignore[assignment,misc] - -try: - from .meetingroommap import MeetingroommapClient -except (ImportError, NameError): - MeetingroommapClient = None # type: ignore[assignment,misc] - -try: - from .starrezrestv1 import Starrezrestv1Client -except (ImportError, NameError): - Starrezrestv1Client = None # type: ignore[assignment,misc] - -try: - from .replicon import RepliconClient -except (ImportError, NameError): - RepliconClient = None # type: ignore[assignment,misc] - -try: - from .etsy import EtsyClient -except (ImportError, NameError): - EtsyClient = None # type: ignore[assignment,misc] - -try: - from .elfsquaddata import ElfsquaddataClient -except (ImportError, NameError): - ElfsquaddataClient = None # type: ignore[assignment,misc] - -try: - from .impexium import ImpexiumClient -except (ImportError, NameError): - ImpexiumClient = None # type: ignore[assignment,misc] - -try: - from .jedoxodatahub import JedoxodatahubClient -except (ImportError, NameError): - JedoxodatahubClient = None # type: ignore[assignment,misc] - -try: - from .orderful import OrderfulClient -except (ImportError, NameError): - OrderfulClient = None # type: ignore[assignment,misc] - -try: - from .cloudconvert import CloudconvertClient -except (ImportError, NameError): - CloudconvertClient = None # type: ignore[assignment,misc] - -__version__ = '0.5.0b1' __all__ = [ - 'ConnectorClientBase', - 'ConnectorException', - 'ConnectorHttpClient', - 'ConnectorResponse', - 'ConnectorResponseHook', - 'ConnectorResponseSnapshot', - 'TriggerCallbackPayload', - 'TriggerCallbackBody', - 'ArmClient', - 'AzureautomationClient', - 'AzuredatafactoryClient', - 'AzuredigitaltwinsClient', - 'KustoClient', - 'Office365Client', - 'SharepointonlineClient', - 'TeamsClient', - 'MsgraphgroupsanduserClient', - 'Office365usersClient', - 'Office365groupsClient', - 'Office365groupsmailClient', - 'AzureblobClient', - 'BoxClient', - 'DropboxClient', - 'MqClient', - 'OnedriveClient', - 'OnedriveforbusinessClient', - 'OnenoteClient', - 'PlannerClient', - 'AzureadClient', - 'SmtpClient', - 'ExcelonlineClient', - 'ExcelonlinebusinessClient', - 'AzurequeuesClient', - 'AzuretablesClient', - 'AzurevmClient', - 'DocumentdbClient', - 'EventhubsClient', - 'FtpClient', - 'KeyvaultClient', - 'MicrosoftbookingsClient', - 'OutlookClient', - 'CommondataserviceClient', - 'ServicebusClient', - 'WdatpClient', - 'WordonlinebusinessClient', - 'YammerClient', - "AzuremonitorlogsClient", - "DocusignClient", - "GithubClient", - "GooglecalendarClient", - "GoogletasksClient", - "GoogledriveClient", - "JiraClient", - "MicrosoftformsClient", - "PowerbiClient", - "RssClient", - "SalesforceClient", - "ShiftsClient", - "SlackClient", - "TodoClient", - "InsightlyClient", - "InfusionsoftClient", - "FreshserviceClient", - "MondayClient", - "ProjectplaceClient", - "MailchimpClient", - "SendgridClient", - "WebexClient", - "CampfireClient", - "ClicksendsmsClient", - "TextrequestClient", - "TwitterClient", - "WordpressClient", - "PlivoClient", - "RevaiClient", - "StarmindClient", - "TallyfyClient", - "UniversalprintClient", - "AzureeventgridClient", - "AzureiotcentralClient", - "CloudmersiveconvertClient", - "DynamicsaxClient", - "PdfcoClient", - "PlumsailClient", - "SqlClient", - "ZendeskClient", - "PipedriveClient", - "TrelloClient", - "DocuwareClient", - "SigninghubClient", - "ZohosignClient", - "ZeptomailClient", - "EventbriteClient", - "FormstackformsClient", - "TypeformClient", - "TicketmasterClient", - "SeismicplannerClient", - "WaywedoClient", - "MeetingroommapClient", - "Starrezrestv1Client", - "RepliconClient", - "EtsyClient", - "ElfsquaddataClient", - "ImpexiumClient", - "JedoxodatahubClient", - "OrderfulClient", - "CloudconvertClient", + "ConnectorClientBase", + "ConnectorException", + "ConnectorHttpClient", + "ConnectorResponse", + "ConnectorResponseHook", + "ConnectorResponseSnapshot", + "TriggerCallbackBody", + "TriggerCallbackPayload", + *CLIENT_REGISTRY, ] diff --git a/src/azure/connectors/__init__.pyi b/src/azure/connectors/__init__.pyi new file mode 100644 index 0000000..c6e3483 --- /dev/null +++ b/src/azure/connectors/__init__.pyi @@ -0,0 +1,116 @@ +# ------------------------------------------------------------ +# Copyright (c) Microsoft Corporation. All rights reserved. +# ------------------------------------------------------------ + +"""Generated type declarations for package-root exports. Do not edit.""" + +from .sdk.client_base import ConnectorClientBase as ConnectorClientBase +from .sdk.exceptions import ConnectorException as ConnectorException +from .sdk.http_client import ConnectorHttpClient as ConnectorHttpClient +from .sdk.http_client import ConnectorResponse as ConnectorResponse +from .sdk.response import ConnectorResponseHook as ConnectorResponseHook +from .sdk.response import ConnectorResponseSnapshot as ConnectorResponseSnapshot +from .sdk.trigger_payload import TriggerCallbackBody as TriggerCallbackBody +from .sdk.trigger_payload import TriggerCallbackPayload as TriggerCallbackPayload +from .arm import ArmClient as ArmClient +from .azuread import AzureadClient as AzureadClient +from .azureautomation import AzureautomationClient as AzureautomationClient +from .azureblob import AzureblobClient as AzureblobClient +from .azuredatafactory import AzuredatafactoryClient as AzuredatafactoryClient +from .azuredigitaltwins import AzuredigitaltwinsClient as AzuredigitaltwinsClient +from .azureeventgrid import AzureeventgridClient as AzureeventgridClient +from .azureiotcentral import AzureiotcentralClient as AzureiotcentralClient +from .azuremonitorlogs import AzuremonitorlogsClient as AzuremonitorlogsClient +from .azurequeues import AzurequeuesClient as AzurequeuesClient +from .azuretables import AzuretablesClient as AzuretablesClient +from .azurevm import AzurevmClient as AzurevmClient +from .box import BoxClient as BoxClient +from .campfire import CampfireClient as CampfireClient +from .clicksendsms import ClicksendsmsClient as ClicksendsmsClient +from .cloudconvert import CloudconvertClient as CloudconvertClient +from .cloudmersiveconvert import CloudmersiveconvertClient as CloudmersiveconvertClient +from .commondataservice import CommondataserviceClient as CommondataserviceClient +from .documentdb import DocumentdbClient as DocumentdbClient +from .docusign import DocusignClient as DocusignClient +from .docuware import DocuwareClient as DocuwareClient +from .dropbox import DropboxClient as DropboxClient +from .dynamicsax import DynamicsaxClient as DynamicsaxClient +from .elfsquaddata import ElfsquaddataClient as ElfsquaddataClient +from .etsy import EtsyClient as EtsyClient +from .eventbrite import EventbriteClient as EventbriteClient +from .eventhubs import EventhubsClient as EventhubsClient +from .excelonline import ExcelonlineClient as ExcelonlineClient +from .excelonlinebusiness import ExcelonlinebusinessClient as ExcelonlinebusinessClient +from .formstackforms import FormstackformsClient as FormstackformsClient +from .freshservice import FreshserviceClient as FreshserviceClient +from .ftp import FtpClient as FtpClient +from .github import GithubClient as GithubClient +from .googlecalendar import GooglecalendarClient as GooglecalendarClient +from .googledrive import GoogledriveClient as GoogledriveClient +from .googletasks import GoogletasksClient as GoogletasksClient +from .impexium import ImpexiumClient as ImpexiumClient +from .infusionsoft import InfusionsoftClient as InfusionsoftClient +from .insightly import InsightlyClient as InsightlyClient +from .jedoxodatahub import JedoxodatahubClient as JedoxodatahubClient +from .jira import JiraClient as JiraClient +from .keyvault import KeyvaultClient as KeyvaultClient +from .kusto import KustoClient as KustoClient +from .mailchimp import MailchimpClient as MailchimpClient +from .meetingroommap import MeetingroommapClient as MeetingroommapClient +from .microsoftbookings import MicrosoftbookingsClient as MicrosoftbookingsClient +from .microsoftforms import MicrosoftformsClient as MicrosoftformsClient +from .monday import MondayClient as MondayClient +from .mq import MqClient as MqClient +from .msgraphgroupsanduser import MsgraphgroupsanduserClient as MsgraphgroupsanduserClient +from .office365 import Office365Client as Office365Client +from .office365groups import Office365groupsClient as Office365groupsClient +from .office365groupsmail import Office365groupsmailClient as Office365groupsmailClient +from .office365users import Office365usersClient as Office365usersClient +from .onedrive import OnedriveClient as OnedriveClient +from .onedriveforbusiness import OnedriveforbusinessClient as OnedriveforbusinessClient +from .onenote import OnenoteClient as OnenoteClient +from .orderful import OrderfulClient as OrderfulClient +from .outlook import OutlookClient as OutlookClient +from .pdfco import PdfcoClient as PdfcoClient +from .pipedrive import PipedriveClient as PipedriveClient +from .planner import PlannerClient as PlannerClient +from .plivo import PlivoClient as PlivoClient +from .plumsail import PlumsailClient as PlumsailClient +from .powerbi import PowerbiClient as PowerbiClient +from .projectplace import ProjectplaceClient as ProjectplaceClient +from .replicon import RepliconClient as RepliconClient +from .revai import RevaiClient as RevaiClient +from .rss import RssClient as RssClient +from .salesforce import SalesforceClient as SalesforceClient +from .seismicplanner import SeismicplannerClient as SeismicplannerClient +from .sendgrid import SendgridClient as SendgridClient +from .servicebus import ServicebusClient as ServicebusClient +from .sharepointonline import SharepointonlineClient as SharepointonlineClient +from .shifts import ShiftsClient as ShiftsClient +from .signinghub import SigninghubClient as SigninghubClient +from .slack import SlackClient as SlackClient +from .smtp import SmtpClient as SmtpClient +from .sql import SqlClient as SqlClient +from .starmind import StarmindClient as StarmindClient +from .starrezrestv1 import Starrezrestv1Client as Starrezrestv1Client +from .tallyfy import TallyfyClient as TallyfyClient +from .teams import TeamsClient as TeamsClient +from .textrequest import TextrequestClient as TextrequestClient +from .ticketmaster import TicketmasterClient as TicketmasterClient +from .todo import TodoClient as TodoClient +from .trello import TrelloClient as TrelloClient +from .twitter import TwitterClient as TwitterClient +from .typeform import TypeformClient as TypeformClient +from .universalprint import UniversalprintClient as UniversalprintClient +from .waywedo import WaywedoClient as WaywedoClient +from .wdatp import WdatpClient as WdatpClient +from .webex import WebexClient as WebexClient +from .wordonlinebusiness import WordonlinebusinessClient as WordonlinebusinessClient +from .wordpress import WordpressClient as WordpressClient +from .yammer import YammerClient as YammerClient +from .zendesk import ZendeskClient as ZendeskClient +from .zeptomail import ZeptomailClient as ZeptomailClient +from .zohosign import ZohosignClient as ZohosignClient + +__version__: str +__all__: list[str] diff --git a/src/azure/connectors/_client_registry.py b/src/azure/connectors/_client_registry.py new file mode 100644 index 0000000..013529c --- /dev/null +++ b/src/azure/connectors/_client_registry.py @@ -0,0 +1,110 @@ +# ------------------------------------------------------------ +# Copyright (c) Microsoft Corporation. All rights reserved. +# ------------------------------------------------------------ + +"""Generated registry of public connector clients. Do not edit.""" + +from typing import Final + + +CLIENT_REGISTRY: Final[dict[str, str]] = { + "ArmClient": "arm", + "AzureadClient": "azuread", + "AzureautomationClient": "azureautomation", + "AzureblobClient": "azureblob", + "AzuredatafactoryClient": "azuredatafactory", + "AzuredigitaltwinsClient": "azuredigitaltwins", + "AzureeventgridClient": "azureeventgrid", + "AzureiotcentralClient": "azureiotcentral", + "AzuremonitorlogsClient": "azuremonitorlogs", + "AzurequeuesClient": "azurequeues", + "AzuretablesClient": "azuretables", + "AzurevmClient": "azurevm", + "BoxClient": "box", + "CampfireClient": "campfire", + "ClicksendsmsClient": "clicksendsms", + "CloudconvertClient": "cloudconvert", + "CloudmersiveconvertClient": "cloudmersiveconvert", + "CommondataserviceClient": "commondataservice", + "DocumentdbClient": "documentdb", + "DocusignClient": "docusign", + "DocuwareClient": "docuware", + "DropboxClient": "dropbox", + "DynamicsaxClient": "dynamicsax", + "ElfsquaddataClient": "elfsquaddata", + "EtsyClient": "etsy", + "EventbriteClient": "eventbrite", + "EventhubsClient": "eventhubs", + "ExcelonlineClient": "excelonline", + "ExcelonlinebusinessClient": "excelonlinebusiness", + "FormstackformsClient": "formstackforms", + "FreshserviceClient": "freshservice", + "FtpClient": "ftp", + "GithubClient": "github", + "GooglecalendarClient": "googlecalendar", + "GoogledriveClient": "googledrive", + "GoogletasksClient": "googletasks", + "ImpexiumClient": "impexium", + "InfusionsoftClient": "infusionsoft", + "InsightlyClient": "insightly", + "JedoxodatahubClient": "jedoxodatahub", + "JiraClient": "jira", + "KeyvaultClient": "keyvault", + "KustoClient": "kusto", + "MailchimpClient": "mailchimp", + "MeetingroommapClient": "meetingroommap", + "MicrosoftbookingsClient": "microsoftbookings", + "MicrosoftformsClient": "microsoftforms", + "MondayClient": "monday", + "MqClient": "mq", + "MsgraphgroupsanduserClient": "msgraphgroupsanduser", + "Office365Client": "office365", + "Office365groupsClient": "office365groups", + "Office365groupsmailClient": "office365groupsmail", + "Office365usersClient": "office365users", + "OnedriveClient": "onedrive", + "OnedriveforbusinessClient": "onedriveforbusiness", + "OnenoteClient": "onenote", + "OrderfulClient": "orderful", + "OutlookClient": "outlook", + "PdfcoClient": "pdfco", + "PipedriveClient": "pipedrive", + "PlannerClient": "planner", + "PlivoClient": "plivo", + "PlumsailClient": "plumsail", + "PowerbiClient": "powerbi", + "ProjectplaceClient": "projectplace", + "RepliconClient": "replicon", + "RevaiClient": "revai", + "RssClient": "rss", + "SalesforceClient": "salesforce", + "SeismicplannerClient": "seismicplanner", + "SendgridClient": "sendgrid", + "ServicebusClient": "servicebus", + "SharepointonlineClient": "sharepointonline", + "ShiftsClient": "shifts", + "SigninghubClient": "signinghub", + "SlackClient": "slack", + "SmtpClient": "smtp", + "SqlClient": "sql", + "StarmindClient": "starmind", + "Starrezrestv1Client": "starrezrestv1", + "TallyfyClient": "tallyfy", + "TeamsClient": "teams", + "TextrequestClient": "textrequest", + "TicketmasterClient": "ticketmaster", + "TodoClient": "todo", + "TrelloClient": "trello", + "TwitterClient": "twitter", + "TypeformClient": "typeform", + "UniversalprintClient": "universalprint", + "WaywedoClient": "waywedo", + "WdatpClient": "wdatp", + "WebexClient": "webex", + "WordonlinebusinessClient": "wordonlinebusiness", + "WordpressClient": "wordpress", + "YammerClient": "yammer", + "ZendeskClient": "zendesk", + "ZeptomailClient": "zeptomail", + "ZohosignClient": "zohosign", +} diff --git a/src/azure/connectors/aio/__init__.py b/src/azure/connectors/aio/__init__.py new file mode 100644 index 0000000..6dd9458 --- /dev/null +++ b/src/azure/connectors/aio/__init__.py @@ -0,0 +1,27 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Asynchronous generated connector clients.""" + +from importlib import import_module +from typing import Any + +from .._client_registry import CLIENT_REGISTRY + + +def __getattr__(name: str) -> Any: + """Load a generated asynchronous client when requested from the package root.""" + module_name = CLIENT_REGISTRY.get(name) + if module_name is None: + raise AttributeError(f"Module '{__name__}' has no attribute '{name}'.") + + client_type = getattr(import_module(f".{module_name}", __name__), name) + globals()[name] = client_type + return client_type + + +def __dir__() -> list[str]: + """List lazily available asynchronous connector clients.""" + return sorted(set(globals()) | CLIENT_REGISTRY.keys()) + + +__all__ = [*CLIENT_REGISTRY] diff --git a/src/azure/connectors/aio/__init__.pyi b/src/azure/connectors/aio/__init__.pyi new file mode 100644 index 0000000..b443b67 --- /dev/null +++ b/src/azure/connectors/aio/__init__.pyi @@ -0,0 +1,107 @@ +# ------------------------------------------------------------ +# Copyright (c) Microsoft Corporation. All rights reserved. +# ------------------------------------------------------------ + +"""Generated type declarations for asynchronous package-root exports.""" + +from .arm import ArmClient as ArmClient +from .azuread import AzureadClient as AzureadClient +from .azureautomation import AzureautomationClient as AzureautomationClient +from .azureblob import AzureblobClient as AzureblobClient +from .azuredatafactory import AzuredatafactoryClient as AzuredatafactoryClient +from .azuredigitaltwins import AzuredigitaltwinsClient as AzuredigitaltwinsClient +from .azureeventgrid import AzureeventgridClient as AzureeventgridClient +from .azureiotcentral import AzureiotcentralClient as AzureiotcentralClient +from .azuremonitorlogs import AzuremonitorlogsClient as AzuremonitorlogsClient +from .azurequeues import AzurequeuesClient as AzurequeuesClient +from .azuretables import AzuretablesClient as AzuretablesClient +from .azurevm import AzurevmClient as AzurevmClient +from .box import BoxClient as BoxClient +from .campfire import CampfireClient as CampfireClient +from .clicksendsms import ClicksendsmsClient as ClicksendsmsClient +from .cloudconvert import CloudconvertClient as CloudconvertClient +from .cloudmersiveconvert import CloudmersiveconvertClient as CloudmersiveconvertClient +from .commondataservice import CommondataserviceClient as CommondataserviceClient +from .documentdb import DocumentdbClient as DocumentdbClient +from .docusign import DocusignClient as DocusignClient +from .docuware import DocuwareClient as DocuwareClient +from .dropbox import DropboxClient as DropboxClient +from .dynamicsax import DynamicsaxClient as DynamicsaxClient +from .elfsquaddata import ElfsquaddataClient as ElfsquaddataClient +from .etsy import EtsyClient as EtsyClient +from .eventbrite import EventbriteClient as EventbriteClient +from .eventhubs import EventhubsClient as EventhubsClient +from .excelonline import ExcelonlineClient as ExcelonlineClient +from .excelonlinebusiness import ExcelonlinebusinessClient as ExcelonlinebusinessClient +from .formstackforms import FormstackformsClient as FormstackformsClient +from .freshservice import FreshserviceClient as FreshserviceClient +from .ftp import FtpClient as FtpClient +from .github import GithubClient as GithubClient +from .googlecalendar import GooglecalendarClient as GooglecalendarClient +from .googledrive import GoogledriveClient as GoogledriveClient +from .googletasks import GoogletasksClient as GoogletasksClient +from .impexium import ImpexiumClient as ImpexiumClient +from .infusionsoft import InfusionsoftClient as InfusionsoftClient +from .insightly import InsightlyClient as InsightlyClient +from .jedoxodatahub import JedoxodatahubClient as JedoxodatahubClient +from .jira import JiraClient as JiraClient +from .keyvault import KeyvaultClient as KeyvaultClient +from .kusto import KustoClient as KustoClient +from .mailchimp import MailchimpClient as MailchimpClient +from .meetingroommap import MeetingroommapClient as MeetingroommapClient +from .microsoftbookings import MicrosoftbookingsClient as MicrosoftbookingsClient +from .microsoftforms import MicrosoftformsClient as MicrosoftformsClient +from .monday import MondayClient as MondayClient +from .mq import MqClient as MqClient +from .msgraphgroupsanduser import MsgraphgroupsanduserClient as MsgraphgroupsanduserClient +from .office365 import Office365Client as Office365Client +from .office365groups import Office365groupsClient as Office365groupsClient +from .office365groupsmail import Office365groupsmailClient as Office365groupsmailClient +from .office365users import Office365usersClient as Office365usersClient +from .onedrive import OnedriveClient as OnedriveClient +from .onedriveforbusiness import OnedriveforbusinessClient as OnedriveforbusinessClient +from .onenote import OnenoteClient as OnenoteClient +from .orderful import OrderfulClient as OrderfulClient +from .outlook import OutlookClient as OutlookClient +from .pdfco import PdfcoClient as PdfcoClient +from .pipedrive import PipedriveClient as PipedriveClient +from .planner import PlannerClient as PlannerClient +from .plivo import PlivoClient as PlivoClient +from .plumsail import PlumsailClient as PlumsailClient +from .powerbi import PowerbiClient as PowerbiClient +from .projectplace import ProjectplaceClient as ProjectplaceClient +from .replicon import RepliconClient as RepliconClient +from .revai import RevaiClient as RevaiClient +from .rss import RssClient as RssClient +from .salesforce import SalesforceClient as SalesforceClient +from .seismicplanner import SeismicplannerClient as SeismicplannerClient +from .sendgrid import SendgridClient as SendgridClient +from .servicebus import ServicebusClient as ServicebusClient +from .sharepointonline import SharepointonlineClient as SharepointonlineClient +from .shifts import ShiftsClient as ShiftsClient +from .signinghub import SigninghubClient as SigninghubClient +from .slack import SlackClient as SlackClient +from .smtp import SmtpClient as SmtpClient +from .sql import SqlClient as SqlClient +from .starmind import StarmindClient as StarmindClient +from .starrezrestv1 import Starrezrestv1Client as Starrezrestv1Client +from .tallyfy import TallyfyClient as TallyfyClient +from .teams import TeamsClient as TeamsClient +from .textrequest import TextrequestClient as TextrequestClient +from .ticketmaster import TicketmasterClient as TicketmasterClient +from .todo import TodoClient as TodoClient +from .trello import TrelloClient as TrelloClient +from .twitter import TwitterClient as TwitterClient +from .typeform import TypeformClient as TypeformClient +from .universalprint import UniversalprintClient as UniversalprintClient +from .waywedo import WaywedoClient as WaywedoClient +from .wdatp import WdatpClient as WdatpClient +from .webex import WebexClient as WebexClient +from .wordonlinebusiness import WordonlinebusinessClient as WordonlinebusinessClient +from .wordpress import WordpressClient as WordpressClient +from .yammer import YammerClient as YammerClient +from .zendesk import ZendeskClient as ZendeskClient +from .zeptomail import ZeptomailClient as ZeptomailClient +from .zohosign import ZohosignClient as ZohosignClient + +__all__: list[str] diff --git a/src/azure/connectors/aio/arm.py b/src/azure/connectors/aio/arm.py new file mode 100644 index 0000000..8d6b391 --- /dev/null +++ b/src/azure/connectors/aio/arm.py @@ -0,0 +1,3074 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# ArmClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.arm import ( + AliasPathType, + AliasType, + BasicDependency, + DebugSetting, + Dependency, + Deployment, + DeploymentExportResult, + DeploymentExtended, + DeploymentListResult, + DeploymentOperation, + DeploymentOperationProperties, + DeploymentOperationsListResult, + DeploymentProperties, + DeploymentPropertiesExtended, + DeploymentValidateResult, + ExportTemplateRequest, + GenericResource, + HttpMessage, + Identity, + Location, + LocationListResult, + ObjectWithoutType, + ParametersLink, + Plan, + Provider, + ProviderListResult, + ProviderResourceType, + ProviderResourcesInvokeInput, + ProviderResourcesInvokeResponse, + ResourceGroup, + ResourceGroupExportResult, + ResourceGroupListResult, + ResourceGroupProperties, + ResourceListResult, + ResourceManagementErrorWithDetails, + ResourcesInvokeInput, + ResourcesInvokeResponse, + Sku, + Subscription, + SubscriptionListResult, + SubscriptionPolicies, + TagCount, + TagDetails, + TagValue, + TagsListResult, + TargetResource, + TemplateLink, +) + +__all__ = [ + "ArmClient", + "AliasPathType", + "AliasType", + "BasicDependency", + "DebugSetting", + "Dependency", + "Deployment", + "DeploymentExportResult", + "DeploymentExtended", + "DeploymentListResult", + "DeploymentOperation", + "DeploymentOperationProperties", + "DeploymentOperationsListResult", + "DeploymentProperties", + "DeploymentPropertiesExtended", + "DeploymentValidateResult", + "ExportTemplateRequest", + "GenericResource", + "HttpMessage", + "Identity", + "Location", + "LocationListResult", + "ObjectWithoutType", + "ParametersLink", + "Plan", + "Provider", + "ProviderListResult", + "ProviderResourceType", + "ProviderResourcesInvokeInput", + "ProviderResourcesInvokeResponse", + "ResourceGroup", + "ResourceGroupExportResult", + "ResourceGroupListResult", + "ResourceGroupProperties", + "ResourceListResult", + "ResourceManagementErrorWithDetails", + "ResourcesInvokeInput", + "ResourcesInvokeResponse", + "Sku", + "Subscription", + "SubscriptionListResult", + "SubscriptionPolicies", + "TagCount", + "TagDetails", + "TagValue", + "TagsListResult", + "TargetResource", + "TemplateLink", +] + + +# Type Definitions + +# Client Class + +class ArmClient(ConnectorClientBase): + """Typed client for arm connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a ArmClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "arm" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_subscriptions_list_locations( + self, + subscription_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Lists the subscription locations + + Lists the locations available for the subscription. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Subscriptions_ListLocations`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions/{quote(str(subscription_id), safe='')}/locations" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def subscriptions_get( + self, + subscription_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Read a subscription + + Reads the details for a particular subscription. + + Swagger operation ID: `Subscriptions_Get`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions/{quote(str(subscription_id), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_subscriptions( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List subscriptions + + Gets a list of all the subscriptions to which the principal has access. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Subscriptions_List`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/subscriptions" + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def deployments_get( + self, + subscription_id: str, + resource_group_name: str, + deployment_name: str, + *, + wait: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Read a template deployment + + Reads a template deployment within a resource group. + + Swagger operation ID: `Deployments_Get`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the resource group template + deployment. + wait: If the action should wait until deployment is completed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Resources" + f"/deployments" + f"/{quote(str(deployment_name), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if wait is not None: + value = str(wait) + if isinstance(wait, bool): + value = value.lower() + query_params.append(f"wait={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def deployments_create_or_update( + self, + input: Deployment | Mapping[str, Any], + subscription_id: str, + resource_group_name: str, + deployment_name: str, + *, + wait: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create or update a template deployment + + Create or update a named resource group template deployment. A template + and parameters are expected for the request to succeed. + + Swagger operation ID: `Deployments_CreateOrUpdate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the deployment. + wait: If the action should wait until deployment is completed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Resources" + f"/deployments" + f"/{quote(str(deployment_name), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if wait is not None: + value = str(wait) + if isinstance(wait, bool): + value = value.lower() + query_params.append(f"wait={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def deployments_delete( + self, + subscription_id: str, + resource_group_name: str, + deployment_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete template deployment + + Deletes a resource group template deployment. The resources will not be + deleted; only the metadata about the template deployment. + + Swagger operation ID: `Deployments_Delete`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the resource group template + deployment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Resources" + f"/deployments" + f"/{quote(str(deployment_name), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if response.status == 404: + return None + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def deployments_cancel( + self, + subscription_id: str, + resource_group_name: str, + deployment_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Cancel a template deployment + + Cancel a currently running template deployment. All pending template + operations will be suspended. + + Swagger operation ID: `Deployments_Cancel`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the resource group template + deployment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Resources" + f"/deployments" + f"/{quote(str(deployment_name), safe='')}" + f"/cancel" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def deployments_validate( + self, + input: Deployment | Mapping[str, Any], + subscription_id: str, + resource_group_name: str, + deployment_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Validate a template deployment + + Validates a deployment template. This operation does not have side + effects and can be used to test a template deployment for syntax or + logical errors. + + Swagger operation ID: `Deployments_Validate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the resource group template + deployment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Resources" + f"/deployments" + f"/{quote(str(deployment_name), safe='')}" + f"/validate" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def deployments_export_template( + self, + subscription_id: str, + resource_group_name: str, + deployment_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Export deployment template + + Exports a template from a past resource group deployment. + + Swagger operation ID: `Deployments_ExportTemplate`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the resource group template + deployment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Resources" + f"/deployments" + f"/{quote(str(deployment_name), safe='')}" + f"/exportTemplate" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_deployments( + self, + subscription_id: str, + resource_group_name: str, + *, + filter: Optional[str] = None, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List template deployments + + Lists all the resource group template deployments. This operation is + useful to know what has been provisioned thus far. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Deployments_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + filter: The filter to apply on the operation. + top: Query parameters. If nothing is passed returns all values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Resources" + f"/deployments" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def deployment_operations_get( + self, + subscription_id: str, + resource_group_name: str, + deployment_name: str, + operation_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Read a template deployment operation + + Reads a particular resource group template deployment operation. This + is useful for troubleshooting failed template deployments. + + Swagger operation ID: `DeploymentOperations_Get`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the resource group template + deployment. + operation_id: Operation Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/deployments" + f"/{quote(str(deployment_name), safe='')}" + f"/operations" + f"/{quote(str(operation_id), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_deployment_operations( + self, + subscription_id: str, + resource_group_name: str, + deployment_name: str, + *, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Lists template deployment operations + + Lists all the template deployment operations. This is useful for + troubleshooting failed template deployments. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `DeploymentOperations_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the resource group template + deployment. + top: Query parameters. If nothing is passed returns all values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/deployments" + f"/{quote(str(deployment_name), safe='')}" + f"/operations" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def providers_unregister( + self, + subscription_id: str, + resource_provider_namespace: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Unregister resource provider + + Unregisters provider from a subscription. This operation will fail if + there are any resources from that resource provider in the + subscription. + + Swagger operation ID: `Providers_Unregister`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_provider_namespace: Namespace of the resource provider. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/providers" + f"/{quote(str(resource_provider_namespace), safe='')}" + f"/unregister" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def providers_register( + self, + subscription_id: str, + resource_provider_namespace: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Register resource provider + + Registers a resource provider to be used with a subscription. This will + provision permissions for the service into your subscription. + + Swagger operation ID: `Providers_Register`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_provider_namespace: Namespace of the resource provider. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/providers" + f"/{quote(str(resource_provider_namespace), safe='')}" + f"/register" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_providers( + self, + subscription_id: str, + *, + top: Optional[int] = None, + expand: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List resource providers + + Lists the resource providers available for the subscription. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Providers_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + top: Query parameters. If nothing is passed returns all values. + expand: The $expand query parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions/{quote(str(subscription_id), safe='')}/providers" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if expand is not None: + value = str(expand) + if isinstance(expand, bool): + value = value.lower() + query_params.append(f"$expand={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def providers_get( + self, + subscription_id: str, + resource_provider_namespace: str, + *, + expand: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Read resource provider + + Reads a particular resource provider within the subscription. + + Swagger operation ID: `Providers_Get`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_provider_namespace: Namespace of the resource provider. + expand: The $expand query parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/providers" + f"/{quote(str(resource_provider_namespace), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if expand is not None: + value = str(expand) + if isinstance(expand, bool): + value = value.lower() + query_params.append(f"$expand={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_resource_groups_list_resources( + self, + subscription_id: str, + resource_group_name: str, + *, + filter: Optional[str] = None, + expand: Optional[str] = None, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List resources by resource group + + Lists all the resources under a resource group. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ResourceGroups_ListResources`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + filter: The filter to apply on the operation. + expand: The $expand query parameter. + top: Query parameters. If nothing is passed returns all values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourceGroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/resources" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if expand is not None: + value = str(expand) + if isinstance(expand, bool): + value = value.lower() + query_params.append(f"$expand={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def resource_groups_get( + self, + subscription_id: str, + resource_group_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Read a resource group + + Reads a particular resource group within the subscription. + + Swagger operation ID: `ResourceGroups_Get`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def resource_groups_create_or_update( + self, + input: ResourceGroup | Mapping[str, Any], + subscription_id: str, + resource_group_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create or update a resource group + + Creates or updates a resource group. The response code can be used to + distinguish between a create (201) or update (200). + + Swagger operation ID: `ResourceGroups_CreateOrUpdate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: The name of the resource group to be created + or updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def resource_groups_delete( + self, + subscription_id: str, + resource_group_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a resource group + + Delete a particular resource group within the subscription. + + Swagger operation ID: `ResourceGroups_Delete`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def resource_groups_patch( + self, + input: ResourceGroup | Mapping[str, Any], + subscription_id: str, + resource_group_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update an existing resource group + + Updates an existing resource group. If the resource does not exist, + this request will fail. + + Swagger operation ID: `ResourceGroups_Patch`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def resource_groups_export_template( + self, + input: ExportTemplateRequest | Mapping[str, Any], + subscription_id: str, + resource_group_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Export a resource group template + + Exports a deployment template from an existing resource group. This can + only be successful if the underlying resources have a schema defined by + Microsoft. + + Swagger operation ID: `ResourceGroups_ExportTemplate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/exportTemplate" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_resource_groups( + self, + subscription_id: str, + *, + filter: Optional[str] = None, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List resource groups + + Lists all the resource groups within the subscription. The results are + paginated at 1,000+ records. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ResourceGroups_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + filter: The filter to apply on the operation. + top: Query parameters. If nothing is passed returns all values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_resources( + self, + subscription_id: str, + *, + filter: Optional[str] = None, + expand: Optional[str] = None, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List resources by subscription + + Reads all of the resources under a particular subscription. The results + are paginated at 1,000+ records. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Resources_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + filter: The filter to apply on the operation. + expand: The $expand query parameter. + top: Query parameters. If nothing is passed returns all values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions/{quote(str(subscription_id), safe='')}/resources" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if expand is not None: + value = str(expand) + if isinstance(expand, bool): + value = value.lower() + query_params.append(f"$expand={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def resources_get_by_id( + self, + subscription_id: str, + resource_group_name: str, + resource_provider_namespace: str, + short_resource_id: str, + x_ms_api_version: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Read a resource + + Reads a resource object. + + Swagger operation ID: `Resources_GetById`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + resource_provider_namespace: Namespace of the resource provider. + short_resource_id: The short Id of the resource, including the + resource name and resource type. For example, sites/mySite. + x_ms_api_version: Api Version to be used. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/{quote(str(resource_provider_namespace), safe='')}" + f"/{quote(str(short_resource_id), safe='')}" + ) + query_params = [] + value = str(x_ms_api_version) + if isinstance(x_ms_api_version, bool): + value = value.lower() + query_params.append(f"x-ms-api-version={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def resources_create_or_update_by_id( + self, + input: GenericResource | Mapping[str, Any], + subscription_id: str, + resource_group_name: str, + resource_provider_namespace: str, + short_resource_id: str, + x_ms_api_version: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create or update a resource + + Creates or updates a resource. The response code can be used to + distinguish between a create (201) or update (200). + + Swagger operation ID: `Resources_CreateOrUpdateById`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + resource_provider_namespace: Namespace of the resource provider. + short_resource_id: The short Id of the resource, including the + resource name and resource type. For example, sites/mySite. + x_ms_api_version: Api Version to be used. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/{quote(str(resource_provider_namespace), safe='')}" + f"/{quote(str(short_resource_id), safe='')}" + ) + query_params = [] + value = str(x_ms_api_version) + if isinstance(x_ms_api_version, bool): + value = value.lower() + query_params.append(f"x-ms-api-version={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def resources_delete_by_id( + self, + subscription_id: str, + resource_group_name: str, + resource_provider_namespace: str, + short_resource_id: str, + x_ms_api_version: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a resource + + Deletes a resource. + + Swagger operation ID: `Resources_DeleteById`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + resource_provider_namespace: Namespace of the resource provider. + short_resource_id: The short Id of the resource, including the + resource name and resource type. For example, sites/mySite. + x_ms_api_version: Api Version to be used. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/{quote(str(resource_provider_namespace), safe='')}" + f"/{quote(str(short_resource_id), safe='')}" + ) + query_params = [] + value = str(x_ms_api_version) + if isinstance(x_ms_api_version, bool): + value = value.lower() + query_params.append(f"x-ms-api-version={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def resources_invoke( + self, + input: ResourcesInvokeInput | Mapping[str, Any], + subscription_id: str, + resource_group_name: str, + resource_provider_namespace: str, + short_resource_id: str, + action_name: str, + x_ms_api_version: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Invoke resource operation + + Invokes an operation on an Azure resource. + + Swagger operation ID: `Resources_Invoke`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + resource_provider_namespace: Namespace of the resource provider. + short_resource_id: The short Id of the resource, including the + resource name and resource type. For example, sites/mySite. + action_name: Name of the resource action to invoke. + x_ms_api_version: Api Version to be used. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/{quote(str(resource_provider_namespace), safe='')}" + f"/{quote(str(short_resource_id), safe='')}" + f"/{quote(str(action_name), safe='')}" + ) + query_params = [] + value = str(x_ms_api_version) + if isinstance(x_ms_api_version, bool): + value = value.lower() + query_params.append(f"x-ms-api-version={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def provider_resources_get_by_id( + self, + subscription_id: str, + resource_provider_namespace: str, + short_resource_id: str, + x_ms_api_version: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Read a resource in provider + + Reads a resource object. + + Swagger operation ID: `Provider_Resources_GetById`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_provider_namespace: Namespace of the resource provider. + short_resource_id: The short Id of the resource, including the + resource name and resource type. For example, sites/mySite. + x_ms_api_version: Api Version to be used. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/providers" + f"/{quote(str(resource_provider_namespace), safe='')}" + f"/{quote(str(short_resource_id), safe='')}" + ) + query_params = [] + value = str(x_ms_api_version) + if isinstance(x_ms_api_version, bool): + value = value.lower() + query_params.append(f"x-ms-api-version={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def provider_resources_invoke( + self, + input: ProviderResourcesInvokeInput | Mapping[str, Any], + subscription_id: str, + resource_provider_namespace: str, + short_resource_id: str, + x_ms_api_version: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Invoke resource operation in provider + + Invokes an operation on an Azure resource. + + Swagger operation ID: `Provider_Resources_Invoke`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_provider_namespace: Namespace of the resource provider. + short_resource_id: The short Id of the resource, including the + resource name and resource type. For example, sites/mySite. + x_ms_api_version: Api Version to be used. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/providers" + f"/{quote(str(resource_provider_namespace), safe='')}" + f"/{quote(str(short_resource_id), safe='')}" + ) + query_params = [] + value = str(x_ms_api_version) + if isinstance(x_ms_api_version, bool): + value = value.lower() + query_params.append(f"x-ms-api-version={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def tags_create_or_update_value( + self, + subscription_id: str, + tag_name: str, + tag_value: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create or update a subscription resource tag value + + Create or update a subscription resource tag value. + + Swagger operation ID: `Tags_CreateOrUpdateValue`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + tag_name: The name of the tag. + tag_value: The value of the tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/tagNames" + f"/{quote(str(tag_name), safe='')}" + f"/tagValues" + f"/{quote(str(tag_value), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def tags_delete_value( + self, + subscription_id: str, + tag_name: str, + tag_value: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a subscription resource tag value + + Delete a subscription resource tag value. + + Swagger operation ID: `Tags_DeleteValue`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + tag_name: The name of the tag. + tag_value: The value of the tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/tagNames" + f"/{quote(str(tag_name), safe='')}" + f"/tagValues" + f"/{quote(str(tag_value), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def tags_create_or_update( + self, + subscription_id: str, + tag_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create or update a subscription resource tag name + + Create or update a subscription resource tag name. + + Swagger operation ID: `Tags_CreateOrUpdate`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + tag_name: The name of the tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/tagNames" + f"/{quote(str(tag_name), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def tags_delete( + self, + subscription_id: str, + tag_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a subscription resource tag name + + Delete a subscription resource tag name. + + Swagger operation ID: `Tags_Delete`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + tag_name: The name of the tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/tagNames" + f"/{quote(str(tag_name), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_tags( + self, + subscription_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List subscription resource tags + + Lists all the subscription resource tags. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Tags_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions/{quote(str(subscription_id), safe='')}/tagNames" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/azuread.py b/src/azure/connectors/aio/azuread.py new file mode 100644 index 0000000..8956542 --- /dev/null +++ b/src/azure/connectors/aio/azuread.py @@ -0,0 +1,1019 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# AzureadClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.azuread import ( + AssignManagerRequest, + CheckMemberGroupsRequest, + CreateGroupInput, + CreateGroupResponse, + CreateOffice365GroupInput, + CreateSecurityGroupInput, + CreateUserRequest, + GetGroupMembersResponse, + GetGroupRequest, + GetGroupResponse, + GetMemberGroupsRequest, + GetMemberGroupsResponse, + GetMemberGroupsResponseV2, + GetUserResponse, + UpdateUserRequest, +) + +__all__ = [ + "AzureadClient", + "AssignManagerRequest", + "CheckMemberGroupsRequest", + "CreateGroupInput", + "CreateGroupResponse", + "CreateOffice365GroupInput", + "CreateSecurityGroupInput", + "CreateUserRequest", + "GetGroupMembersResponse", + "GetGroupRequest", + "GetGroupResponse", + "GetMemberGroupsRequest", + "GetMemberGroupsResponse", + "GetMemberGroupsResponseV2", + "GetUserResponse", + "UpdateUserRequest", +] + + +# Type Definitions + +# Client Class + +class AzureadClient(ConnectorClientBase): + """Typed client for azuread connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a AzureadClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "azuread" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_office365_group( + self, + input: CreateOffice365GroupInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Office 365 group + + Create an Office 365 group in your Microsoft Entra ID tenant. + + Swagger operation ID: `CreateOffice365Group`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/groups/office365" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_security_group( + self, + input: CreateSecurityGroupInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create security group + + Create a security group in your Microsoft Entra ID tenant. + + Swagger operation ID: `CreateSecurityGroup`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1.0/groups/securityGroup" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_group( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get group + + Get details for a group. + + Swagger operation ID: `GetGroup`. + + Args: + id: Unique identifier of a group (Ex. + '40639f36-46a6-73a6-91e2-9584b7913429'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/groups/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_user( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get user + + Get details for a user. + + Swagger operation ID: `GetUser`. + + Args: + id: Unique identifier of a user (Ex. 'user@tennant.onmicrosoft.com' + or '5f6ce5c7-b521-4842-9bbe-3f6d5aa5e35b'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/users/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_user( + self, + input: UpdateUserRequest | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update user + + Update the info for a user. + + Swagger operation ID: `UpdateUser`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique identifier of a user (Ex. 'user@tennant.onmicrosoft.com' + or '5f6ce5c7-b521-4842-9bbe-3f6d5aa5e35b'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/users/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + async def refresh_tokens( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Refresh tokens + + Invalidate all refresh tokens for a user + + Swagger operation ID: `RefreshTokens`. + + Args: + id: Unique identifier of a user (Ex. 'user@tennant.onmicrosoft.com' + or '5f6ce5c7-b521-4842-9bbe-3f6d5aa5e35b'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/users/{quote(str(id), safe='')}/revokeSignInSessions" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def create_user( + self, + input: CreateUserRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create user + + Create a new user in your Microsoft Entra ID tenant. + + Swagger operation ID: `CreateUser`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/users" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_group_members( + self, + id: str, + *, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get group members + + Get the users who are members of a group. You can query up to 1000 + items using the Top parameter. If you need to retrieve more than 1000 + values, please turn on the Settings->Pagination feature and provide a + Threshold limit. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetGroupMembers`. + + Args: + id: Unique identifier of a group (Ex. + '40639f36-46a6-73a6-91e2-9584b7913429'). + top: Limit on the number of results to return (from 1 to 999, + default is 100). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/groups/{quote(str(id), safe='')}/members" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def remove_member_from_group( + self, + group_id: str, + member_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Remove Member From Group + + Remove Member From Group + + Swagger operation ID: `RemoveMemberFromGroup`. + + Args: + group_id: The Id of the group. + member_id: The Id of the member. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/groups" + f"/{quote(str(group_id), safe='')}" + f"/members" + f"/{quote(str(member_id), safe='')}" + f"/$ref" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_user_to_group( + self, + input: GetGroupRequest | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add user to group + + Add a user to a group in this Microsoft Entra ID tenant. + + Swagger operation ID: `AddUserToGroup`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique identifier of a group (Ex. + '40639f36-46a6-73a6-91e2-9584b7913429'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/groups/{quote(str(id), safe='')}/members/$ref" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def assign_manager( + self, + input: AssignManagerRequest | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Assign manager + + Assign a manager for a user. + + Swagger operation ID: `AssignManager`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique identifier of a user (Ex. 'user@tennant.onmicrosoft.com' + or '5f6ce5c7-b521-4842-9bbe-3f6d5aa5e35b'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/users/{quote(str(id), safe='')}/manager/$ref" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + async def create_group( + self, + input: CreateGroupInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create group + + Create a group in your Microsoft Entra ID tenant. + + Swagger operation ID: `CreateGroup`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/groups" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def check_member_groups( + self, + input: CheckMemberGroupsRequest | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Check group membership + + If the user is a member of the given group, the result will contain the + given id. Otherwise the result will be empty. + + Swagger operation ID: `CheckMemberGroupsV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique identifier of a user (Ex. 'user@tennant.onmicrosoft.com' + or '5f6ce5c7-b521-4842-9bbe-3f6d5aa5e35b'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/v1.0/users/{quote(str(id), safe='')}/checkMemberGroups" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_member_groups( + self, + input: GetMemberGroupsRequest | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[str]: + """ + Get groups of a user + + Get the groups a user is a member of. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMemberGroupsV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique identifier of a user (Ex. 'user@tennant.onmicrosoft.com' + or '5f6ce5c7-b521-4842-9bbe-3f6d5aa5e35b'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[str]: An Azure Core pager over connector results. + Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/v1.0/users/{quote(str(id), safe='')}/getMemberGroups" + ) + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[str]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/azureautomation.py b/src/azure/connectors/aio/azureautomation.py new file mode 100644 index 0000000..a65b2fe --- /dev/null +++ b/src/azure/connectors/aio/azureautomation.py @@ -0,0 +1,868 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# AzureautomationClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.azureautomation import ( + AutomationAccountResponse, + CreateJobInput, + CreateJobResponse, + ResourceGroup, + ResourceGroupListResult, + RunbookListResults, + Subscription, + SubscriptionListResult, +) + +__all__ = [ + "AzureautomationClient", + "AutomationAccountResponse", + "CreateJobInput", + "CreateJobResponse", + "ResourceGroup", + "ResourceGroupListResult", + "RunbookListResults", + "Subscription", + "SubscriptionListResult", +] + + +# Type Definitions + +# Client Class + +class AzureautomationClient(ConnectorClientBase): + """Typed client for azureautomation connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a AzureautomationClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "azureautomation" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def get_job_output( + self, + subscription_id: str, + resource_group_name: str, + automation_account: str, + job_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get job output + + Get outputs of an Azure Automation job. + + Swagger operation ID: `GetJobOutput`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: The name of the Azure Resource Group. + automation_account: The name of the Azure Automation Account. + job_id: GUID for the ID of the run. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourceGroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Automation" + f"/automationAccounts" + f"/{quote(str(automation_account), safe='')}" + f"/jobs" + f"/{quote(str(job_id), safe='')}" + f"/output" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2015-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def get_status_of_job( + self, + subscription_id: str, + resource_group_name: str, + automation_account: str, + job_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get status of job + + Get Status of a Job + + Swagger operation ID: `GetStatusOfJob`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: The name of the Azure Resource Group. + automation_account: The name of the Azure Automation Account. + job_id: GUID for the ID of the run. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourceGroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Automation" + f"/automationAccounts" + f"/{quote(str(automation_account), safe='')}" + f"/jobs" + f"/{quote(str(job_id), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2015-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_job( + self, + input: CreateJobInput | Mapping[str, Any], + subscription_id: str, + resource_group_name: str, + automation_account: str, + *, + runbook_name: Optional[str] = None, + wait: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create job + + Create Job to run on hybrid worker + + Swagger operation ID: `CreateJob`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: The name of the Azure Resource Group. + automation_account: The name of the Azure Automation Account. + runbook_name: Name of the runbook to run. + wait: Wait for the job to finish before completing the action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourceGroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Automation" + f"/automationAccounts" + f"/{quote(str(automation_account), safe='')}" + f"/jobs" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2015-10-31", safe='')) + if runbook_name is not None: + value = str(runbook_name) + if isinstance(runbook_name, bool): + value = value.lower() + query_params.append(f"runbookName={quote(value, safe='')}") + if wait is not None: + value = str(wait) + if isinstance(wait, bool): + value = value.lower() + query_params.append(f"wait={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_subscriptions( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List subscriptions + + Gets a list of all the subscriptions to which the principal has access. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Subscriptions_List`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/subscriptions" + query_params = [] + query_params.append("x-ms-api-version=" + quote("2015-11-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_resource_groups( + self, + subscription_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List resource groups + + Lists all the resource groups within the subscription. Paginates at + 1,000 records. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ResourceGroups_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2015-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_automation_accounts( + self, + subscription_id: str, + resource_group_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Automation accounts + + Lists Azure Automation accounts in a resource group. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `AutomationAccounts_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: The name of the Azure Resource Group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourceGroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Automation" + f"/automationAccounts" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2015-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_runbooks( + self, + subscription_id: str, + resource_group_name: str, + automation_account: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List runbooks + + Lists Azure Automation runbooks in an automation account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Runbooks_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: The name of the Azure Resource Group. + automation_account: The name of the Azure Automation Account. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourceGroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Automation" + f"/automationAccounts" + f"/{quote(str(automation_account), safe='')}" + f"/runbooks" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2015-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_runbook( + self, + subscription_id: str, + resource_group_name: str, + automation_account: str, + runbook_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get runbook + + Get information on an Azure Automation runbook. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetRunbook`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: The name of the Azure Resource Group. + automation_account: The name of the Azure Automation Account. + runbook_name: The name of the Azure Automation runbook. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourceGroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Automation" + f"/automationAccounts" + f"/{quote(str(automation_account), safe='')}" + f"/runbooks" + f"/{quote(str(runbook_name), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2015-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/azureblob.py b/src/azure/connectors/aio/azureblob.py new file mode 100644 index 0000000..37601d8 --- /dev/null +++ b/src/azure/connectors/aio/azureblob.py @@ -0,0 +1,1473 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# AzureblobClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.azureblob import ( + BlobDataSetsMetadata, + BlobMetadata, + BlobMetadataPage, + BlobMetadataResponse, + DataSetsMetadata, + DataWithSensitivityLabelInfo, + ListOfBlobsWithSensitivityLabels, + ObjectEntity, + SensitivityLabelMetadata, + SharedAccessSignature, + SharedAccessSignatureBlobPolicy, + StorageAccount, + StorageAccountList, + TabularDataSetsMetadata, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "AzureblobClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "BlobMetadataPage", + "BlobMetadataResponse", + "DataSetsMetadata", + "DataWithSensitivityLabelInfo", + "ListOfBlobsWithSensitivityLabels", + "ObjectEntity", + "SensitivityLabelMetadata", + "SharedAccessSignature", + "SharedAccessSignatureBlobPolicy", + "StorageAccount", + "StorageAccountList", + "TabularDataSetsMetadata", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class AzureblobClient(ConnectorClientBase): + """Typed client for azureblob connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a AzureblobClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "azureblob" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def copy_file( + self, + dataset: str, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Copy blob + + This operation copies a blob. If blob is being deleted/renamed on + server right after it was copied, connector may return HTTP 404 error + by it's design. Please use a delay for 1 minute before deleting or + renaming newly created blob. Chunk transfer is not supported in this + action. If source and destination are present in same storage account, + please use relative path. Otherwise, maximum size of a source for copy + blob operation is 50 MB. + + Swagger operation ID: `CopyFile_V2`. + + Args: + dataset: Azure Storage account name or blob endpoint. + source: Specify the url to source blob. + destination: Specify the destination blob path, including the + target blob name. + overwrite: Should the destination blob be overwritten + (true/false)?. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/copyFile" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_block_blob( + self, + input: bytes, + storage_account_name: str, + folder_path: str, + name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Create block blob + + This operation uploads a block blob to Azure Blob Storage. + + Swagger operation ID: `CreateBlockBlob_V2`. + + Args: + input: The binary request body. + storage_account_name: The storage account name. + folder_path: Specify folder path to upload. + name: Specify name of the blob to create. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/codeless" + f"/datasets" + f"/{quote(str(storage_account_name), safe='')}" + f"/CreateBlockBlob" + ) + query_params = [] + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def create_file( + self, + input: bytes, + dataset: str, + folder_path: str, + name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create blob + + This operation uploads a blob to Azure Blob Storage. + + Swagger operation ID: `CreateFile_V2`. + + Args: + input: The binary request body. + dataset: Azure Storage account name or blob endpoint. + folder_path: Specify folder path to upload. + name: Specify name of the blob to create. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/files" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_share_link_by_path( + self, + input: SharedAccessSignatureBlobPolicy | Mapping[str, Any], + storage_account_name: str, + path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create SAS URI by path + + This operation creates a SAS link for a blob using the path. + + Swagger operation ID: `CreateShareLinkByPath_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + storage_account_name: Azure Storage account name or blob endpoint. + path: The unique path of the blob. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(str(storage_account_name), safe='')}" + f"/CreateSharedLinkByPath" + ) + query_params = [] + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_file( + self, + dataset: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete blob + + This operation deletes a blob. + + Swagger operation ID: `DeleteFile_V2`. + + Args: + dataset: Azure Storage account name or blob endpoint. + id: Specify the blob to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def extract_folder( + self, + dataset: str, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Extract archive to folder + + This operation extracts an archive blob into a folder (example: .zip). + + Swagger operation ID: `ExtractFolder_V3`. + + Args: + dataset: Azure Storage account name or blob endpoint. + source: Specify the path to the archive blob. + destination: Specify the path in Azure Blob Storage to extract the + archive contents. + overwrite: Should destination blob be overwritten (true/false)?. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/extractFolderV2" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_access_policies( + self, + storage_account_name: str, + path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get available access policies + + This operation gets available shared access policies for a blob. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAccessPolicies_V2`. + + Args: + storage_account_name: Azure Storage account name or blob endpoint. + path: The unique path of the blob. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(str(storage_account_name), safe='')}" + f"/policies" + ) + query_params = [] + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_file_content( + self, + dataset: str, + id: str, + *, + infer_content_type: Optional[bool] = None, + extract_sensitivity_label: Optional[bool] = None, + purview_account_name: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get blob content + + This operation retrieves blob contents using id. + + Swagger operation ID: `GetFileContent_V2`. + + Args: + dataset: Azure Storage account name or blob endpoint. + id: Specify the blob. + infer_content_type: Infer content-type based on extension. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/content" + ) + query_params = [] + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if purview_account_name is not None: + value = str(purview_account_name) + if isinstance(purview_account_name, bool): + value = value.lower() + query_params.append(f"purviewAccountName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def get_file_content_by_path( + self, + dataset: str, + path: str, + *, + infer_content_type: Optional[bool] = None, + extract_sensitivity_label: Optional[bool] = None, + purview_account_name: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get blob content using path + + This operation retrieves blob contents using path. + + Swagger operation ID: `GetFileContentByPath_V2`. + + Args: + dataset: Azure Storage account name or blob endpoint. + path: Specify unique path to the blob. + infer_content_type: Infer content-type based on extension. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/GetFileContentByPath" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if purview_account_name is not None: + value = str(purview_account_name) + if isinstance(purview_account_name, bool): + value = value.lower() + query_params.append(f"purviewAccountName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def get_file_metadata( + self, + dataset: str, + id: str, + *, + extract_sensitivity_label: Optional[bool] = None, + purview_account_name: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Blob Metadata + + This operation retrieves blob metadata using blob id. + + Swagger operation ID: `GetFileMetadata_V2`. + + Args: + dataset: Azure Storage account name or blob endpoint. + id: Specify the blob. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + query_params = [] + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if purview_account_name is not None: + value = str(purview_account_name) + if isinstance(purview_account_name, bool): + value = value.lower() + query_params.append(f"purviewAccountName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_file_metadata_by_path( + self, + dataset: str, + path: str, + *, + extract_sensitivity_label: Optional[bool] = None, + purview_account_name: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Blob Metadata using path + + This operation retrieves blob metadata using path. + + Swagger operation ID: `GetFileMetadataByPath_V2`. + + Args: + dataset: Azure Storage account name or blob endpoint. + path: Specify unique path to the blob. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/GetFileByPath" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if purview_account_name is not None: + value = str(purview_account_name) + if isinstance(purview_account_name, bool): + value = value.lower() + query_params.append(f"purviewAccountName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_folder( + self, + dataset: str, + id: str, + *, + use_flat_listing: Optional[bool] = None, + extract_sensitivity_label: Optional[bool] = None, + purview_account_name: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Lists blobs + + This operation lists blobs in a container. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListFolder_V4`. + + Args: + dataset: Azure Storage account name or blob endpoint. + id: Specify the folder. + use_flat_listing: Whether or not to list blobs in flat listing\". + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/foldersV2" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + query_params = [] + if use_flat_listing is not None: + value = str(use_flat_listing) + if isinstance(use_flat_listing, bool): + value = value.lower() + query_params.append(f"useFlatListing={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if purview_account_name is not None: + value = str(purview_account_name) + if isinstance(purview_account_name, bool): + value = value.lower() + query_params.append(f"purviewAccountName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_root_folder( + self, + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Lists blobs in the root folder + + This operation lists blobs in the Azure Blob Storage root folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListRootFolder_V4`. + + Args: + dataset: Azure Storage account name or blob endpoint. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/foldersV2" + ) + query_params = [] + query_params.append("useFlatListing=" + quote("false", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def set_blob_tier_by_path( + self, + storage_account_name: str, + path: str, + new_tier: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Set blob tier by path + + This operation sets a tier for a block blob on a standard storage + account using the path. + + Swagger operation ID: `SetBlobTierByPath_V2`. + + Args: + storage_account_name: Azure Storage account name or blob endpoint. + path: The unique path of the blob. + new_tier: The new tier for the blob. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(str(storage_account_name), safe='')}" + f"/SetBlobTierByPath" + ) + query_params = [] + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + value = str(new_tier) + if isinstance(new_tier, bool): + value = value.lower() + query_params.append(f"newTier={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def update_file( + self, + input: bytes, + dataset: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update blob + + This operation updates a blob in Azure Blob Storage. + + Swagger operation ID: `UpdateFile_V2`. + + Args: + input: The binary request body. + dataset: Azure Storage account name or blob endpoint. + id: Specify the blob to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PUT", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_data_sets( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get storage accounts + + This operation list the user's Azure Storage Account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetDataSets`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/codeless/GetDataSets" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/azuredatafactory.py b/src/azure/connectors/aio/azuredatafactory.py new file mode 100644 index 0000000..c674ce4 --- /dev/null +++ b/src/azure/connectors/aio/azuredatafactory.py @@ -0,0 +1,803 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# AzuredatafactoryClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.azuredatafactory import ( + Activity, + ActivityFull, + CreatePipelineRunResponse, + DataFactory, + DataFactoryListResult, + ParameterValueSpecification, + Pipeline, + PipelineListResult, + PipelineRun, + ResourceGroup, + ResourceGroupListResult, + ResourceGroupProperties, + Subscription, + SubscriptionListResult, + SubscriptionPolicies, +) + +__all__ = [ + "AzuredatafactoryClient", + "Activity", + "ActivityFull", + "CreatePipelineRunResponse", + "DataFactory", + "DataFactoryListResult", + "ParameterValueSpecification", + "Pipeline", + "PipelineListResult", + "PipelineRun", + "ResourceGroup", + "ResourceGroupListResult", + "ResourceGroupProperties", + "Subscription", + "SubscriptionListResult", + "SubscriptionPolicies", +] + + +# Type Definitions + +# Client Class + +class AzuredatafactoryClient(ConnectorClientBase): + """Typed client for azuredatafactory connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a AzuredatafactoryClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "azuredatafactory" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_pipeline_run( + self, + input: ParameterValueSpecification | Mapping[str, Any], + subscription_id: str, + resource_group_name: str, + data_factory_name: str, + pipeline_name: str, + *, + reference_pipeline_run_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a pipeline run + + This operation creates a new pipeline run in your factory + + Swagger operation ID: `CreatePipelineRun`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + data_factory_name: The name of the Data Factory. + pipeline_name: The name of the Data Factory pipeline. + reference_pipeline_run_id: The pipeline run identifier. If run ID + is specified the parameters of the specified run will be used + to create a new run. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.DataFactory" + f"/factories" + f"/{quote(str(data_factory_name), safe='')}" + f"/pipelines" + f"/{quote(str(pipeline_name), safe='')}" + f"/CreateRun" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2017-09-01-preview", safe='')) + if reference_pipeline_run_id is not None: + value = str(reference_pipeline_run_id) + if isinstance(reference_pipeline_run_id, bool): + value = value.lower() + query_params.append(f"referencePipelineRunId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def cancel_pipeline_run( + self, + subscription_id: str, + resource_group_name: str, + data_factory_name: str, + pipeline_run_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Cancel a pipeline run + + This operation cancels a pipeline run by its run ID. + + Swagger operation ID: `CancelPipelineRun`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + data_factory_name: The name of the Data Factory. + pipeline_run_name: The id of the Data Factory pipeline run. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.DataFactory" + f"/factories" + f"/{quote(str(data_factory_name), safe='')}" + f"/cancelpipelineRun" + f"/{quote(str(pipeline_run_name), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2017-09-01-preview", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_pipeline_run( + self, + subscription_id: str, + resource_group_name: str, + data_factory_name: str, + pipeline_run_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a pipeline run + + Get a particular pipeline run execution + + Swagger operation ID: `GetPipelineRun`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + data_factory_name: The name of the Data Factory. + pipeline_run_name: The id of the Data Factory pipeline run. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.DataFactory" + f"/factories" + f"/{quote(str(data_factory_name), safe='')}" + f"/pipelineRuns" + f"/{quote(str(pipeline_run_name), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2017-09-01-preview", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_subscriptions( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List subscriptions + + Gets a list of all the subscriptions to which the principal has access. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListSubscriptions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/subscriptions" + query_params = [] + query_params.append("x-ms-api-version=" + quote("2017-09-01-preview", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_resource_groups( + self, + subscription_id: str, + *, + filter: Optional[str] = None, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List resource groups + + Lists all the resource groups within the subscription. The results are + paginated at 1,000+ records. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListResourceGroups`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + filter: The filter to apply on the operation. + top: Query parameters. If nothing is passed returns all values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2017-09-01-preview", safe='')) + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_data_factories( + self, + subscription_id: str, + resource_group_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Factories + + Get the list of Data Factories + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListDataFactories`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.DataFactory" + f"/factories" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2017-09-01-preview", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_pipelines( + self, + subscription_id: str, + resource_group_name: str, + data_factory_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List pipelines + + List the list of pipelines from a particular factory + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListPipelines`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + data_factory_name: The name of the Data Factory. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.DataFactory" + f"/factories" + f"/{quote(str(data_factory_name), safe='')}" + f"/pipelines" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2017-09-01-preview", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/azuredigitaltwins.py b/src/azure/connectors/aio/azuredigitaltwins.py new file mode 100644 index 0000000..cd4bc1b --- /dev/null +++ b/src/azure/connectors/aio/azuredigitaltwins.py @@ -0,0 +1,1520 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# AzuredigitaltwinsClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.azuredigitaltwins import ( + AddModelsInput, + AddRelationshipInput, + AddTwinInput, + GetComponentResult, + GetModelByIdResponse, + IncomingRelationship, + ListIncomingRelationshipsResponse, + ListModelsResponse, + ListRelationshipsResponse, + QueryResult, + QueryTwinsInput, + SendComponentTelemetryInput, + SendTelemetryInput, + TwinRelationship, + TwinResult, + UpdateComponentInput, + UpdateModelInput, + UpdateRelationshipInput, + UpdateTwinInput, +) + +__all__ = [ + "AzuredigitaltwinsClient", + "AddModelsInput", + "AddRelationshipInput", + "AddTwinInput", + "GetComponentResult", + "GetModelByIdResponse", + "IncomingRelationship", + "ListIncomingRelationshipsResponse", + "ListModelsResponse", + "ListRelationshipsResponse", + "QueryResult", + "QueryTwinsInput", + "SendComponentTelemetryInput", + "SendTelemetryInput", + "TwinRelationship", + "TwinResult", + "UpdateComponentInput", + "UpdateModelInput", + "UpdateRelationshipInput", + "UpdateTwinInput", +] + + +# Type Definitions + +# Client Class + +class AzuredigitaltwinsClient(ConnectorClientBase): + """Typed client for azuredigitaltwins connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a AzuredigitaltwinsClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "azuredigitaltwins" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def add_models( + self, + input: AddModelsInput, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Model + + Uploads one or more models. When any error occurs, no models are + uploaded. + + Swagger operation ID: `AddModels`. + + Args: + input: The request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/models" + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_models( + self, + *, + dependencies_for: Optional[str] = None, + include_model_definition: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Models + + Retrieves model metadata and, optionally, model definitions. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListModels`. + + Args: + dependencies_for: The set of the models which will have their + dependencies retrieved. If omitted, all models are retrieved. + include_model_definition: When true the model definition will be + returned as part of the result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/models" + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if dependencies_for is not None: + value = str(dependencies_for) + if isinstance(dependencies_for, bool): + value = value.lower() + query_params.append(f"dependenciesFor={quote(value, safe='')}") + if include_model_definition is not None: + value = str(include_model_definition) + if isinstance(include_model_definition, bool): + value = value.lower() + query_params.append(f"includeModelDefinition={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def delete_model( + self, + modelid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete Model + + Deletes a model. A model can only be deleted if no other models + reference it. + + Swagger operation ID: `DeleteModel`. + + Args: + modelid: The id of the Model. The id is unique within the service + and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/models/{quote(str(modelid), safe='')}" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_model_by_id( + self, + modelid: str, + *, + include_model_definition: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Model By Id + + Retrieves model metadata and, optionally, the model definition. + + Swagger operation ID: `GetModelById`. + + Args: + modelid: The id of the Model. The id is unique within the service + and case sensitive. + include_model_definition: When true the model definition will be + returned as part of the result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/models/{quote(str(modelid), safe='')}" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if include_model_definition is not None: + value = str(include_model_definition) + if isinstance(include_model_definition, bool): + value = value.lower() + query_params.append(f"includeModelDefinition={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_model( + self, + input: UpdateModelInput | Mapping[str, Any], + modelid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update Model's Property + + Updates the metadata for a model. + + Swagger operation ID: `UpdateModel`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + modelid: The id of the Model. The id is unique within the service + and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/models/{quote(str(modelid), safe='')}" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_twin_by_id( + self, + twinid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Twin by Id + + Retrieves a digital twin and its data. + + Swagger operation ID: `GetTwinById`. + + Args: + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/digitaltwins/{quote(str(twinid), safe='')}" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_twin( + self, + twinid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete Twin + + Deletes a digital twin. All relationships referencing the digital twin + must already be deleted. + + Swagger operation ID: `DeleteTwin`. + + Args: + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/digitaltwins/{quote(str(twinid), safe='')}" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_twin( + self, + input: AddTwinInput | Mapping[str, Any], + twinid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Twin + + Adds or replaces a digital twin. + + Swagger operation ID: `AddTwin`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/digitaltwins/{quote(str(twinid), safe='')}" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_twin( + self, + input: UpdateTwinInput | Mapping[str, Any], + twinid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update Twin + + Updates properties on a twin. + + Swagger operation ID: `UpdateTwin`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/digitaltwins/{quote(str(twinid), safe='')}" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_component( + self, + twinid: str, + component_path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Component + + Retrieves a component from a digital twin. + + Swagger operation ID: `GetComponent`. + + Args: + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + component_path: The name of the DTDL component. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/digitaltwins" + f"/{quote(str(twinid), safe='')}" + f"/components" + f"/{quote(str(component_path), safe='')}" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_component( + self, + input: UpdateComponentInput | Mapping[str, Any], + twinid: str, + component_path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update Component + + Updates integer properties on a component of a twin. + + Swagger operation ID: `UpdateComponent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + component_path: The name of the DTDL component. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/digitaltwins" + f"/{quote(str(twinid), safe='')}" + f"/components" + f"/{quote(str(component_path), safe='')}" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_relationship_by_id( + self, + twinid: str, + relationship_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Relationship by Id + + Retrieves a relationship between two digital twins. + + Swagger operation ID: `GetRelationshipById`. + + Args: + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + relationship_id: The id of the relationship. The id is unique + within the digital twin and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/digitaltwins" + f"/{quote(str(twinid), safe='')}" + f"/relationships" + f"/{quote(str(relationship_id), safe='')}" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_relationship( + self, + twinid: str, + relationship_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete Relationship + + Deletes a relationship between two digital twins. + + Swagger operation ID: `DeleteRelationship`. + + Args: + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + relationship_id: The id of the relationship. The id is unique + within the digital twin and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/digitaltwins" + f"/{quote(str(twinid), safe='')}" + f"/relationships" + f"/{quote(str(relationship_id), safe='')}" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_relationship( + self, + input: AddRelationshipInput | Mapping[str, Any], + twinid: str, + relationship_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Relationship + + Adds a relationship between two digital twins. + + Swagger operation ID: `AddRelationship`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + relationship_id: The id of the relationship. The id is unique + within the digital twin and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/digitaltwins" + f"/{quote(str(twinid), safe='')}" + f"/relationships" + f"/{quote(str(relationship_id), safe='')}" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_relationship( + self, + input: UpdateRelationshipInput | Mapping[str, Any], + twinid: str, + relationship_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update Relationship + + Updates integer properties on a relationship between two digital twins. + + Swagger operation ID: `UpdateRelationship`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + relationship_id: The id of the relationship. The id is unique + within the digital twin and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/digitaltwins" + f"/{quote(str(twinid), safe='')}" + f"/relationships" + f"/{quote(str(relationship_id), safe='')}" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + def list_incoming_relationships( + self, + twinid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Incoming Relationships + + Retrieves all incoming relationships for a digital twin. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListIncomingRelationships`. + + Args: + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/digitaltwins" + f"/{quote(str(twinid), safe='')}" + f"/incomingrelationships" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def send_telemetry( + self, + input: SendTelemetryInput | Mapping[str, Any], + twinid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Send Telemetry + + Sends telemetry on behalf of a digital twin. + + Swagger operation ID: `SendTelemetry`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/digitaltwins/{quote(str(twinid), safe='')}/telemetry" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def send_component_telemetry( + self, + input: SendComponentTelemetryInput | Mapping[str, Any], + twinid: str, + component_path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Send Component Telemetry + + Sends telemetry on behalf of a component in a digital twin. + + Swagger operation ID: `SendComponentTelemetry`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + component_path: The name of the DTDL component. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/digitaltwins" + f"/{quote(str(twinid), safe='')}" + f"/components" + f"/{quote(str(component_path), safe='')}" + f"/telemetry" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_relationships( + self, + twinid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Relationships + + Retrieves all outgoing relationships from a digital twin. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListRelationships`. + + Args: + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/digitaltwins/{quote(str(twinid), safe='')}/relationships" + ) + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def query_twins( + self, + input: QueryTwinsInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Query API + + Executes a query that allows traversing relationships and filtering by + property values. + + Swagger operation ID: `QueryTwins`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/query" + query_params = [] + query_params.append("api-version=" + quote("2020-10-31", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/azureeventgrid.py b/src/azure/connectors/aio/azureeventgrid.py new file mode 100644 index 0000000..f6ee586 --- /dev/null +++ b/src/azure/connectors/aio/azureeventgrid.py @@ -0,0 +1,311 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# AzureeventgridClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.azureeventgrid import ( + EventRequest, + EventSchema, + EventTypesResponse, + ResourceNameResponse, + Subscription, + SubscriptionListResult, + TopicTypesResponse, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "AzureeventgridClient", + "EventRequest", + "EventSchema", + "EventTypesResponse", + "ResourceNameResponse", + "Subscription", + "SubscriptionListResult", + "TopicTypesResponse", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class AzureeventgridClient(ConnectorClientBase): + """Typed client for azureeventgrid connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a AzureeventgridClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "azureeventgrid" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_subscriptions( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List subscriptions + + Gets a list of all the subscriptions to which the principal has access. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Subscriptions_List`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/subscriptions" + query_params = [] + query_params.append("x-ms-api-version=" + quote("2015-11-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_topic_types( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + TopicTypes_List + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `TopicTypes_List`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/providers/Microsoft.EventGrid/topicTypes" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2017-09-15-preview", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/azureiotcentral.py b/src/azure/connectors/aio/azureiotcentral.py new file mode 100644 index 0000000..372b738 --- /dev/null +++ b/src/azure/connectors/aio/azureiotcentral.py @@ -0,0 +1,6318 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# AzureiotcentralClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.azureiotcentral import ( + Action, + ActionGroupsAction, + Application, + ApplicationCollection, + CloudPropertyJobData, + CommandJobData, + DateJobSchedule, + Device, + DeviceCloudProperties, + DeviceCollection, + DeviceCommand, + DeviceCommandV1, + DeviceComponentCommand, + DeviceComponentTelemetry, + DeviceGroup, + DeviceGroupCollection, + DeviceGroupDeviceCollection, + DeviceModuleCommand, + DeviceModuleComponentCommand, + DeviceModuleComponentTelemetry, + DeviceModuleTelemetry, + DeviceProperties, + DeviceRelationship, + DeviceRelationshipCollection, + DeviceRelationshipStatic, + DeviceTelemetry, + DeviceTemplate, + DeviceTemplateCollection, + DeviceTemplateCollectionV1, + DeviceTemplateMigrationJobData, + DeviceTemplateV1, + DeviceV1, + DeviceV2, + DynamicValues, + EmailAction, + EmailUser, + Job, + JobBatch, + JobCancellationThreshold, + JobCollection, + JobDeviceStatus, + JobDeviceStatusCollection, + JobSchedule, + JobScheduleEnd, + JobStatic, + LogicAppsAction, + ModuleProperties, + OccurrencesJobSchedule, + Organization, + OrganizationCollection, + OrganizationStatic, + PowerAutomateAction, + PropertyJobData, + Role, + RoleAssignment, + RoleCollection, + Rule, + RuleCollection, + ScheduledJob, + ScheduledJobCollection, + ScheduledJobJobCollection, + ScheduledJobPatch, + ScheduledJobStatic, + SchemaDeviceCloudPropertiesResponse, + SchemaDeviceCommandResponse, + SchemaDevicePropertiesResponse, + SchemaDeviceTelemetryResponse, + SchemaJobResponse, + SchemaScheduledJobResponse, + SchemaUserResponse, + ServicePrincipalUser, + User, + UserCollection, + UserPatch, + UserStatic, + WebhookAction, + WebhookActionBody, + WebhookActionDevice, + WorkflowTrigger, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "AzureiotcentralClient", + "Action", + "ActionGroupsAction", + "Application", + "ApplicationCollection", + "CloudPropertyJobData", + "CommandJobData", + "DateJobSchedule", + "Device", + "DeviceCloudProperties", + "DeviceCollection", + "DeviceCommand", + "DeviceCommandV1", + "DeviceComponentCommand", + "DeviceComponentTelemetry", + "DeviceGroup", + "DeviceGroupCollection", + "DeviceGroupDeviceCollection", + "DeviceModuleCommand", + "DeviceModuleComponentCommand", + "DeviceModuleComponentTelemetry", + "DeviceModuleTelemetry", + "DeviceProperties", + "DeviceRelationship", + "DeviceRelationshipCollection", + "DeviceRelationshipStatic", + "DeviceTelemetry", + "DeviceTemplate", + "DeviceTemplateCollection", + "DeviceTemplateCollectionV1", + "DeviceTemplateMigrationJobData", + "DeviceTemplateV1", + "DeviceV1", + "DeviceV2", + "DynamicValues", + "EmailAction", + "EmailUser", + "Job", + "JobBatch", + "JobCancellationThreshold", + "JobCollection", + "JobDeviceStatus", + "JobDeviceStatusCollection", + "JobSchedule", + "JobScheduleEnd", + "JobStatic", + "LogicAppsAction", + "ModuleProperties", + "OccurrencesJobSchedule", + "Organization", + "OrganizationCollection", + "OrganizationStatic", + "PowerAutomateAction", + "PropertyJobData", + "Role", + "RoleAssignment", + "RoleCollection", + "Rule", + "RuleCollection", + "ScheduledJob", + "ScheduledJobCollection", + "ScheduledJobJobCollection", + "ScheduledJobPatch", + "ScheduledJobStatic", + "SchemaDeviceCloudPropertiesResponse", + "SchemaDeviceCommandResponse", + "SchemaDevicePropertiesResponse", + "SchemaDeviceTelemetryResponse", + "SchemaJobResponse", + "SchemaScheduledJobResponse", + "SchemaUserResponse", + "ServicePrincipalUser", + "User", + "UserCollection", + "UserPatch", + "UserStatic", + "WebhookAction", + "WebhookActionBody", + "WebhookActionDevice", + "WorkflowTrigger", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class AzureiotcentralClient(ConnectorClientBase): + """Typed client for azureiotcentral connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a AzureiotcentralClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "azureiotcentral" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_device_groups( + self, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List device groups + + Get the list of device groups in an application. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `DeviceGroups_List`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/api/ga_2022_07_31/deviceGroups" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def device_groups_get( + self, + device_group_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a device group + + Get details about an existing device group by ID. + + Swagger operation ID: `DeviceGroups_Get`. + + Args: + device_group_id: Unique ID of the device group. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/deviceGroups" + f"/{quote(str(device_group_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def device_groups_set( + self, + input: DeviceGroup | Mapping[str, Any], + device_group_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a device group + + Create or update a device group. + + Swagger operation ID: `DeviceGroups_Set`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_group_id: Unique ID of the device group. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/deviceGroups" + f"/{quote(str(device_group_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def device_groups_remove( + self, + device_group_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete device group + + Delete an existing device group by ID + + Swagger operation ID: `DeviceGroups_Remove`. + + Args: + device_group_id: Unique ID of the device group. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/deviceGroups" + f"/{quote(str(device_group_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_device_groups_get_devices( + self, + device_group_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get devices by device group ID + + Get the list of devices in a device group in an application. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `DeviceGroups_GetDevices`. + + Args: + device_group_id: Unique ID of the device group. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/deviceGroups" + f"/{quote(str(device_group_id), safe='')}" + f"/devices" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def devices_get_cloud_properties( + self, + device_id: str, + application: str, + *, + instance_of: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get device cloud properties (deprecated) + + Get all cloud property values of a device by device ID (deprecated). + + Swagger operation ID: `Devices_GetCloudProperties`. + + Args: + device_id: Unique ID of the device. + application: Unique ID of the application. + instance_of: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/preview" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/cloudProperties" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if instance_of is not None: + value = str(instance_of) + if isinstance(instance_of, bool): + value = value.lower() + query_params.append(f"instanceOf={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_update_cloud_properties( + self, + input: DeviceCloudProperties | Mapping[str, Any], + device_id: str, + application: str, + *, + instance_of: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update device cloud properties (deprecated) + + Update all cloud property values of a device by device ID (deprecated). + + Swagger operation ID: `Devices_UpdateCloudProperties`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + application: Unique ID of the application. + instance_of: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/preview" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/cloudProperties" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if instance_of is not None: + value = str(instance_of) + if isinstance(instance_of, bool): + value = value.lower() + query_params.append(f"instanceOf={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_execute_component_command( + self, + input: DeviceCommand | Mapping[str, Any], + device_id: str, + component_name: str, + command_name: str, + application: str, + *, + instance_of: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Execute a device command (deprecated) + + Execute a command on a device (deprecated). + + Swagger operation ID: `Devices_ExecuteComponentCommand`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + component_name: Name of the device component. + command_name: Name of this device command. + application: Unique ID of the application. + instance_of: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/preview" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/components" + f"/{quote(str(component_name), safe='')}" + f"/commands" + f"/{quote(str(command_name), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if instance_of is not None: + value = str(instance_of) + if isinstance(instance_of, bool): + value = value.lower() + query_params.append(f"instanceOf={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_device_relationships( + self, + device_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List relationships + + List all relationships based on device ID. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `DeviceRelationships_List`. + + Args: + device_id: Unique ID of the device. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/relationships" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def device_relationships_get( + self, + device_id: str, + relationship_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get device relationship + + Get details about an existing device relationship by device ID and by + relationship ID. + + Swagger operation ID: `DeviceRelationships_Get`. + + Args: + device_id: Unique ID of the device. + relationship_id: Unique ID of the device relationship. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/relationships" + f"/{quote(str(relationship_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def device_relationships_set( + self, + input: DeviceRelationship | Mapping[str, Any], + relationship_id: str, + device_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a device relationship + + Create a new device relationship between the given device and a new + device given a device ID and a relationship ID. + + Swagger operation ID: `DeviceRelationships_Set`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + relationship_id: Unique ID of the device relationship. + device_id: Unique ID of the device. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/relationships" + f"/{quote(str(relationship_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def device_relationships_update( + self, + input: DeviceRelationship | Mapping[str, Any], + device_id: str, + relationship_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a device relationship + + Update an existing device relationship between the given device and a + new device given a device ID and a relationship ID. + + Swagger operation ID: `DeviceRelationships_Update`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + relationship_id: Unique ID of the device relationship. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/relationships" + f"/{quote(str(relationship_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def device_relationships_remove( + self, + device_id: str, + relationship_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a device relationship + + Delete an existing device relationship by device ID and relationship + ID. + + Swagger operation ID: `DeviceRelationships_Remove`. + + Args: + device_id: Unique ID of the device. + relationship_id: Unique ID of the device relationship. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/relationships" + f"/{quote(str(relationship_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_jobs( + self, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List jobs + + Get the list of jobs in an application. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Jobs_List`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/ga_2022_07_31/jobs" + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def jobs_get( + self, + job_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a job + + Get details about an existing job by ID. + + Swagger operation ID: `Jobs_Get`. + + Args: + job_id: Unique ID of the job. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/ga_2022_07_31/jobs/{quote(str(job_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def jobs_set( + self, + input: Job | Mapping[str, Any], + job_id: str, + application: str, + *, + job_type: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a job + + Create and execute a new job via its job definition. + + Swagger operation ID: `Jobs_Set`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + job_id: Unique ID of the job. + application: Unique ID of the application. + job_type: Type of the job. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/ga_2022_07_31/jobs/{quote(str(job_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if job_type is not None: + value = str(job_type) + if isinstance(job_type, bool): + value = value.lower() + query_params.append(f"job_type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_jobs_get_devices( + self, + job_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get device statuses + + Get the list of individual device statuses by job ID. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Jobs_GetDevices`. + + Args: + job_id: Unique ID of the job. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/ga_2022_07_31/jobs/{quote(str(job_id), safe='')}/devices" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def jobs_stop( + self, + job_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Stop a running job + + Stop execution of a job that is currently running. + + Swagger operation ID: `Jobs_Stop`. + + Args: + job_id: Unique ID of the job. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/ga_2022_07_31/jobs/{quote(str(job_id), safe='')}/stop" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def jobs_resume( + self, + job_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Resume a stopped job + + Resume execution of an existing stopped job. + + Swagger operation ID: `Jobs_Resume`. + + Args: + job_id: Unique ID of the job. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/ga_2022_07_31/jobs/{quote(str(job_id), safe='')}/resume" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def jobs_rerun( + self, + job_id: str, + rerun_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Resume a job on failed devices + + Execute a rerun of an existing job on all failed devices. + + Swagger operation ID: `Jobs_Rerun`. + + Args: + job_id: Unique ID of the job. + rerun_id: Unique ID of the rerun. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/jobs" + f"/{quote(str(job_id), safe='')}" + f"/rerun" + f"/{quote(str(rerun_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_organizations( + self, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List organizations + + Get the list of organizations in an application. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Organizations_List`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/api/ga_2022_07_31/organizations" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def organizations_get( + self, + organization_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get an organization + + Get details about an existing organization by ID. + + Swagger operation ID: `Organizations_Get`. + + Args: + organization_id: Unique ID of the organization. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/organizations" + f"/{quote(str(organization_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def organizations_set( + self, + input: Organization | Mapping[str, Any], + organization_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create an organization + + Create a new organization. + + Swagger operation ID: `Organizations_Set`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + organization_id: Unique ID of the organization. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/organizations" + f"/{quote(str(organization_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def organizations_remove( + self, + organization_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete organization + + Delete an existing organization by ID + + Swagger operation ID: `Organizations_Remove`. + + Args: + organization_id: Unique ID of the organization. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/organizations" + f"/{quote(str(organization_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_scheduled_jobs( + self, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List scheduled jobs + + Get the list of scheduled jobs in an application. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ScheduledJobs_List`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/api/ga_2022_07_31/scheduledJobs" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def scheduled_jobs_get( + self, + scheduled_job_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a scheduled job + + Get details about an existing scheduled job by ID. + + Swagger operation ID: `ScheduledJobs_Get`. + + Args: + scheduled_job_id: Unique ID of the scheduled job. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/scheduledJobs" + f"/{quote(str(scheduled_job_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def scheduled_jobs_set( + self, + input: ScheduledJob | Mapping[str, Any], + scheduled_job_id: str, + application: str, + *, + job_type: Optional[str] = None, + scheduled_job_end_type: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a scheduled job + + Create and execute a new scheduled job via its job definition. + + Swagger operation ID: `ScheduledJobs_Set`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + scheduled_job_id: Unique ID of the scheduled job. + application: Unique ID of the application. + job_type: Type of the job. + scheduled_job_end_type: How the scheduled job should end (not + applied to device template migrations). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/scheduledJobs" + f"/{quote(str(scheduled_job_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if job_type is not None: + value = str(job_type) + if isinstance(job_type, bool): + value = value.lower() + query_params.append(f"job_type={quote(value, safe='')}") + if scheduled_job_end_type is not None: + value = str(scheduled_job_end_type) + if isinstance(scheduled_job_end_type, bool): + value = value.lower() + query_params.append(f"scheduled_job_end_type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def scheduled_jobs_update( + self, + input: ScheduledJobPatch | Mapping[str, Any], + scheduled_job_id: str, + application: str, + *, + scheduled_job_end_type: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a scheduled job + + Update an existing scheduled job by ID. + + Swagger operation ID: `ScheduledJobs_Update`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + scheduled_job_id: Unique ID of the scheduled job. + application: Unique ID of the application. + scheduled_job_end_type: How the scheduled job should end (not + applied to device template migrations). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/scheduledJobs" + f"/{quote(str(scheduled_job_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if scheduled_job_end_type is not None: + value = str(scheduled_job_end_type) + if isinstance(scheduled_job_end_type, bool): + value = value.lower() + query_params.append(f"scheduled_job_end_type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def scheduled_jobs_remove( + self, + scheduled_job_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a scheduled job + + Delete an existing scheduled job by ID. + + Swagger operation ID: `ScheduledJobs_Remove`. + + Args: + scheduled_job_id: Unique ID of the scheduled job. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/scheduledJobs" + f"/{quote(str(scheduled_job_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_scheduled_jobs_list_jobs( + self, + scheduled_job_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get jobs by scheduled job ID + + Get the list of jobs for a scheduled job definition. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ScheduledJobs_ListJobs`. + + Args: + scheduled_job_id: Unique ID of the scheduled job. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/ga_2022_07_31" + f"/scheduledJobs" + f"/{quote(str(scheduled_job_id), safe='')}" + f"/jobs" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def devices_get( + self, + device_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a device by ID + + Get details about an existing device by device ID. + + Swagger operation ID: `Devices_Get_V1`. + + Args: + device_id: Unique ID of the device. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/devices/{quote(str(device_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_get_command_response( + self, + device_id: str, + command_name: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get device command response + + Get the last response for a device command. + + Swagger operation ID: `Devices_GetCommandResponse_V1`. + + Args: + device_id: Unique ID of the device. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/commands" + f"/{quote(str(command_name), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_get_component_command_response( + self, + device_id: str, + component_name: str, + command_name: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get component command response + + Get the last response for a device component command. + + Swagger operation ID: `Devices_GetComponentCommandResponse_V1`. + + Args: + device_id: Unique ID of the device. + component_name: Name of the device component. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/components" + f"/{quote(str(component_name), safe='')}" + f"/commands" + f"/{quote(str(command_name), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_get_component_telemetry_value( + self, + device_id: str, + component_name: str, + telemetry_name: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get component telemetry value + + Get the last telemetry value from a component. + + Swagger operation ID: `Devices_GetComponentTelemetryValue_V1`. + + Args: + device_id: Unique ID of the device. + component_name: Name of the device component. + telemetry_name: Name of this device telemetry. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/components" + f"/{quote(str(component_name), safe='')}" + f"/telemetry" + f"/{quote(str(telemetry_name), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_get_module_command_response( + self, + device_id: str, + module: str, + command_name: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get module command response + + Get the last response for a device module command + + Swagger operation ID: `Devices_GetModuleCommandResponse_V1`. + + Args: + device_id: Unique ID of the device. + module: Name of the device module. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/modules" + f"/{quote(str(module), safe='')}" + f"/commands" + f"/{quote(str(command_name), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_get_module_component_command_response( + self, + device_id: str, + module: str, + component_name: str, + command_name: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get module component command response + + Get the last response for a module component command. + + Swagger operation ID: `Devices_GetModuleComponentCommandResponse_V1`. + + Args: + device_id: Unique ID of the device. + module: Name of the device module. + component_name: Name of the device component. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/modules" + f"/{quote(str(module), safe='')}" + f"/components" + f"/{quote(str(component_name), safe='')}" + f"/commands" + f"/{quote(str(command_name), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_get_module_component_telemetry_value( + self, + device_id: str, + module: str, + component_name: str, + telemetry_name: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get module component telemetry value + + Get the last telemetry value from a module component. + + Swagger operation ID: `Devices_GetModuleComponentTelemetryValue_V1`. + + Args: + device_id: Unique ID of the device. + module: Name of the device module. + component_name: Name of the device component. + telemetry_name: Name of this device telemetry. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/modules" + f"/{quote(str(module), safe='')}" + f"/components" + f"/{quote(str(component_name), safe='')}" + f"/telemetry" + f"/{quote(str(telemetry_name), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_get_module_properties( + self, + device_id: str, + module: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get module properties + + Get all property values of a module. + + Swagger operation ID: `Devices_GetModuleProperties_V1`. + + Args: + device_id: Unique ID of the device. + module: Name of the device module. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/modules" + f"/{quote(str(module), safe='')}" + f"/properties" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_get_module_telemetry_value( + self, + device_id: str, + module: str, + telemetry_name: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get module telemetry value + + Get the last telemetry value from a module. + + Swagger operation ID: `Devices_GetModuleTelemetryValue_V1`. + + Args: + device_id: Unique ID of the device. + module: Name of the device module. + telemetry_name: Name of this device telemetry. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/modules" + f"/{quote(str(module), safe='')}" + f"/telemetry" + f"/{quote(str(telemetry_name), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_get_properties( + self, + device_id: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get device properties + + Get all property values of a device by device ID. + + Swagger operation ID: `Devices_GetProperties_V1`. + + Args: + device_id: Unique ID of the device. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/devices/{quote(str(device_id), safe='')}/properties" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_get_telemetry_value( + self, + device_id: str, + telemetry_name: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get device telemetry value + + Get the last telemetry value from a device. + + Swagger operation ID: `Devices_GetTelemetryValue_V1`. + + Args: + device_id: Unique ID of the device. + telemetry_name: Name of this device telemetry. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/telemetry" + f"/{quote(str(telemetry_name), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_devices( + self, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List devices + + Get the list of devices in an application. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Devices_List_V1`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/v1/devices" + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def devices_remove( + self, + device_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a device + + Delete an existing device by device ID. + + Swagger operation ID: `Devices_Remove_V1`. + + Args: + device_id: Unique ID of the device. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/devices/{quote(str(device_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def devices_run_command( + self, + input: DeviceCommandV1 | Mapping[str, Any], + device_id: str, + command_name: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Run a device command + + Run a command on a device. + + Swagger operation ID: `Devices_RunCommand_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/commands" + f"/{quote(str(command_name), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_run_component_command( + self, + input: DeviceComponentCommand | Mapping[str, Any], + device_id: str, + component_name: str, + command_name: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Run a component command + + Run a command on a component. + + Swagger operation ID: `Devices_RunComponentCommand_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + component_name: Name of the device component. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/components" + f"/{quote(str(component_name), safe='')}" + f"/commands" + f"/{quote(str(command_name), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_run_module_command( + self, + input: DeviceModuleCommand | Mapping[str, Any], + device_id: str, + module: str, + command_name: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Run a module command + + Run a command on a module. + + Swagger operation ID: `Devices_RunModuleCommand_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + module: Name of the device module. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/modules" + f"/{quote(str(module), safe='')}" + f"/commands" + f"/{quote(str(command_name), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_run_module_component_command( + self, + input: DeviceModuleComponentCommand | Mapping[str, Any], + device_id: str, + module: str, + component_name: str, + command_name: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Run a module component command + + Run a command on a module component. + + Swagger operation ID: `Devices_RunModuleComponentCommand_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + module: Name of the device module. + component_name: Name of the device component. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/modules" + f"/{quote(str(module), safe='')}" + f"/components" + f"/{quote(str(component_name), safe='')}" + f"/commands" + f"/{quote(str(command_name), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_set( + self, + input: DeviceV2 | Mapping[str, Any], + device_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create or update a device + + Create a new device or update an existing one by device ID. + + Swagger operation ID: `Devices_Set_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/ga_2022_07_31/devices/{quote(str(device_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_update_module_properties( + self, + input: ModuleProperties | Mapping[str, Any], + device_id: str, + module: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update module properties + + Update all property values of a module. + + Swagger operation ID: `Devices_UpdateModuleProperties_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + module: Name of the device module. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/devices" + f"/{quote(str(device_id), safe='')}" + f"/modules" + f"/{quote(str(module), safe='')}" + f"/properties" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def devices_update_properties( + self, + input: DeviceProperties | Mapping[str, Any], + device_id: str, + application: str, + *, + template: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update device properties + + Update all property values of a device by device ID. + + Swagger operation ID: `Devices_UpdateProperties_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/devices/{quote(str(device_id), safe='')}/properties" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def device_templates_get( + self, + template_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a device template by ID + + Get details about an existing device template by ID. + + Swagger operation ID: `DeviceTemplates_Get_V1`. + + Args: + template_id: Unique ID of the template. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/deviceTemplates/{quote(str(template_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_device_templates( + self, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List device templates + + Get the list of device templates in an application. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `DeviceTemplates_List_V1`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/v1/deviceTemplates" + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def device_templates_remove( + self, + template_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a device template + + Delete an existing device template by ID. + + Swagger operation ID: `DeviceTemplates_Remove_V1`. + + Args: + template_id: Unique ID of the template. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/deviceTemplates/{quote(str(template_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def roles_get( + self, + role_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get role + + Get a role by ID. + + Swagger operation ID: `Roles_Get_V1`. + + Args: + role_id: Unique ID for the role. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/roles/{quote(str(role_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_roles( + self, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List roles + + Get the list of roles in an application. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Roles_List_V1`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/v1/roles" + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def users_create( + self, + input: User | Mapping[str, Any], + user_id: str, + application: str, + *, + user_type: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create user + + Create a user in the application + + Swagger operation ID: `Users_Create_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + user_id: Unique ID of the user. + application: Unique ID of the application. + user_type: Type of the user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/users/{quote(str(user_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if user_type is not None: + value = str(user_type) + if isinstance(user_type, bool): + value = value.lower() + query_params.append(f"user_type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def users_get( + self, + user_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get user + + Get a user by ID + + Swagger operation ID: `Users_Get_V1`. + + Args: + user_id: Unique ID of the user. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/users/{quote(str(user_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_users( + self, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List users + + Get the list of users in an application + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Users_List_V1`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/v1/users" + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def users_remove( + self, + user_id: str, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete user + + Delete a user + + Swagger operation ID: `Users_Remove_V1`. + + Args: + user_id: Unique ID of the user. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/users/{quote(str(user_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def users_update( + self, + input: UserPatch | Mapping[str, Any], + user_id: str, + application: str, + *, + user_type: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update user + + Update a user in the application via patch + + Swagger operation ID: `Users_Update_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + user_id: Unique ID of the user. + application: Unique ID of the application. + user_type: Type of the user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/users/{quote(str(user_id), safe='')}" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if user_type is not None: + value = str(user_type) + if isinstance(user_type, bool): + value = value.lower() + query_params.append(f"user_type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_applications( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get the list of applications accessible to the signed-in user + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Applications_List`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/api/preview/applications" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_device_templates_2( + self, + application: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List device templates + + Get the list of device templates in an application. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `DeviceTemplates_List`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/api/preview/deviceTemplates" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_workflow_get_components( + self, + application: str, + template: str, + *, + module: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Workflow_GetComponents + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Workflow_GetComponents`. + + Args: + application: Unique ID of the application. + template: template. + module: module. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/preview/_internal/workflow/components" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if module is not None: + value = str(module) + if isinstance(module, bool): + value = value.lower() + query_params.append(f"module={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_workflow_get_capabilities( + self, + application: str, + template: str, + *, + component: Optional[str] = None, + module: Optional[str] = None, + type_: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Workflow_GetCapabilities + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Workflow_GetCapabilities`. + + Args: + application: Unique ID of the application. + template: template. + component: component. + module: module. + type_: type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/preview/_internal/workflow/capabilities" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if component is not None: + value = str(component) + if isinstance(component, bool): + value = value.lower() + query_params.append(f"component={quote(value, safe='')}") + if module is not None: + value = str(module) + if isinstance(module, bool): + value = value.lower() + query_params.append(f"module={quote(value, safe='')}") + if type_ is not None: + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_workflow_get_capabilities_v1( + self, + application: str, + template: str, + *, + component: Optional[str] = None, + module: Optional[str] = None, + type_: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Workflow_GetCapabilities_V1 + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Workflow_GetCapabilities_V1`. + + Args: + application: Unique ID of the application. + template: template. + component: component. + module: module. + type_: type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/_internal/workflow/capabilities" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if component is not None: + value = str(component) + if isinstance(component, bool): + value = value.lower() + query_params.append(f"component={quote(value, safe='')}") + if module is not None: + value = str(module) + if isinstance(module, bool): + value = value.lower() + query_params.append(f"module={quote(value, safe='')}") + if type_ is not None: + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_workflow_get_components_v1( + self, + application: str, + template: str, + *, + module: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Workflow_GetComponents_V1 + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Workflow_GetComponents_V1`. + + Args: + application: Unique ID of the application. + template: template. + module: module. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/_internal/workflow/components" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if module is not None: + value = str(module) + if isinstance(module, bool): + value = value.lower() + query_params.append(f"module={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_workflow_get_modules( + self, + application: str, + template: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Workflow_GetModules + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Workflow_GetModules_V1`. + + Args: + application: Unique ID of the application. + template: template. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/api/v1/_internal/workflow/modules" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def schema_device_cloud_properties( + self, + application: str, + *, + instance_of: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Schema_DeviceCloudProperties + + Swagger operation ID: `Schema_DeviceCloudProperties`. + + Args: + application: Unique ID of the application. + instance_of: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/preview/_internal/workflow/schema/DeviceCloudProperties" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if instance_of is not None: + value = str(instance_of) + if isinstance(instance_of, bool): + value = value.lower() + query_params.append(f"instanceOf={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def schema_device_command( + self, + application: str, + *, + instance_of: Optional[str] = None, + component: Optional[str] = None, + capability: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Schema_DeviceCommand + + Swagger operation ID: `Schema_DeviceCommand`. + + Args: + application: Unique ID of the application. + instance_of: The device template definition for the device. + component: component. + capability: capability. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/preview/_internal/workflow/schema/DeviceCommand" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if instance_of is not None: + value = str(instance_of) + if isinstance(instance_of, bool): + value = value.lower() + query_params.append(f"instanceOf={quote(value, safe='')}") + if component is not None: + value = str(component) + if isinstance(component, bool): + value = value.lower() + query_params.append(f"component={quote(value, safe='')}") + if capability is not None: + value = str(capability) + if isinstance(capability, bool): + value = value.lower() + query_params.append(f"capability={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def schema_device_command_v1( + self, + application: str, + *, + template: Optional[str] = None, + module: Optional[str] = None, + component: Optional[str] = None, + capability: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Schema_DeviceCommand_V1 + + Swagger operation ID: `Schema_DeviceCommand_V1`. + + Args: + application: Unique ID of the application. + template: The device template definition for the device. + module: module. + component: component. + capability: capability. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/_internal/workflow/schema/DeviceCommand" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if module is not None: + value = str(module) + if isinstance(module, bool): + value = value.lower() + query_params.append(f"module={quote(value, safe='')}") + if component is not None: + value = str(component) + if isinstance(component, bool): + value = value.lower() + query_params.append(f"component={quote(value, safe='')}") + if capability is not None: + value = str(capability) + if isinstance(capability, bool): + value = value.lower() + query_params.append(f"capability={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def schema_device_properties( + self, + application: str, + *, + template: Optional[str] = None, + module: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Schema_DeviceProperties + + Swagger operation ID: `Schema_DeviceProperties_V1`. + + Args: + application: Unique ID of the application. + template: The device template definition for the device. + module: module. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/_internal/workflow/schema/DeviceProperties" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if module is not None: + value = str(module) + if isinstance(module, bool): + value = value.lower() + query_params.append(f"module={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def schema_device_telemetry( + self, + application: str, + *, + template: Optional[str] = None, + module: Optional[str] = None, + component: Optional[str] = None, + capability: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Schema_DeviceTelemetry + + Swagger operation ID: `Schema_DeviceTelemetry_V1`. + + Args: + application: Unique ID of the application. + template: The device template definition for the device. + module: module. + component: component. + capability: capability. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/_internal/workflow/schema/DeviceTelemetry" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if template is not None: + value = str(template) + if isinstance(template, bool): + value = value.lower() + query_params.append(f"template={quote(value, safe='')}") + if module is not None: + value = str(module) + if isinstance(module, bool): + value = value.lower() + query_params.append(f"module={quote(value, safe='')}") + if component is not None: + value = str(component) + if isinstance(component, bool): + value = value.lower() + query_params.append(f"component={quote(value, safe='')}") + if capability is not None: + value = str(capability) + if isinstance(capability, bool): + value = value.lower() + query_params.append(f"capability={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def schema_job( + self, + application: str, + *, + job_type: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Schema_Job + + Swagger operation ID: `Schema_Job`. + + Args: + application: Unique ID of the application. + job_type: job_type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/ga_2022_07_31/_internal/workflow/schema/Job" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if job_type is not None: + value = str(job_type) + if isinstance(job_type, bool): + value = value.lower() + query_params.append(f"job_type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def schema_scheduled_job( + self, + application: str, + *, + scheduled_job_end_type: Optional[str] = None, + job_type: Optional[str] = None, + patch: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Schema_ScheduledJob + + Swagger operation ID: `Schema_ScheduledJob`. + + Args: + application: Unique ID of the application. + scheduled_job_end_type: scheduled_job_end_type. + job_type: job_type. + patch: patch. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/ga_2022_07_31/_internal/workflow/schema/ScheduledJob" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if scheduled_job_end_type is not None: + value = str(scheduled_job_end_type) + if isinstance(scheduled_job_end_type, bool): + value = value.lower() + query_params.append(f"scheduled_job_end_type={quote(value, safe='')}") + if job_type is not None: + value = str(job_type) + if isinstance(job_type, bool): + value = value.lower() + query_params.append(f"job_type={quote(value, safe='')}") + if patch is not None: + value = str(patch) + if isinstance(patch, bool): + value = value.lower() + query_params.append(f"patch={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def schema_user( + self, + application: str, + *, + user_type: Optional[str] = None, + patch: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Schema_User + + Swagger operation ID: `Schema_User_V1`. + + Args: + application: Unique ID of the application. + user_type: user_type. + patch: patch. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/_internal/workflow/schema/User" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if user_type is not None: + value = str(user_type) + if isinstance(user_type, bool): + value = value.lower() + query_params.append(f"user_type={quote(value, safe='')}") + if patch is not None: + value = str(patch) + if isinstance(patch, bool): + value = value.lower() + query_params.append(f"patch={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def schema_webhook_action_body( + self, + application: str, + *, + rule: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Schema_WebhookActionBody + + Swagger operation ID: `Schema_WebhookActionBody`. + + Args: + application: Unique ID of the application. + rule: rule. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/preview/_internal/workflow/schema/WebhookActionBody" + ) + query_params = [] + value = str(application) + if isinstance(application, bool): + value = value.lower() + query_params.append(f"application={quote(value, safe='')}") + if rule is not None: + value = str(rule) + if isinstance(rule, bool): + value = value.lower() + query_params.append(f"rule={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) diff --git a/src/azure/connectors/aio/azuremonitorlogs.py b/src/azure/connectors/aio/azuremonitorlogs.py new file mode 100644 index 0000000..0fb96d7 --- /dev/null +++ b/src/azure/connectors/aio/azuremonitorlogs.py @@ -0,0 +1,756 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# AzuremonitorlogsClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.azuremonitorlogs import ( + ObjectEntity, + PartialQueryError, + QueryDataInput, + QuerySchemaInput, + ResourceGroup, + ResourceGroupListResult, + ResourceItem, + ResourceItemListResult, + Row, + Subscription, + SubscriptionListResult, + Table, + TimeRangeItem, + TimeRangeListResult, + TimeRangeTypesListResult, + VisualizeQueryInput, + VisualizeResults, +) + +__all__ = [ + "AzuremonitorlogsClient", + "ObjectEntity", + "PartialQueryError", + "QueryDataInput", + "QuerySchemaInput", + "ResourceGroup", + "ResourceGroupListResult", + "ResourceItem", + "ResourceItemListResult", + "Row", + "Subscription", + "SubscriptionListResult", + "Table", + "TimeRangeItem", + "TimeRangeListResult", + "TimeRangeTypesListResult", + "VisualizeQueryInput", + "VisualizeResults", +] + + +# Type Definitions + +# Client Class + +class AzuremonitorlogsClient(ConnectorClientBase): + """Typed client for azuremonitorlogs connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a AzuremonitorlogsClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "azuremonitorlogs" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def query_data( + self, + input: QueryDataInput | Mapping[str, Any], + subscriptions: str, + resourcegroups: str, + resourcetype: str, + resourcename: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Run query and list results + + Returns each row as its own object. Use this action when you want to + work with each row separately in the rest of the workflow. + + Swagger operation ID: `QueryDataV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscriptions: Select subscription. + resourcegroups: Select resource group. + resourcetype: Select Resource Type. + resourcename: Select Resource. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/queryDataV2" + query_params = [] + value = str(subscriptions) + if isinstance(subscriptions, bool): + value = value.lower() + query_params.append(f"subscriptions={quote(value, safe='')}") + value = str(resourcegroups) + if isinstance(resourcegroups, bool): + value = value.lower() + query_params.append(f"resourcegroups={quote(value, safe='')}") + value = str(resourcetype) + if isinstance(resourcetype, bool): + value = value.lower() + query_params.append(f"resourcetype={quote(value, safe='')}") + value = str(resourcename) + if isinstance(resourcename, bool): + value = value.lower() + query_params.append(f"resourcename={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def visualize_query( + self, + input: VisualizeQueryInput | Mapping[str, Any], + subscriptions: str, + resourcegroups: str, + resourcetype: str, + resourcename: str, + vis_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Run query and visualize results + + Returns all rows in the result set as a single formatted object. Use + this action when you want to use the result set together in the rest of + the workflow. + + Swagger operation ID: `VisualizeQueryV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscriptions: Select subscription. + resourcegroups: Select resource group. + resourcetype: Select Resource Type. + resourcename: Select Resource. + vis_type: Specify the resulting chart type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/visualizeQueryV2" + query_params = [] + value = str(subscriptions) + if isinstance(subscriptions, bool): + value = value.lower() + query_params.append(f"subscriptions={quote(value, safe='')}") + value = str(resourcegroups) + if isinstance(resourcegroups, bool): + value = value.lower() + query_params.append(f"resourcegroups={quote(value, safe='')}") + value = str(resourcetype) + if isinstance(resourcetype, bool): + value = value.lower() + query_params.append(f"resourcetype={quote(value, safe='')}") + value = str(resourcename) + if isinstance(resourcename, bool): + value = value.lower() + query_params.append(f"resourcename={quote(value, safe='')}") + value = str(vis_type) + if isinstance(vis_type, bool): + value = value.lower() + query_params.append(f"visType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_subscriptions( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List subscriptions + + Gets a list of all the subscriptions to which the principal has access. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListSubscriptions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/listSubscriptions" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_resource_groups( + self, + subscriptions: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List resource groups + + Lists all the resource groups within the subscription. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListResourceGroups`. + + Args: + subscriptions: Select subscription. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/listResourceGroups" + query_params = [] + value = str(subscriptions) + if isinstance(subscriptions, bool): + value = value.lower() + query_params.append(f"subscriptions={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_resources( + self, + subscriptions: str, + resourcegroups: str, + resourcetype: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List resources + + Lists all the resource groups within the resource group. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListResources`. + + Args: + subscriptions: Select subscription. + resourcegroups: Select resource group. + resourcetype: Select Resource Type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/listResources" + query_params = [] + value = str(subscriptions) + if isinstance(subscriptions, bool): + value = value.lower() + query_params.append(f"subscriptions={quote(value, safe='')}") + value = str(resourcegroups) + if isinstance(resourcegroups, bool): + value = value.lower() + query_params.append(f"resourcegroups={quote(value, safe='')}") + value = str(resourcetype) + if isinstance(resourcetype, bool): + value = value.lower() + query_params.append(f"resourcetype={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def query_schema( + self, + input: QuerySchemaInput, + subscriptions: str, + resourcegroups: str, + resourcetype: str, + resourcename: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get query schema + + Gets the schema for a specific query. + + Swagger operation ID: `QuerySchemaV2`. + + Args: + input: The request body. + subscriptions: Select subscription. + resourcegroups: Select resource group. + resourcetype: Select Resource Type. + resourcename: Select Resource. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/querySchemaV2" + query_params = [] + value = str(subscriptions) + if isinstance(subscriptions, bool): + value = value.lower() + query_params.append(f"subscriptions={quote(value, safe='')}") + value = str(resourcegroups) + if isinstance(resourcegroups, bool): + value = value.lower() + query_params.append(f"resourcegroups={quote(value, safe='')}") + value = str(resourcetype) + if isinstance(resourcetype, bool): + value = value.lower() + query_params.append(f"resourcetype={quote(value, safe='')}") + value = str(resourcename) + if isinstance(resourcename, bool): + value = value.lower() + query_params.append(f"resourcename={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_time_range_selection_control( + self, + timerangetype: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Returns the control schema according to to the given time range type + + Returns the Relative\\Absolute\\Set in query time range control. + + Swagger operation ID: `getTimeRangeSelectionControl`. + + Args: + timerangetype: The Time Range type that the control represents. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/getTimeRangeSelectionControl" + ) + query_params = [] + value = str(timerangetype) + if isinstance(timerangetype, bool): + value = value.lower() + query_params.append(f"timerangetype={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/azurequeues.py b/src/azure/connectors/aio/azurequeues.py new file mode 100644 index 0000000..c901732 --- /dev/null +++ b/src/azure/connectors/aio/azurequeues.py @@ -0,0 +1,598 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# AzurequeuesClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.azurequeues import ( + MessagePost, + Messages, + PutMessageInput, + QueueArray, + QueueInfo, + QueueMessage, + QueueMessagesList, + StorageAccount, + StorageAccountList, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "AzurequeuesClient", + "MessagePost", + "Messages", + "PutMessageInput", + "QueueArray", + "QueueInfo", + "QueueMessage", + "QueueMessagesList", + "StorageAccount", + "StorageAccountList", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class AzurequeuesClient(ConnectorClientBase): + """Typed client for azurequeues connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a AzurequeuesClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "azurequeues" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def delete_message( + self, + storage_account_name: str, + queue_name: str, + message_id: str, + popreceipt: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete message + + Delete a specific message from the queue. + + Swagger operation ID: `DeleteMessage_V2`. + + Args: + storage_account_name: Azure Storage account name or queue endpoint. + queue_name: The queue to delete a message from. + message_id: The ID of the message to delete. + popreceipt: A valid pop receipt value returned from an earlier call + to the Get Messages. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/queues" + f"/{quote(str(queue_name), safe='')}" + f"/messages" + f"/{quote(str(message_id), safe='')}" + ) + query_params = [] + value = str(popreceipt) + if isinstance(popreceipt, bool): + value = value.lower() + query_params.append(f"popreceipt={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_messages( + self, + storage_account_name: str, + queue_name: str, + *, + numofmessages: Optional[str] = None, + visibilitytimeout: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get messages + + Get a specific set of messages from the queue. The messages will be + hidden but remain on the queue until the delete action is used. + + Swagger operation ID: `GetMessages_V2`. + + Args: + storage_account_name: Azure Storage account name or queue endpoint. + queue_name: The queue to get Messages from. + numofmessages: The number of messages to grab from the queue + (default 1). + visibilitytimeout: The time in seconds that messages will be + invisible to other consumers (default 30). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/queues" + f"/{quote(str(queue_name), safe='')}" + f"/messages" + ) + query_params = [] + if numofmessages is not None: + value = str(numofmessages) + if isinstance(numofmessages, bool): + value = value.lower() + query_params.append(f"numofmessages={quote(value, safe='')}") + if visibilitytimeout is not None: + value = str(visibilitytimeout) + if isinstance(visibilitytimeout, bool): + value = value.lower() + query_params.append(f"visibilitytimeout={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_queues( + self, + storage_account_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List queues + + List all the queues for your storage account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListQueues_V2`. + + Args: + storage_account_name: Azure Storage account name or queue endpoint. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/queues" + f"/list" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def put_message( + self, + input: PutMessageInput, + storage_account_name: str, + queue_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Put a message on a queue + + Adds a message to the given queue. + + Swagger operation ID: `PutMessage_V2`. + + Args: + input: The request body. + storage_account_name: Azure Storage account name or queue endpoint. + queue_name: The queue to put a message to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/queues" + f"/{quote(str(queue_name), safe='')}" + f"/messages" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def put_queue( + self, + storage_account_name: str, + queue_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a new queue + + Adds a queue to your account. + + Swagger operation ID: `PutQueue_V2`. + + Args: + storage_account_name: Azure Storage account name or queue endpoint. + queue_name: The name of the queue to create. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/queues" + f"/putQueue" + ) + query_params = [] + value = str(queue_name) + if isinstance(queue_name, bool): + value = value.lower() + query_params.append(f"queueName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_storage_accounts( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get storage accounts + + This operation list the user's Azure Storage Account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetStorageAccounts`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/GetStorageAccounts" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/azuretables.py b/src/azure/connectors/aio/azuretables.py new file mode 100644 index 0000000..d2a720e --- /dev/null +++ b/src/azure/connectors/aio/azuretables.py @@ -0,0 +1,1182 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# AzuretablesClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core import MatchConditions +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.azuretables import ( + CreateEntityInput, + CreateTableInput, + EntityItem, + GetEntitiesResponse, + GetEntityResponse, + GetTableResponse, + GetTablesResponse, + InsertEntityResponse, + InsertMergeEntityInput, + InsertReplaceEntityInput, + MergeEntityInput, + ReplaceEntityInput, + StorageAccount, + StorageAccountList, +) + +__all__ = [ + "AzuretablesClient", + "CreateEntityInput", + "CreateTableInput", + "EntityItem", + "GetEntitiesResponse", + "GetEntityResponse", + "GetTableResponse", + "GetTablesResponse", + "InsertEntityResponse", + "InsertMergeEntityInput", + "InsertReplaceEntityInput", + "MergeEntityInput", + "ReplaceEntityInput", + "StorageAccount", + "StorageAccountList", +] + + +# Type Definitions + +# Client Class + +class AzuretablesClient(ConnectorClientBase): + """Typed client for azuretables connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a AzuretablesClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "azuretables" + + @staticmethod + def _prepare_match_headers( + headers: Optional[Mapping[str, str]], + etag: Optional[str], + match_condition: Optional[MatchConditions], + *, + if_match_required: bool, + ) -> Optional[Mapping[str, str]]: + request_headers = dict(headers) if headers is not None else {} + existing_if_match = next( + (name for name in request_headers if name.lower() == "if-match"), + None, + ) + if etag is None and match_condition is None: + if if_match_required and existing_if_match is None: + request_headers["If-Match"] = "*" + return request_headers or None + + if existing_if_match is not None: + del request_headers[existing_if_match] + if match_condition is None: + assert etag is not None + request_headers["If-Match"] = etag + elif match_condition == MatchConditions.IfNotModified: + if etag is None: + raise ValueError( + "etag is required for MatchConditions.IfNotModified." + ) + request_headers["If-Match"] = etag + elif match_condition == MatchConditions.Unconditionally: + request_headers["If-Match"] = "*" + else: + raise ValueError( + "If-Match operations support only IfNotModified or Unconditionally." + ) + return request_headers or None + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_entity( + self, + input: CreateEntityInput | Mapping[str, Any], + storage_account_name: str, + table_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Insert Entity + + Operation to add an entity to a table. + + Swagger operation ID: `CreateEntity_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table_name), safe='')}" + f"/entities" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_table( + self, + input: CreateTableInput, + storage_account_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create table + + This operation adds a table to the storage account. + + Swagger operation ID: `CreateTable_V2`. + + Args: + input: The request body. + storage_account_name: Azure Storage account name or table endpoint. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/tables" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_entity( + self, + storage_account_name: str, + table_name: str, + partition_key: str, + row_key: str, + *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete Entity + + Operation to delete an entity. + + Swagger operation ID: `DeleteEntity_V2`. + + Args: + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + partition_key: The partition id containing this entity. + row_key: The row id containing this entity. + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=False, + ) + + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table_name), safe='')}" + f"/entities" + f"/etag(PartitionKey='" + f"{quote(str(partition_key), safe='')}" + f"',RowKey='" + f"{quote(str(row_key), safe='')}" + f"')" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def delete_table( + self, + storage_account_name: str, + table_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a table + + Delete a table. + + Swagger operation ID: `DeleteTable_V2`. + + Args: + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table_name), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_entities( + self, + storage_account_name: str, + table_name: str, + *, + filter: Optional[str] = None, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get entities + + This operation queries the entities in a table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetEntities_V2`. + + Args: + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + filter: OData filter query for which entities to return. Example: + Column eq 'Value' and Column2 ne 2. Invalid OData queries, such + as not wrapping string values in quotes will return 501. + select: OData select query for the columns to be returned. Example: + Column, PartitionKey. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table_name), safe='')}" + f"/entities" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_entity( + self, + storage_account_name: str, + table_name: str, + partition_key: str, + row_key: str, + *, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get entity + + This operation gets the entity in a table based on the partition and + row key. + + Swagger operation ID: `GetEntity_V2`. + + Args: + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + partition_key: The partition id containing this entity. + row_key: The row id containing this entity. + select: OData select query for the columns to be returned. Example: + Column, PartitionKey. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table_name), safe='')}" + f"/entities(PartitionKey='" + f"{quote(str(partition_key), safe='')}" + f"',RowKey='" + f"{quote(str(row_key), safe='')}" + f"')" + ) + query_params = [] + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_table( + self, + storage_account_name: str, + table_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a table + + This operation gets the metadata of a table. + + Swagger operation ID: `GetTable_V2`. + + Args: + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table_name), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tables( + self, + storage_account_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List tables + + List all the tables for your storage account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTables_V2`. + + Args: + storage_account_name: Azure Storage account name or table endpoint. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/tables" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def insert_merge_entity( + self, + input: InsertMergeEntityInput | Mapping[str, Any], + storage_account_name: str, + table_name: str, + partition_key: str, + row_key: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Insert or Merge Entity + + Operation to merge data with an entity in a table, creating a new + entity if needed. + + Swagger operation ID: `InsertMergeEntity_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + partition_key: The partition id containing this entity. + row_key: The row id containing this entity. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table_name), safe='')}" + f"/entities(PartitionKey='" + f"{quote(str(partition_key), safe='')}" + f"',RowKey='" + f"{quote(str(row_key), safe='')}" + f"')" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + async def insert_replace_entity( + self, + input: InsertReplaceEntityInput | Mapping[str, Any], + storage_account_name: str, + table_name: str, + partition_key: str, + row_key: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Insert or Replace Entity + + Operation to replace an entity in a table, creating a new entity if + needed. + + Swagger operation ID: `InsertReplaceEntity_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + partition_key: The partition id containing this entity. + row_key: The row id containing this entity. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table_name), safe='')}" + f"/entities(PartitionKey='" + f"{quote(str(partition_key), safe='')}" + f"',RowKey='" + f"{quote(str(row_key), safe='')}" + f"')" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + async def merge_entity( + self, + input: MergeEntityInput | Mapping[str, Any], + storage_account_name: str, + table_name: str, + partition_key: str, + row_key: str, + *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Merge Entity + + Operation to merge data with an entity in a table. + + Swagger operation ID: `MergeEntity_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + partition_key: The partition id containing this entity. + row_key: The row id containing this entity. + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table_name), safe='')}" + f"/entities" + f"/etag(PartitionKey='" + f"{quote(str(partition_key), safe='')}" + f"',RowKey='" + f"{quote(str(row_key), safe='')}" + f"')" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + async def replace_entity( + self, + input: ReplaceEntityInput | Mapping[str, Any], + storage_account_name: str, + table_name: str, + partition_key: str, + row_key: str, + *, + etag: Optional[str] = "*", + match_condition: Optional[MatchConditions] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Replace Entity + + Operation to replace an entity in a table. + + Swagger operation ID: `ReplaceEntity_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + partition_key: The partition id containing this entity. + row_key: The row id containing this entity. + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/storageAccounts" + f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table_name), safe='')}" + f"/entities" + f"/etag(PartitionKey='" + f"{quote(str(partition_key), safe='')}" + f"',RowKey='" + f"{quote(str(row_key), safe='')}" + f"')" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + def list_storage_accounts( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get storage accounts + + This operation list the user's Azure Storage Account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetStorageAccounts`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/GetStorageAccounts" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/azurevm.py b/src/azure/connectors/aio/azurevm.py new file mode 100644 index 0000000..4293107 --- /dev/null +++ b/src/azure/connectors/aio/azurevm.py @@ -0,0 +1,1638 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# AzurevmClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.azurevm import ( + ResourceGroup, + ResourceGroupListResult, + Subscription, + SubscriptionListResult, + VirtualMachine, + VirtualMachineInScaleSet, + VirtualMachineInScaleSetListResult, + VirtualMachineInScaleSetProperties, + VirtualMachineListResult, + VirtualMachineProperties, + VirtualMachineScaleSet, + VirtualMachineScaleSetListResult, + VirtualMachineScaleSetProperties, +) + +__all__ = [ + "AzurevmClient", + "ResourceGroup", + "ResourceGroupListResult", + "Subscription", + "SubscriptionListResult", + "VirtualMachine", + "VirtualMachineInScaleSet", + "VirtualMachineInScaleSetListResult", + "VirtualMachineInScaleSetProperties", + "VirtualMachineListResult", + "VirtualMachineProperties", + "VirtualMachineScaleSet", + "VirtualMachineScaleSetListResult", + "VirtualMachineScaleSetProperties", +] + + +# Type Definitions + +# Client Class + +class AzurevmClient(ConnectorClientBase): + """Typed client for azurevm connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a AzurevmClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "azurevm" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def virtual_machine_in_scale_set_get( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_scale_set_name: str, + virtual_machine_in_scale_set_instance_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get virtual machine in a VM scale set + + Gets a virtual machine in a VM scale set. + + Swagger operation ID: `VirtualMachineInScaleSet_Get`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + virtual_machine_in_scale_set_instance_id: The name of the virtual + machine in a VM scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachineScaleSets" + f"/{quote(str(virtual_machine_scale_set_name), safe='')}" + f"/virtualMachines" + f"/{quote(str(virtual_machine_in_scale_set_instance_id), safe='')}" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def virtual_machine_in_scale_set_deallocate( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_scale_set_name: str, + virtual_machine_in_scale_set_instance_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Deallocate virtual machine in a VM scale set + + Deallocates a specific virtual machine in a VM scale set. Shuts down + the virtual machine and releases the compute resources it uses. You are + not billed for the compute resources of this virtual machine once it is + deallocated. + + Swagger operation ID: `VirtualMachineInScaleSet_Deallocate`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + virtual_machine_in_scale_set_instance_id: The name of the virtual + machine in a VM scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachineScaleSets" + f"/{quote(str(virtual_machine_scale_set_name), safe='')}" + f"/virtualMachines" + f"/{quote(str(virtual_machine_in_scale_set_instance_id), safe='')}" + f"/deallocate" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def virtual_machine_in_scale_set_power_off( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_scale_set_name: str, + virtual_machine_in_scale_set_instance_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Power off virtual machine in a VM scale set + + Power off (stop) a virtual machine in a VM scale set. Note that + resources are still attached and you are getting charged for the + resources. + + Swagger operation ID: `VirtualMachineInScaleSet_PowerOff`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + virtual_machine_in_scale_set_instance_id: The name of the virtual + machine in a VM scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachineScaleSets" + f"/{quote(str(virtual_machine_scale_set_name), safe='')}" + f"/virtualMachines" + f"/{quote(str(virtual_machine_in_scale_set_instance_id), safe='')}" + f"/poweroff" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def virtual_machine_in_scale_set_redeploy( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_scale_set_name: str, + virtual_machine_in_scale_set_instance_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Redeploy virtual machine in a VM scale set + + Shuts down the virtual machine in the VM scale set, moves it to a new + node, and powers it back on. + + Swagger operation ID: `VirtualMachineInScaleSet_Redeploy`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + virtual_machine_in_scale_set_instance_id: The name of the virtual + machine in a VM scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachineScaleSets" + f"/{quote(str(virtual_machine_scale_set_name), safe='')}" + f"/virtualMachines" + f"/{quote(str(virtual_machine_in_scale_set_instance_id), safe='')}" + f"/redeploy" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def virtual_machine_in_scale_set_reimage( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_scale_set_name: str, + virtual_machine_in_scale_set_instance_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Reimage virtual machine in a VM scale set + + Reimages (upgrade the operating system) a specific virtual machine in a + VM scale set. + + Swagger operation ID: `VirtualMachineInScaleSet_Reimage`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + virtual_machine_in_scale_set_instance_id: The name of the virtual + machine in a VM scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachineScaleSets" + f"/{quote(str(virtual_machine_scale_set_name), safe='')}" + f"/virtualMachines" + f"/{quote(str(virtual_machine_in_scale_set_instance_id), safe='')}" + f"/reimage" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def virtual_machine_in_scale_set_restart( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_scale_set_name: str, + virtual_machine_in_scale_set_instance_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Restart virtual machine in a VM scale set + + Restarts a virtual machine in a VM scale set. + + Swagger operation ID: `VirtualMachineInScaleSet_Restart`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + virtual_machine_in_scale_set_instance_id: The name of the virtual + machine in a VM scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachineScaleSets" + f"/{quote(str(virtual_machine_scale_set_name), safe='')}" + f"/virtualMachines" + f"/{quote(str(virtual_machine_in_scale_set_instance_id), safe='')}" + f"/restart" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def virtual_machine_in_scale_set_start( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_scale_set_name: str, + virtual_machine_in_scale_set_instance_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Start virtual machine in a VM scale set + + Starts a virtual machine in a VM scale set. + + Swagger operation ID: `VirtualMachineInScaleSet_Start`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + virtual_machine_in_scale_set_instance_id: The name of the virtual + machine in a VM scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachineScaleSets" + f"/{quote(str(virtual_machine_scale_set_name), safe='')}" + f"/virtualMachines" + f"/{quote(str(virtual_machine_in_scale_set_instance_id), safe='')}" + f"/start" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def virtual_machine_get( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get virtual machine + + Gets a virtual machine. + + Swagger operation ID: `VirtualMachine_Get`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_name: The name of the virtual machine. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachines" + f"/{quote(str(virtual_machine_name), safe='')}" + ) + query_params = [] + query_params.append("api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def virtual_machine_start( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Start virtual machine + + Starts a virtual machine. + + Swagger operation ID: `VirtualMachine_Start`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_name: The name of the virtual machine. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachines" + f"/{quote(str(virtual_machine_name), safe='')}" + f"/start" + ) + query_params = [] + query_params.append("api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def virtual_machine_deallocate( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Deallocate virtual machine + + Shuts down the virtual machine and releases the compute resources. You + are not billed for the compute resources that this virtual machine + uses. + + Swagger operation ID: `VirtualMachine_Deallocate`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_name: The name of the virtual machine. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachines" + f"/{quote(str(virtual_machine_name), safe='')}" + f"/deallocate" + ) + query_params = [] + query_params.append("api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def virtual_machine_poweroff( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Power off virtual machine + + Power off (stop) a virtual machine. The virtual machine can be + restarted with the same provisioned resources. You are still charged + for this virtual machine. + + Swagger operation ID: `VirtualMachine_Poweroff`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_name: The name of the virtual machine. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachines" + f"/{quote(str(virtual_machine_name), safe='')}" + f"/powerOff" + ) + query_params = [] + query_params.append("api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def virtual_machine_reapply( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Reapply virtual machine + + Reapply a virtual machine's state. + + Swagger operation ID: `VirtualMachine_Reapply`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_name: The name of the virtual machine. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachines" + f"/{quote(str(virtual_machine_name), safe='')}" + f"/reapply" + ) + query_params = [] + query_params.append("api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def virtual_machine_redeploy( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Redeploy virtual machine + + Shuts down the virtual machine, moves it to a new node, and powers it + back on. + + Swagger operation ID: `VirtualMachine_Redeploy`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_name: The name of the virtual machine. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachines" + f"/{quote(str(virtual_machine_name), safe='')}" + f"/redeploy" + ) + query_params = [] + query_params.append("api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def virtual_machine_restart( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Restart virtual machine + + Restarts a virtual machine. + + Swagger operation ID: `VirtualMachine_Restart`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_name: The name of the virtual machine. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachines" + f"/{quote(str(virtual_machine_name), safe='')}" + f"/restart" + ) + query_params = [] + query_params.append("api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_subscriptions( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List subscriptions + + Gets a list of all the subscriptions to which the principal has access. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Subscriptions_List`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/subscriptions" + query_params = [] + query_params.append("x-ms-api-version=" + quote("2020-01-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_resource_groups( + self, + subscription_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List resource groups + + Lists all the resource groups within the subscription. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ResourceGroups_List`. + + Args: + subscription_id: Microsoft Azure subscription. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2020-01-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_virtual_machine_scale_sets( + self, + subscription_id: str, + resource_group_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List virtual machine scale sets + + Lists all the virtual machine scale sets within the resource group. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `VirtualMachineScaleSets_List`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachineScaleSets" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_virtual_machines_in_scale_set( + self, + subscription_id: str, + resource_group_name: str, + virtual_machine_scale_set_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List virtual machines in a VM scale set + + Lists all the virtual machines in a VM scale set. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `VirtualMachinesInScaleSet_List`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachineScaleSets" + f"/{quote(str(virtual_machine_scale_set_name), safe='')}" + f"/virtualMachines" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_virtual_machines( + self, + subscription_id: str, + resource_group_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List virtual machines + + Lists all the virtual machines within the resource group. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `VirtualMachines_List`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/subscriptions" + f"/{quote(str(subscription_id), safe='')}" + f"/resourcegroups" + f"/{quote(str(resource_group_name), safe='')}" + f"/providers" + f"/Microsoft.Compute" + f"/virtualMachines" + ) + query_params = [] + query_params.append("x-ms-api-version=" + quote("2019-12-01", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/box.py b/src/azure/connectors/aio/box.py new file mode 100644 index 0000000..f0b808d --- /dev/null +++ b/src/azure/connectors/aio/box.py @@ -0,0 +1,914 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# BoxClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.box import ( + BlobDataSetsMetadata, + BlobMetadata, + BlobMetadataPage, + BlobMetadataResponse, + DataSetsMetadata, + ObjectEntity, + TabularDataSetsMetadata, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "BoxClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "BlobMetadataPage", + "BlobMetadataResponse", + "DataSetsMetadata", + "ObjectEntity", + "TabularDataSetsMetadata", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class BoxClient(ConnectorClientBase): + """Typed client for box connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a BoxClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "box" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def get_file_metadata( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file metadata using id + + Retrieves the file metadata from Box using file id. + + Swagger operation ID: `GetFileMetadata`. + + Args: + id: The unique identifier of the file in Box. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_file( + self, + input: bytes, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update file + + Updates an existing file in Box. + + Swagger operation ID: `UpdateFile`. + + Args: + input: The binary request body. + id: The unique identifier of the file to update in Box. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PUT", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_file( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete file + + Deletes an existing file from Box. + + Swagger operation ID: `DeleteFile`. + + Args: + id: The unique identifier of the file to delete from Box. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_file_metadata_by_path( + self, + path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file metadata using path + + Retrieves the file metadata from Box using path. + + Swagger operation ID: `GetFileMetadataByPath`. + + Args: + path: The unique path to the file in Box. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/GetFileByPath" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_file_content_by_path( + self, + path: str, + *, + infer_content_type: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file content using path + + Retrieves the file contents from Box using path. + + Swagger operation ID: `GetFileContentByPath`. + + Args: + path: The unique path to the file in Box. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/GetFileContentByPath" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def get_file_content( + self, + id: str, + *, + infer_content_type: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file content using id + + Retrieves the file content from Box using id. + + Swagger operation ID: `GetFileContent`. + + Args: + id: The unique identifier of the file in Box. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/content" + ) + query_params = [] + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def create_file( + self, + input: bytes, + folder_path: str, + name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create file + + Uploads a file to Box. + + Swagger operation ID: `CreateFile`. + + Args: + input: The binary request body. + folder_path: The folder path to upload the file to Box. + name: The name of the file to create in Box. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/datasets/default/files" + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def copy_file( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Copy file + + Copy a file to a file path in Box. + + Swagger operation ID: `CopyFile`. + + Args: + source: The url to source file. + destination: The destination file path in Box, including target + filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/copyFile" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_folder( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List files and folders in folder + + Lists the files and folders in a Box folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListFolder`. + + Args: + id: The unique identifier of the folder in Box. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/folders" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_root_folder( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List files and folders in root folder + + Lists the files and folders in the Box root folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListRootFolder`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/folders" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def extract_folder( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Extract archive to folder + + Extracts an archive file into a folder in Box (example: .zip). + + Swagger operation ID: `ExtractFolderV2`. + + Args: + source: The path to the archive file. + destination: The path in Box to extract the archive contents. + overwrite: Overwrites the destination files if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/extractFolderV2" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/campfire.py b/src/azure/connectors/aio/campfire.py new file mode 100644 index 0000000..dd80479 --- /dev/null +++ b/src/azure/connectors/aio/campfire.py @@ -0,0 +1,465 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# CampfireClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.campfire import ( + Account, + AccountsResponse, + CreateMessageResponse, + CreateUploadResponse, + Message, + MessagesResponse, + Room, + RoomsResponse, + Upload, + UploadResponse, + UserResponse, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "CampfireClient", + "Account", + "AccountsResponse", + "CreateMessageResponse", + "CreateUploadResponse", + "Message", + "MessagesResponse", + "Room", + "RoomsResponse", + "Upload", + "UploadResponse", + "UserResponse", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class CampfireClient(ConnectorClientBase): + """Typed client for campfire connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a CampfireClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "campfire" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_message( + self, + room_id: str, + account: str, + message: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a message + + Sends a message to the given room. + + Swagger operation ID: `CreateMessage`. + + Args: + room_id: A room associated with the account. + account: Account in Campfire. + message: Message text to be created. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/room/{quote(str(room_id), safe='')}/speak.json" + ) + query_params = [] + value = str(account) + if isinstance(account, bool): + value = value.lower() + query_params.append(f"account={quote(value, safe='')}") + value = str(message) + if isinstance(message, bool): + value = value.lower() + query_params.append(f"message={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_user( + self, + user_id: int, + account: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get user by ID + + Retrieves information about a user by given ID + + Swagger operation ID: `GetUser`. + + Args: + user_id: User ID. + account: Account in Campfire. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/users/{quote(str(user_id), safe='')}.json" + ) + query_params = [] + value = str(account) + if isinstance(account, bool): + value = value.lower() + query_params.append(f"account={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_accounts( + self, + *, + parent_operation: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List accounts + + Retrieves the list of accounts this user has access too + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListAccounts`. + + Args: + parent_operation: parentOperation. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/authorization.json" + query_params = [] + if parent_operation is not None: + value = str(parent_operation) + if isinstance(parent_operation, bool): + value = value.lower() + query_params.append(f"parentOperation={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("accounts", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_rooms( + self, + account: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Rooms + + Retrieves the list of rooms in an account + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListRooms`. + + Args: + account: Account in Campfire. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/rooms.json" + query_params = [] + value = str(account) + if isinstance(account, bool): + value = value.lower() + query_params.append(f"account={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("rooms", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/clicksendsms.py b/src/azure/connectors/aio/clicksendsms.py new file mode 100644 index 0000000..c374a99 --- /dev/null +++ b/src/azure/connectors/aio/clicksendsms.py @@ -0,0 +1,951 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# ClicksendsmsClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping +from urllib.parse import quote +import json + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, +) + +from azure.connectors.clicksendsms import ( + CreateListContactInput, + CreateListContactResponse, + CreateListInput, + CreateListResponse, + DeleteListContactResponse, + DeleteListResponse, + GetContactListsResponse, + SearchContactListResponse, + SendFaxInput, + SendFaxResponse, + SendLetterInput, + SendLetterResponse, + SendMmsInput, + SendMmsResponse, + SendPostcardInput, + SendPostcardResponse, + SendVoiceInput, + SendVoiceResponse, + SmsInboundAutomationInput, + SmsSendInput, + SmsSendResponse, + UploadMediaInput, + UploadMediaResponse, + ViewListContactsResponse, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "ClicksendsmsClient", + "CreateListContactInput", + "CreateListContactResponse", + "CreateListInput", + "CreateListResponse", + "DeleteListContactResponse", + "DeleteListResponse", + "GetContactListsResponse", + "SearchContactListResponse", + "SendFaxInput", + "SendFaxResponse", + "SendLetterInput", + "SendLetterResponse", + "SendMmsInput", + "SendMmsResponse", + "SendPostcardInput", + "SendPostcardResponse", + "SendVoiceInput", + "SendVoiceResponse", + "SmsInboundAutomationInput", + "SmsSendInput", + "SmsSendResponse", + "UploadMediaInput", + "UploadMediaResponse", + "ViewListContactsResponse", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class ClicksendsmsClient(ConnectorClientBase): + """Typed client for clicksendsms connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a ClicksendsmsClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "clicksendsms" + + async def sms_send( + self, + input: SmsSendInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send SMS + + Each 160 characters = 1 SMS. Can send up to 1,224 standard characters. + + Swagger operation ID: `sms_send`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/sms/send" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_list( + self, + input: CreateListInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create New Contact List + + Create New Contact List + + Swagger operation ID: `create_list`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/lists" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_contact_lists( + self, + *, + page: Optional[int] = None, + limit: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Contact Lists + + Get all contact lists unless specified in the advance options + + Swagger operation ID: `get_contact_lists`. + + Args: + page: Page number. + limit: Number of records per page. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/lists" + query_params = [] + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_voice( + self, + input: SendVoiceInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send Voice Message + + Each 300 characters = 1 voice message. Can send up to 1,200 standard + characters + + Swagger operation ID: `send_voice`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/voice/send" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_list( + self, + list_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete List + + Delete a specific contact list + + Swagger operation ID: `delete_list`. + + Args: + list_id: You may use the Search Contact List action OR Get Contact + List action to get the List ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(list_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_list_contact( + self, + input: CreateListContactInput | Mapping[str, Any], + list_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create New Contact + + Create New Contact + + Swagger operation ID: `create_list_contact`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + list_id: You may use the Search Contact List action OR Get Contact + List action to get the List ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(list_id), safe='')}/contacts" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def view_list_contacts( + self, + list_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Contacts in a List + + Get all Contacts in a List + + Swagger operation ID: `view_list_contacts`. + + Args: + list_id: You may use the Search Contact List action OR Get Contact + List action to get the List ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(list_id), safe='')}/contacts" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_list_contact( + self, + list_id: int, + contact_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete a Contact + + Delete a Contact + + Swagger operation ID: `delete_list_contact`. + + Args: + list_id: You may use the Search Contact List action OR Get Contact + List action to get the List ID. + contact_id: Contact ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists" + f"/{quote(str(list_id), safe='')}" + f"/contacts" + f"/{quote(str(contact_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_mms( + self, + input: SendMmsInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send MMS + + Send MMS + + Swagger operation ID: `send_mms`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/mms/send" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_fax( + self, + input: SendFaxInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send Fax + + Send Fax + + Swagger operation ID: `send_fax`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/fax/send" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def upload_media( + self, + input: UploadMediaInput | Mapping[str, Any], + convert: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Convert Media File Format + + Convert Media File Format + + Swagger operation ID: `upload_media`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + convert: Select action the file is needed for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/uploads" + query_params = [] + value = str(convert) + if isinstance(convert, bool): + value = value.lower() + query_params.append(f"convert={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def search_contact_list( + self, + q: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Search Contact Lists + + Get list of searched contact list + + Swagger operation ID: `search_contact_list`. + + Args: + q: Search for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/search/contacts-lists" + query_params = [] + value = str(q) + if isinstance(q, bool): + value = value.lower() + query_params.append(f"q={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_letter( + self, + input: SendLetterInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send Letter + + Send Letter + + Swagger operation ID: `send_letter`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/post/letters/send" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_postcard( + self, + input: SendPostcardInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send Postcard + + Send one or more postcards + + Swagger operation ID: `send_postcard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/post/postcards/send" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/cloudconvert.py b/src/azure/connectors/aio/cloudconvert.py new file mode 100644 index 0000000..8dabdb1 --- /dev/null +++ b/src/azure/connectors/aio/cloudconvert.py @@ -0,0 +1,623 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# CloudconvertClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping +from urllib.parse import quote +import json + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, +) + +from azure.connectors.cloudconvert import ( + CaptureWebsiteInput, + ConvertFileInput, + GetCaptureWebsiteOptionsResponse, + GetConvertOptionsResponse, + GetMergeInputsResponse, + GetMergeOptionsResponse, + GetOptimizeOptionsResponse, + MergeFilesInput, + OptimizeFileInput, +) + +__all__ = [ + "CloudconvertClient", + "CaptureWebsiteInput", + "ConvertFileInput", + "GetCaptureWebsiteOptionsResponse", + "GetConvertOptionsResponse", + "GetMergeInputsResponse", + "GetMergeOptionsResponse", + "GetOptimizeOptionsResponse", + "MergeFilesInput", + "OptimizeFileInput", +] + + +# Type Definitions + +# Client Class + +class CloudconvertClient(ConnectorClientBase): + """Typed client for cloudconvert connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a CloudconvertClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "cloudconvert" + + async def convert_file( + self, + input: ConvertFileInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Convert File + + Convert a file to another format + + Swagger operation ID: `ConvertFile`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/flow/jobs/convertfile" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def optimize_file( + self, + input: OptimizeFileInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Compress File + + Compress a PDF, PNG or JPG file + + Swagger operation ID: `OptimizeFile`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/flow/jobs/optimize" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def capture_website( + self, + input: CaptureWebsiteInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Create Website Screenshot + + Create a website screenshot as PDF, PNG or JPG + + Swagger operation ID: `CaptureWebsite`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/jobs/capture-website" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def merge_files( + self, + input: MergeFilesInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Merge Files + + Merge multiple files in one PDF + + Swagger operation ID: `MergeFiles`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/flow/jobs/merge" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def get_convert_options( + self, + *, + input_format: Optional[str] = None, + output_format: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Convert Options + + Swagger operation ID: `GetConvertOptions`. + + Args: + input_format: input_format. + output_format: output_format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/flow/options/convert" + query_params = [] + if input_format is not None: + value = str(input_format) + if isinstance(input_format, bool): + value = value.lower() + query_params.append(f"input_format={quote(value, safe='')}") + if output_format is not None: + value = str(output_format) + if isinstance(output_format, bool): + value = value.lower() + query_params.append(f"output_format={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_optimize_options( + self, + *, + input_format: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Optimize Options + + Swagger operation ID: `GetOptimizeOptions`. + + Args: + input_format: input_format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/flow/options/optimize" + query_params = [] + if input_format is not None: + value = str(input_format) + if isinstance(input_format, bool): + value = value.lower() + query_params.append(f"input_format={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_capture_website_options( + self, + *, + output_format: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Capture Website Options + + Swagger operation ID: `GetCaptureWebsiteOptions`. + + Args: + output_format: output_format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/options/capture-website" + ) + query_params = [] + if output_format is not None: + value = str(output_format) + if isinstance(output_format, bool): + value = value.lower() + query_params.append(f"output_format={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_merge_inputs( + self, + *, + number_of_inputs: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Merge Inputs + + Swagger operation ID: `GetMergeInputs`. + + Args: + number_of_inputs: number_of_inputs. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/flow/inputs/merge" + query_params = [] + if number_of_inputs is not None: + value = str(number_of_inputs) + if isinstance(number_of_inputs, bool): + value = value.lower() + query_params.append(f"number_of_inputs={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_merge_options( + self, + *, + output_format: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Merge Options + + Swagger operation ID: `GetMergeOptions`. + + Args: + output_format: output_format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/flow/options/merge" + query_params = [] + if output_format is not None: + value = str(output_format) + if isinstance(output_format, bool): + value = value.lower() + query_params.append(f"output_format={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/cloudmersiveconvert.py b/src/azure/connectors/aio/cloudmersiveconvert.py new file mode 100644 index 0000000..e901a9c --- /dev/null +++ b/src/azure/connectors/aio/cloudmersiveconvert.py @@ -0,0 +1,3481 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# CloudmersiveconvertClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping +import json + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, +) + +from azure.connectors.cloudmersiveconvert import ( + AddPdfAnnotationRequest, + AlternateFileFormatCandidate, + AutodetectDocumentValidationResult, + AutodetectGetInfoResult, + AutodetectToPngResult, + Base64DecodeRequest, + Base64DecodeResponse, + Base64DetectRequest, + Base64DetectResponse, + Base64EncodeRequest, + Base64EncodeResponse, + ChangeLineEndingResponse, + ClearXlsxCellRequest, + ClearXlsxCellResponse, + ConvertDataJsonToXmlInput, + ConvertWebHtmlToPngResponse, + ConvertedPngPage, + CreateBlankDocxRequest, + CreateBlankDocxResponse, + CreateBlankSpreadsheetRequest, + CreateBlankSpreadsheetResponse, + CreateSpreadsheetFromDataRequest, + CreateSpreadsheetFromDataResponse, + CreateZipArchiveRequest, + DeleteDocxTableRowRangeRequest, + DeleteDocxTableRowRangeResponse, + DeleteDocxTableRowRequest, + DeleteDocxTableRowResponse, + DetectLineEndingsResponse, + DocumentValidationError, + DocumentValidationResult, + DocxBody, + DocxCellStyle, + DocxComment, + DocxFooter, + DocxHeader, + DocxImage, + DocxInsertCommentOnParagraphRequest, + DocxInsertImageRequest, + DocxInsertImageResponse, + DocxPage, + DocxParagraph, + DocxRemoveObjectRequest, + DocxRemoveObjectResponse, + DocxRun, + DocxSection, + DocxSetFooterAddPageNumberRequest, + DocxSetFooterRequest, + DocxSetFooterResponse, + DocxSetHeaderRequest, + DocxSetHeaderResponse, + DocxStyle, + DocxTable, + DocxTableCell, + DocxTableRow, + DocxTemplateApplicationRequest, + DocxTemplateOperation, + DocxText, + DocxTopLevelComment, + EditDocumentXlsxDeleteWorksheetResponse, + ExifValue, + FindRegexMatch, + FindStringMatch, + FindStringRegexRequest, + FindStringRegexResponse, + FindStringSimpleRequest, + FindStringSimpleResponse, + FinishEditingRequest, + GetDocxBodyRequest, + GetDocxBodyResponse, + GetDocxCommentsHierarchicalResponse, + GetDocxCommentsResponse, + GetDocxGetCommentsHierarchicalRequest, + GetDocxGetCommentsRequest, + GetDocxHeadersAndFootersRequest, + GetDocxHeadersAndFootersResponse, + GetDocxImagesRequest, + GetDocxImagesResponse, + GetDocxPagesRequest, + GetDocxPagesResponse, + GetDocxSectionsRequest, + GetDocxSectionsResponse, + GetDocxStylesRequest, + GetDocxStylesResponse, + GetDocxTableByIndexRequest, + GetDocxTableByIndexResponse, + GetDocxTableRowRequest, + GetDocxTableRowResponse, + GetDocxTablesRequest, + GetDocxTablesResponse, + GetImageInfoResult, + GetPdfAnnotationsResult, + GetXlsxCellByIdentifierRequest, + GetXlsxCellByIdentifierResponse, + GetXlsxCellRequest, + GetXlsxCellResponse, + GetXlsxColumnsRequest, + GetXlsxColumnsResponse, + GetXlsxImagesRequest, + GetXlsxImagesResponse, + GetXlsxRowsAndCellsRequest, + GetXlsxRowsAndCellsResponse, + GetXlsxStylesRequest, + GetXlsxStylesResponse, + GetXlsxWorksheetsRequest, + GetXlsxWorksheetsResponse, + HtmlMdResult, + HtmlTemplateApplicationRequest, + HtmlTemplateApplicationResponse, + HtmlTemplateOperation, + HtmlToOfficeRequest, + HtmlToPdfRequest, + HtmlToPngRequest, + HtmlToTextRequest, + HtmlToTextResponse, + InsertDocxCommentOnParagraphResponse, + InsertDocxInsertParagraphRequest, + InsertDocxInsertParagraphResponse, + InsertDocxTableRowRequest, + InsertDocxTableRowResponse, + InsertDocxTablesRequest, + InsertDocxTablesResponse, + InsertXlsxWorksheetRequest, + InsertXlsxWorksheetResponse, + MultipageImageFormatConversionResult, + PageConversionResult, + PdfAnnotation, + PdfDocument, + PdfFormField, + PdfFormFields, + PdfMetadata, + PdfPageText, + PdfTextByPageResult, + PdfToPngResult, + PresentationResult, + RemoveDocxHeadersAndFootersRequest, + RemoveDocxHeadersAndFootersResponse, + RemoveDocxPagesRequest, + RemoveHtmlFromTextRequest, + RemoveHtmlFromTextResponse, + RemovePptxSlidesRequest, + RemoveWhitespaceFromTextRequest, + RemoveWhitespaceFromTextResponse, + RemoveXlsxWorksheetRequest, + ReplaceStringRegexRequest, + ReplaceStringRegexResponse, + ReplaceStringRequest, + ReplaceStringSimpleRequest, + ReplaceStringSimpleResponse, + ScreenshotRequest, + SetFormFieldValue, + SetPdfFormFieldsRequest, + SetPdfMetadataRequest, + SetXlsxCellByIdentifierRequest, + SetXlsxCellByIdentifierResponse, + SetXlsxCellRequest, + SetXlsxCellResponse, + SplitDocumentResult, + SplitDocxDocumentResult, + SplitPdfResult, + SplitPptxPresentationResult, + SplitTextDocumentByLinesResult, + SplitTextDocumentByStringResult, + SplitXlsxWorksheetResult, + TextConversionResult, + TextDocumentElement, + TextDocumentLine, + TextEncodingDetectResponse, + UpdateDocxTableCellRequest, + UpdateDocxTableCellResponse, + UpdateDocxTableRowRequest, + UpdateDocxTableRowResponse, + UrlToTextRequest, + UrlToTextResponse, + ViewerResponse, + WorksheetResult, + XlsxImage, + XlsxSpreadsheetCell, + XlsxSpreadsheetColumn, + XlsxSpreadsheetRow, + XlsxWorksheet, + XmlAddAttributeWithXPathResult, + XmlAddChildWithXPathResult, + XmlFilterWithXPathResult, + XmlQueryWithXQueryMultiResult, + XmlQueryWithXQueryResult, + XmlRemoveAllChildrenWithXPathResult, + XmlRemoveWithXPathResult, + XmlReplaceWithXPathResult, + XmlSetValueWithXPathResult, + ZipDirectory, + ZipExtractResponse, + ZipFile, +) + +__all__ = [ + "CloudmersiveconvertClient", + "AddPdfAnnotationRequest", + "AlternateFileFormatCandidate", + "AutodetectDocumentValidationResult", + "AutodetectGetInfoResult", + "AutodetectToPngResult", + "Base64DecodeRequest", + "Base64DecodeResponse", + "Base64DetectRequest", + "Base64DetectResponse", + "Base64EncodeRequest", + "Base64EncodeResponse", + "ChangeLineEndingResponse", + "ClearXlsxCellRequest", + "ClearXlsxCellResponse", + "ConvertDataJsonToXmlInput", + "ConvertWebHtmlToPngResponse", + "ConvertedPngPage", + "CreateBlankDocxRequest", + "CreateBlankDocxResponse", + "CreateBlankSpreadsheetRequest", + "CreateBlankSpreadsheetResponse", + "CreateSpreadsheetFromDataRequest", + "CreateSpreadsheetFromDataResponse", + "CreateZipArchiveRequest", + "DeleteDocxTableRowRangeRequest", + "DeleteDocxTableRowRangeResponse", + "DeleteDocxTableRowRequest", + "DeleteDocxTableRowResponse", + "DetectLineEndingsResponse", + "DocumentValidationError", + "DocumentValidationResult", + "DocxBody", + "DocxCellStyle", + "DocxComment", + "DocxFooter", + "DocxHeader", + "DocxImage", + "DocxInsertCommentOnParagraphRequest", + "DocxInsertImageRequest", + "DocxInsertImageResponse", + "DocxPage", + "DocxParagraph", + "DocxRemoveObjectRequest", + "DocxRemoveObjectResponse", + "DocxRun", + "DocxSection", + "DocxSetFooterAddPageNumberRequest", + "DocxSetFooterRequest", + "DocxSetFooterResponse", + "DocxSetHeaderRequest", + "DocxSetHeaderResponse", + "DocxStyle", + "DocxTable", + "DocxTableCell", + "DocxTableRow", + "DocxTemplateApplicationRequest", + "DocxTemplateOperation", + "DocxText", + "DocxTopLevelComment", + "EditDocumentXlsxDeleteWorksheetResponse", + "ExifValue", + "FindRegexMatch", + "FindStringMatch", + "FindStringRegexRequest", + "FindStringRegexResponse", + "FindStringSimpleRequest", + "FindStringSimpleResponse", + "FinishEditingRequest", + "GetDocxBodyRequest", + "GetDocxBodyResponse", + "GetDocxCommentsHierarchicalResponse", + "GetDocxCommentsResponse", + "GetDocxGetCommentsHierarchicalRequest", + "GetDocxGetCommentsRequest", + "GetDocxHeadersAndFootersRequest", + "GetDocxHeadersAndFootersResponse", + "GetDocxImagesRequest", + "GetDocxImagesResponse", + "GetDocxPagesRequest", + "GetDocxPagesResponse", + "GetDocxSectionsRequest", + "GetDocxSectionsResponse", + "GetDocxStylesRequest", + "GetDocxStylesResponse", + "GetDocxTableByIndexRequest", + "GetDocxTableByIndexResponse", + "GetDocxTableRowRequest", + "GetDocxTableRowResponse", + "GetDocxTablesRequest", + "GetDocxTablesResponse", + "GetImageInfoResult", + "GetPdfAnnotationsResult", + "GetXlsxCellByIdentifierRequest", + "GetXlsxCellByIdentifierResponse", + "GetXlsxCellRequest", + "GetXlsxCellResponse", + "GetXlsxColumnsRequest", + "GetXlsxColumnsResponse", + "GetXlsxImagesRequest", + "GetXlsxImagesResponse", + "GetXlsxRowsAndCellsRequest", + "GetXlsxRowsAndCellsResponse", + "GetXlsxStylesRequest", + "GetXlsxStylesResponse", + "GetXlsxWorksheetsRequest", + "GetXlsxWorksheetsResponse", + "HtmlMdResult", + "HtmlTemplateApplicationRequest", + "HtmlTemplateApplicationResponse", + "HtmlTemplateOperation", + "HtmlToOfficeRequest", + "HtmlToPdfRequest", + "HtmlToPngRequest", + "HtmlToTextRequest", + "HtmlToTextResponse", + "InsertDocxCommentOnParagraphResponse", + "InsertDocxInsertParagraphRequest", + "InsertDocxInsertParagraphResponse", + "InsertDocxTableRowRequest", + "InsertDocxTableRowResponse", + "InsertDocxTablesRequest", + "InsertDocxTablesResponse", + "InsertXlsxWorksheetRequest", + "InsertXlsxWorksheetResponse", + "MultipageImageFormatConversionResult", + "PageConversionResult", + "PdfAnnotation", + "PdfDocument", + "PdfFormField", + "PdfFormFields", + "PdfMetadata", + "PdfPageText", + "PdfTextByPageResult", + "PdfToPngResult", + "PresentationResult", + "RemoveDocxHeadersAndFootersRequest", + "RemoveDocxHeadersAndFootersResponse", + "RemoveDocxPagesRequest", + "RemoveHtmlFromTextRequest", + "RemoveHtmlFromTextResponse", + "RemovePptxSlidesRequest", + "RemoveWhitespaceFromTextRequest", + "RemoveWhitespaceFromTextResponse", + "RemoveXlsxWorksheetRequest", + "ReplaceStringRegexRequest", + "ReplaceStringRegexResponse", + "ReplaceStringRequest", + "ReplaceStringSimpleRequest", + "ReplaceStringSimpleResponse", + "ScreenshotRequest", + "SetFormFieldValue", + "SetPdfFormFieldsRequest", + "SetPdfMetadataRequest", + "SetXlsxCellByIdentifierRequest", + "SetXlsxCellByIdentifierResponse", + "SetXlsxCellRequest", + "SetXlsxCellResponse", + "SplitDocumentResult", + "SplitDocxDocumentResult", + "SplitPdfResult", + "SplitPptxPresentationResult", + "SplitTextDocumentByLinesResult", + "SplitTextDocumentByStringResult", + "SplitXlsxWorksheetResult", + "TextConversionResult", + "TextDocumentElement", + "TextDocumentLine", + "TextEncodingDetectResponse", + "UpdateDocxTableCellRequest", + "UpdateDocxTableCellResponse", + "UpdateDocxTableRowRequest", + "UpdateDocxTableRowResponse", + "UrlToTextRequest", + "UrlToTextResponse", + "ViewerResponse", + "WorksheetResult", + "XlsxImage", + "XlsxSpreadsheetCell", + "XlsxSpreadsheetColumn", + "XlsxSpreadsheetRow", + "XlsxWorksheet", + "XmlAddAttributeWithXPathResult", + "XmlAddChildWithXPathResult", + "XmlFilterWithXPathResult", + "XmlQueryWithXQueryMultiResult", + "XmlQueryWithXQueryResult", + "XmlRemoveAllChildrenWithXPathResult", + "XmlRemoveWithXPathResult", + "XmlReplaceWithXPathResult", + "XmlSetValueWithXPathResult", + "ZipDirectory", + "ZipExtractResponse", + "ZipFile", +] + + +# Type Definitions + +# Client Class + +class CloudmersiveconvertClient(ConnectorClientBase): + """Typed client for cloudmersiveconvert connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a CloudmersiveconvertClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "cloudmersiveconvert" + + async def edit_document_docx_create_blank_document( + self, + input: CreateBlankDocxRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a blank Word DOCX document + + Returns a blank Word DOCX Document format file. The file is blank, with + no contents. Use additional editing commands such as Insert Paragraph + or Insert Table or Insert Image to populate the document. + + Swagger operation ID: `EditDocument_DocxCreateBlankDocument`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/create/blank" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_delete_pages( + self, + input: RemoveDocxPagesRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Delete, remove pages from a Word DOCX document + + Returns the edited Word Document in the Word Document (DOCX) format + file with the specified pages removed + + Swagger operation ID: `EditDocument_DocxDeletePages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/delete-pages" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def edit_document_docx_delete_table_row( + self, + input: DeleteDocxTableRowRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Deletes a table row in an existing table in a Word DOCX document + + Deletes an existing table row in a Word DOCX Document and returns the + result. + + Swagger operation ID: `EditDocument_DocxDeleteTableRow`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/docx/delete-table-row" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_delete_table_row_range( + self, + input: DeleteDocxTableRowRangeRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Deletes a range of multiple table rows in an existing table in a Word + + Deletes a range of 1 or more existing table rows in a Word DOCX + Document and returns the result. + + Swagger operation ID: `EditDocument_DocxDeleteTableRowRange`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/docx/delete-table-row/range" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_body( + self, + input: GetDocxBodyRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get body from a Word DOCX document + + Returns the body defined in the Word Document (DOCX) format file; this + is the main content part of a DOCX document + + Swagger operation ID: `EditDocument_DocxBody`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/get-body" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_get_comments_hierarchical( + self, + input: GetDocxGetCommentsHierarchicalRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get comments from a Word DOCX document hierarchically + + Returns the comments and review annotations stored in the Word Document + (DOCX) format file hierarchically, where reply comments are nested as + children under top-level comments in the results returned. + + Swagger operation ID: `EditDocument_DocxGetCommentsHierarchical`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/docx/get-comments/hierarchical" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_get_headers_and_footers( + self, + input: GetDocxHeadersAndFootersRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get content of a footer from a Word DOCX document + + Returns the footer content from a Word Document (DOCX) format file + + Swagger operation ID: `EditDocument_DocxGetHeadersAndFooters`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/docx/get-headers-and-footers" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_get_images( + self, + input: GetDocxImagesRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get images from a Word DOCX document + + Returns the images defined in the Word Document (DOCX) format file + + Swagger operation ID: `EditDocument_DocxGetImages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/get-images" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_pages( + self, + input: GetDocxPagesRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get pages and content from a Word DOCX document + + Returns the pages and contents of each page defined in the Word + Document (DOCX) format file + + Swagger operation ID: `EditDocument_DocxPages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/get-pages" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_get_sections( + self, + input: GetDocxSectionsRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get sections from a Word DOCX document + + Returns the sections defined in the Word Document (DOCX) format file + + Swagger operation ID: `EditDocument_DocxGetSections`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/get-sections" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_get_styles( + self, + input: GetDocxStylesRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get styles from a Word DOCX document + + Returns the styles defined in the Word Document (DOCX) format file + + Swagger operation ID: `EditDocument_DocxGetStyles`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/get-styles" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_get_table_row( + self, + input: GetDocxTableRowRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Gets the contents of an existing table row in an existing table in a W + + Gets the contents of an existing table row in a Word DOCX Document and + returns the result. + + Swagger operation ID: `EditDocument_DocxGetTableRow`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/get-table-row" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_get_table_by_index( + self, + input: GetDocxTableByIndexRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a specific table by index in a Word DOCX document + + Returns the specific table object by its 0-based index in an Office + Word Document (DOCX) + + Swagger operation ID: `EditDocument_DocxGetTableByIndex`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/docx/get-table/by-index" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_get_tables( + self, + input: GetDocxTablesRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get all tables in Word DOCX document + + Returns all the table objects in an Office Word Document (docx) + + Swagger operation ID: `EditDocument_DocxGetTables`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/get-tables" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_insert_comment_on_paragraph( + self, + input: DocxInsertCommentOnParagraphRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Insert a new comment into a Word DOCX document attached to a paragraph + + Adds a new comment into a Word DOCX document attached to a paragraph + and returns the result. Call Finish Editing on the output URL to + complete the operation. + + Swagger operation ID: `EditDocument_DocxInsertCommentOnParagraph`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/docx/insert-comment/on/paragraph" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_insert_image( + self, + input: DocxInsertImageRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Insert image into a Word DOCX document + + Set the footer in a Word Document (DOCX). Call Finish Editing on the + output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxInsertImage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/insert-image" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_insert_paragraph( + self, + input: InsertDocxInsertParagraphRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Insert a new paragraph into a Word DOCX document + + Adds a new paragraph into a DOCX and returns the result. You can insert + at the beginning/end of a document, or before/after an existing object + using its Path (location within the document). Call Finish Editing on + the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxInsertParagraph`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/docx/insert-paragraph" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_insert_table( + self, + input: InsertDocxTablesRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Insert a new table into a Word DOCX document + + Adds a new table into a DOCX and returns the result. Call Finish + Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxInsertTable`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/insert-table" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_insert_table_row( + self, + input: InsertDocxTableRowRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Insert a new row into an existing table in a Word DOCX document + + Adds a new table row into a DOCX Document and returns the result. Call + Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxInsertTableRow`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/docx/insert-table-row" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_remove_headers_and_footers( + self, + input: RemoveDocxHeadersAndFootersRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Remove headers and footers from Word DOCX document + + Remove all headers, or footers, or both from a Word Document (DOCX). + Call Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxRemoveHeadersAndFooters`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/docx/remove-headers-and-footers" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_remove_object( + self, + input: DocxRemoveObjectRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete any object in a Word DOCX document + + Delete any object, such as a paragraph, table, image, etc. from a Word + Document (DOCX). Pass in the Path of the object you would like to + delete. You can call other functions such as Get-Tables, Get-Images, + Get-Body, etc. to get the paths of the objects in the document. Call + Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxRemoveObject`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/remove-object" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_replace( + self, + input: ReplaceStringRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Replace string in Word DOCX document + + Replace all instances of a string in an Office Word Document (docx) + + Swagger operation ID: `EditDocument_DocxReplace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/replace-all" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def edit_document_docx_set_footer( + self, + input: DocxSetFooterRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Set the footer in a Word DOCX document + + Set the footer in a Word Document (DOCX). Call Finish Editing on the + output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxSetFooter`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/set-footer" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_set_footer_add_page_number( + self, + input: DocxSetFooterAddPageNumberRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add page number to footer in a Word DOCX document + + Set the footer in a Word Document (DOCX) to contain a page number. Call + Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxSetFooterAddPageNumber`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/docx/set-footer/add-page-number" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_set_header( + self, + input: DocxSetHeaderRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Set the header in a Word DOCX document + + Set the header in a Word Document (DOCX). Call Finish Editing on the + output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxSetHeader`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/docx/set-header" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_update_table_cell( + self, + input: UpdateDocxTableCellRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update, set contents of a table cell in an existing table in a Word DO + + Sets the contents of a table cell into a DOCX Document and returns the + result. Call Finish Editing on the output URL to complete the + operation. + + Swagger operation ID: `EditDocument_DocxUpdateTableCell`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/docx/update-table-cell" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_docx_update_table_row( + self, + input: UpdateDocxTableRowRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update, set contents of a table row in an existing table in a Word DOCX + document + + Sets the contents of a table row into a DOCX Document and returns the + result. Call Finish Editing on the output URL to complete the + operation. + + Swagger operation ID: `EditDocument_DocxUpdateTableRow`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/docx/update-table-row" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_finish_editing( + self, + input: FinishEditingRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Finish editing document, and download result from document editing + + Once done editing a document, download the result. Begin editing a + document by calling begin-editing, then perform operations, then call + finish-editing to get the result. + + Swagger operation ID: `EditDocument_FinishEditing`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/finish-editing" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def edit_document_pptx_delete_slides( + self, + input: RemovePptxSlidesRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Delete, remove slides from a PowerPoint PPTX presentation document + + Edits the input PowerPoint PPTX presentation document to remove the + specified slides + + Swagger operation ID: `EditDocument_PptxDeleteSlides`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/pptx/delete-slides" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def edit_document_pptx_replace( + self, + input: ReplaceStringRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Replace string in PowerPoint PPTX presentation + + Replace all instances of a string in an Office PowerPoint Document + (pptx) + + Swagger operation ID: `EditDocument_PptxReplace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/pptx/replace-all" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def edit_document_xlsx_clear_cell_by_index( + self, + input: ClearXlsxCellRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Clear cell contents in an Excel XLSX spreadsheet, worksheet by index + + Clears, sets to blank, the contents of a specific cell in an Excel XLSX + spreadsheet, worksheet + + Swagger operation ID: `EditDocument_XlsxClearCellByIndex`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/xlsx/clear-cell/by-index" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_xlsx_create_blank_spreadsheet( + self, + input: CreateBlankSpreadsheetRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a blank Excel XLSX spreadsheet + + Returns a blank Excel XLSX Spreadsheet (XLSX) format file + + Swagger operation ID: `EditDocument_XlsxCreateBlankSpreadsheet`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/xlsx/create/blank" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_xlsx_create_spreadsheet_from_data( + self, + input: CreateSpreadsheetFromDataRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a new Excel XLSX spreadsheet from column and row data + + Returns a new Excel XLSX Spreadsheet (XLSX) format file populated with + column and row data specified as input + + Swagger operation ID: `EditDocument_XlsxCreateSpreadsheetFromData`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/xlsx/create/from/data" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_xlsx_delete_worksheet( + self, + input: RemoveXlsxWorksheetRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete, remove worksheet from an Excel XLSX spreadsheet document + + Edits the input Excel XLSX spreadsheet document to remove the specified + worksheet (tab). Use the Get Worksheets API to enumerate available + worksheets in a spreadsheet. + + Swagger operation ID: `EditDocument_XlsxDeleteWorksheet`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/xlsx/delete-worksheet" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_xlsx_get_cell_by_identifier( + self, + input: GetXlsxCellByIdentifierRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get cell from an Excel XLSX spreadsheet, worksheet by cell identifier + + Returns the value of a specific cell based on its identifier (e.g. A1, + B22, C33, etc.) in the Excel Spreadsheet worksheet + + Swagger operation ID: `EditDocument_XlsxGetCellByIdentifier`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/xlsx/get-cell/by-identifier" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_xlsx_get_cell_by_index( + self, + input: GetXlsxCellRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get cell from an Excel XLSX spreadsheet, worksheet by index + + Returns the value and definition of a specific cell in a specific row + in the Excel Spreadsheet worksheet + + Swagger operation ID: `EditDocument_XlsxGetCellByIndex`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/xlsx/get-cell/by-index" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_xlsx_get_columns( + self, + input: GetXlsxColumnsRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get rows and cells from a Excel XLSX spreadsheet, worksheet + + Returns the rows and cells defined in the Excel Spreadsheet worksheet + + Swagger operation ID: `EditDocument_XlsxGetColumns`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/xlsx/get-columns" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_xlsx_get_images( + self, + input: GetXlsxImagesRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get images from a Excel XLSX spreadsheet, worksheet + + Returns the images defined in the Excel Spreadsheet worksheet + + Swagger operation ID: `EditDocument_XlsxGetImages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/xlsx/get-images" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_xlsx_get_rows_and_cells( + self, + input: GetXlsxRowsAndCellsRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get rows and cells from a Excel XLSX spreadsheet, worksheet + + Returns the rows and cells defined in the Excel Spreadsheet worksheet + + Swagger operation ID: `EditDocument_XlsxGetRowsAndCells`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/xlsx/get-rows-and-cells" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_xlsx_get_styles( + self, + input: GetXlsxStylesRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get styles from a Excel XLSX spreadsheet, worksheet + + Returns the style defined in the Excel Spreadsheet + + Swagger operation ID: `EditDocument_XlsxGetStyles`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/xlsx/get-styles" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_xlsx_get_worksheets( + self, + input: GetXlsxWorksheetsRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get worksheets from a Excel XLSX spreadsheet + + Returns the worksheets (tabs) defined in the Excel Spreadsheet (XLSX) + format file + + Swagger operation ID: `EditDocument_XlsxGetWorksheets`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/edit/xlsx/get-worksheets" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_xlsx_insert_worksheet( + self, + input: InsertXlsxWorksheetRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Insert a new worksheet into an Excel XLSX spreadsheet + + Inserts a new worksheet into an Excel Spreadsheet + + Swagger operation ID: `EditDocument_XlsxInsertWorksheet`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/xlsx/insert-worksheet" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_xlsx_set_cell_by_identifier( + self, + input: SetXlsxCellByIdentifierRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Set, update cell contents in an Excel XLSX spreadsheet, worksheet by c + + Sets, updates the contents of a specific cell in an Excel XLSX + spreadsheet, worksheet using its cell identifier (e.g. A1, B22, C33) in + the worksheet + + Swagger operation ID: `EditDocument_XlsxSetCellByIdentifier`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/xlsx/set-cell/by-identifier" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_document_xlsx_set_cell_by_index( + self, + input: SetXlsxCellRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Set, update cell contents in an Excel XLSX spreadsheet, worksheet by + index + + Sets, updates the contents of a specific cell in an Excel XLSX + spreadsheet, worksheet + + Swagger operation ID: `EditDocument_XlsxSetCellByIndex`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/convert/edit/xlsx/set-cell/by-index" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def convert_web_html_to_docx( + self, + input: HtmlToOfficeRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Convert HTML to Word DOCX Document + + Convert HTML to Office Word Document (DOCX) format + + Swagger operation ID: `ConvertWeb_HtmlToDocx`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/convert/html/to/docx" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def convert_data_json_to_xml( + self, + input: ConvertDataJsonToXmlInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Convert JSON to XML conversion + + Convert a JSON object into XML + + Swagger operation ID: `ConvertData_JsonToXml`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/convert/json/to/xml" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def convert_template_apply_html_template( + self, + input: HtmlTemplateApplicationRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Apply HTML template + + Apply operations to fill in an HTML template, generating a final HTML + result + + Swagger operation ID: `ConvertTemplate_ApplyHtmlTemplate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/template/html/apply" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def convert_web_html_to_pdf( + self, + input: HtmlToPdfRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Convert HTML string to PDF + + Fully renders a website and returns a PDF of the HTML. Javascript, + HTML5, CSS and other advanced features are all supported. + + Swagger operation ID: `ConvertWeb_HtmlToPdf`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/convert/web/html/to/pdf" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def convert_web_html_to_png( + self, + input: HtmlToPngRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Convert HTML string to PNG screenshot + + Fully renders a website and returns a PNG (screenshot) of the HTML. + Javascript, HTML5, CSS and other advanced features are all supported. + + Swagger operation ID: `ConvertWeb_HtmlToPng`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/convert/web/html/to/png" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def convert_web_html_to_txt( + self, + input: HtmlToTextRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Convert HTML string to text (txt) + + Converts an HTML string input into text (txt); extracts text from HTML + + Swagger operation ID: `ConvertWeb_HtmlToTxt`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/convert/web/html/to/txt" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def convert_web_url_to_pdf( + self, + input: ScreenshotRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Convert a URL to PDF + + Fully renders a website and returns a PDF of the full page. Javascript, + HTML5, CSS and other advanced features are all supported. + + Swagger operation ID: `ConvertWeb_UrlToPdf`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/convert/web/url/to/pdf" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def convert_web_url_to_screenshot( + self, + input: ScreenshotRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Take screenshot of URL + + Fully renders a website and returns a PNG screenshot of the full page + image. Javascript, HTML5, CSS and other advanced features are all + supported. + + Swagger operation ID: `ConvertWeb_UrlToScreenshot`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/convert/web/url/to/screenshot" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def convert_web_url_to_txt( + self, + input: UrlToTextRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Convert website URL page to text (txt) + + Converts a website URL page into text (txt); extracts text from HTML + + Swagger operation ID: `ConvertWeb_UrlToTxt`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/convert/web/url/to/txt" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/commondataservice.py b/src/azure/connectors/aio/commondataservice.py new file mode 100644 index 0000000..acafefc --- /dev/null +++ b/src/azure/connectors/aio/commondataservice.py @@ -0,0 +1,1833 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# CommondataserviceClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.commondataservice import ( + ActionsDynamicValuesList, + AssociateEntityRequest, + AssociateRecordsPatchItemInput, + BlobDataSetsMetadata, + CallbackRegistration, + DataSet, + DataSetsList, + DataSetsMetadata, + DisplayCollectionName, + EntitiesDynamicValuesList, + EntitiesDynamicValuesListItem, + EntityItem, + EntityItemList, + EntityMetadata, + EntityRelationshipsDynamicValuesList, + GetItemResponse, + Item, + ItemsList, + ObjectEntity, + OrganizationsDynamicValuesList, + OrganizationsDynamicValuesListItem, + PassThroughNativeQuery, + PatchItemInput, + PatchItemResponse, + PostItemInput, + PostItemResponse, + Procedure, + SearchOutput, + SearchRequestBody, + SubscriptionRequest, + SubscriptionResponse, + Table, + TableCapabilitiesMetadata, + TableFilterRestrictionsMetadata, + TableMetadata, + TableSelectRestrictionsMetadata, + TableSortRestrictionsMetadata, + TablesList, + TabularDataSetsMetadata, + UpdateTriggerSubscriptionRequest, + UserLocalizedLabel, + WebhookNotificationContent, + WebhookNotificationContentForWhenAnActionIsPerformed, + WhenAnActionIsPerformedSubscriptionRequest, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "CommondataserviceClient", + "ActionsDynamicValuesList", + "AssociateEntityRequest", + "AssociateRecordsPatchItemInput", + "BlobDataSetsMetadata", + "CallbackRegistration", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "DisplayCollectionName", + "EntitiesDynamicValuesList", + "EntitiesDynamicValuesListItem", + "EntityItem", + "EntityItemList", + "EntityMetadata", + "EntityRelationshipsDynamicValuesList", + "GetItemResponse", + "Item", + "ItemsList", + "ObjectEntity", + "OrganizationsDynamicValuesList", + "OrganizationsDynamicValuesListItem", + "PassThroughNativeQuery", + "PatchItemInput", + "PatchItemResponse", + "PostItemInput", + "PostItemResponse", + "Procedure", + "SearchOutput", + "SearchRequestBody", + "SubscriptionRequest", + "SubscriptionResponse", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TablesList", + "TabularDataSetsMetadata", + "UpdateTriggerSubscriptionRequest", + "UserLocalizedLabel", + "WebhookNotificationContent", + "WebhookNotificationContentForWhenAnActionIsPerformed", + "WhenAnActionIsPerformedSubscriptionRequest", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class CommondataserviceClient(ConnectorClientBase): + """Typed client for commondataservice connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a CommondataserviceClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "commondataservice" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + encoded_token = quote(str(next_link), safe='') + return f"{self._connection_runtime_url}/nextLink/{encoded_token}" + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def get_data_sets_metadata( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + GetDataSetsMetadata + + Swagger operation ID: `GetDataSetsMetadata`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/$metadata.json/datasets" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_next_page( + self, + next_link: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Follows nextLink to retrieve next page of data + + This operation gets the next page of data. + + Swagger operation ID: `GetNextPage`. + + Args: + next_link: OData nextLink. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/nextLink/{quote(str(next_link), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def associate_records_patch_item( + self, + input: AssociateRecordsPatchItemInput | Mapping[str, Any], + dataset: str, + table: str, + id: str, + relationship: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Associates one row to another on the provided relationship + + Associates one row to another on the provided relationship + + Swagger operation ID: `AssociateRecordsPatchItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Select an Environment. + table: Name of the table. + id: Id of the table row. + relationship: Relationship on which to associate. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/Relationship" + f"/{quote(quote(str(relationship), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_attachment( + self, + input: bytes, + dataset: str, + table: str, + id: str, + display_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Creates Note (annotation) for specified table row + + Creates Note (annotation) for specified table row. + + Swagger operation ID: `CreateAttachment_V2`. + + Args: + input: The binary request body. + dataset: Select an Environment. + table: Table on which to create Note (annotation). + id: Id of the table row on which to create a Note (annotation). + display_name: Filename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/attachments" + ) + query_params = [] + value = str(display_name) + if isinstance(display_name, bool): + value = value.lower() + query_params.append(f"displayName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_attachment( + self, + dataset: str, + table: str, + id: str, + attachment_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Deletes specified attachment on the Note (annotation) + + Deletes specified attachment on the Note (annotation). + + Swagger operation ID: `DeleteAttachment_V2`. + + Args: + dataset: Select an Environment. + table: Table on which to delete Note (annotation). + id: Id of the table row on which to delete a Note (annotation). + attachment_id: Note (annotation) id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/attachments" + f"/{quote(quote(str(attachment_id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def delete_item( + self, + dataset: str, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a row (legacy) + + This operation deletes a row from a table collection + + Swagger operation ID: `DeleteItem_V2`. + + Args: + dataset: Select an Environment. + table: Select a table. + id: Identifier for the row. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def disassociate_records_post_item( + self, + dataset: str, + table: str, + id: str, + relationship: str, + related_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Disassociates a row from a multi-valued relationship + + Disassociates a row from a multi-valued relationship + + Swagger operation ID: `DisassociateRecordsPostItem_V2`. + + Args: + dataset: Select an Environment. + table: Name of the table. + id: Id of the table row. + relationship: Relationship on which to associate. + related_id: The item to disassociate. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/Relationship" + f"/{quote(quote(str(relationship), safe=''), safe='')}" + f"/RelatedId" + f"/{quote(quote(str(related_id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def disassociate_single_value_record_delete_item( + self, + dataset: str, + table: str, + id: str, + relationship: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Disassociates a row from a single-valued relationship + + Disassociates a row from a single-valued relationship + + Swagger operation ID: `DisassociateSingleValueRecordDeleteItem_V2`. + + Args: + dataset: Select an Environment. + table: Name of the table. + id: Id of the table row. + relationship: Relationship on which to associate. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/Relationship" + f"/{quote(quote(str(relationship), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_attachment_content( + self, + dataset: str, + table: str, + id: str, + attachment_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Retrieves file content for specified Note (annotation) + + Retrieves file content for specified Note (annotation). + + Swagger operation ID: `GetAttachmentContent_V2`. + + Args: + dataset: Select an Environment. + table: Table for which to get Note (annotation) content. + id: Id of the table row for which to get Notes (annotations). + attachment_id: Note (annotation) id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/attachments" + f"/{quote(quote(str(attachment_id), safe=''), safe='')}" + f"/$value" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + def list_collection_relationships( + self, + dataset: str, + table: str, + id: str, + collection_type: str, + relationship: str, + target: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Retrieves all collection valued relationship items as an expand would + + Retrieves all collection valued relationship items as an expand would + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetCollectionRelationships_V2`. + + Args: + dataset: Select an Environment. + table: Name of the table. + id: Id of the table row. + collection_type: many to many or not. + relationship: Relationship on which to expand. + target: Target table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/Collection" + f"/{quote(quote(str(collection_type), safe=''), safe='')}" + f"/{quote(quote(str(relationship), safe=''), safe='')}" + f"/TargetTable" + f"/{quote(quote(str(target), safe=''), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_data_sets( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + GetDataSets + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetDataSets_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/datasets" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_item( + self, + dataset: str, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get row (legacy) + + This operation retrieves the specified row for a table + + Swagger operation ID: `GetItem_V2`. + + Args: + dataset: Select an Environment. + table: Select a table. + id: Identifier for the row. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_item_attachments( + self, + dataset: str, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Retrieves all Notes (annotations) for the provided table row Id + + Retrieves all Notes (annotations) for the provided table row Id. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItemAttachments_V2`. + + Args: + dataset: Select an Environment. + table: Table for which to get Notes (annotations). + id: Id of the table row for which to get Notes (annotations). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/attachments" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_items( + self, + dataset: str, + table: str, + *, + apply: Optional[str] = None, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + expand: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List rows (legacy) + + This operation gets rows for a table + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItems_V2`. + + Args: + dataset: Select an Environment. + table: Select a table. + apply: A sequence of OData aggregation transformations. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + expand: Related entries to include with requested entries (default + = none). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + query_params = [] + if apply is not None: + value = str(apply) + if isinstance(apply, bool): + value = value.lower() + query_params.append(f"$apply={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if expand is not None: + value = str(expand) + if isinstance(expand, bool): + value = value.lower() + query_params.append(f"$expand={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_metadata_for_patch_item( + self, + dataset: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get table metadata - Patch + + Gets table metadata for patch operation + + Swagger operation ID: `GetMetadataForPatchItem_V2`. + + Args: + dataset: Select an Environment. + table: Select a table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/$metadata.json" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/patchitem" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_metadata_for_post_item( + self, + dataset: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get table metadata - Post + + Gets table metadata for post operation + + Swagger operation ID: `GetMetadataForPostItem_V2`. + + Args: + dataset: Select an Environment. + table: Select a table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/$metadata.json" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/postitem" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_multi_select_metadata( + self, + dataset: str, + table: str, + item: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Retrieves the metadata for multi select column metadata + + Retrieves the metadata for multi select column metadata. + + Swagger operation ID: `GetMultiSelectMetadata_V2`. + + Args: + dataset: org name. + table: table name. + item: id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(item), safe=''), safe='')}" + f"/MultiSelect" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_option_set_metadata( + self, + dataset: str, + table: str, + item: str, + type_: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Retrieves the metadata for choice column metadata + + Retrieves the metadata for choice column metadata. + + Swagger operation ID: `GetOptionSetMetadata_V2`. + + Args: + dataset: org name. + table: table name. + item: id. + type_: type of choice. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(item), safe=''), safe='')}" + f"/OptionSet" + f"/{quote(str(type_), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_table( + self, + dataset: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get table metadata + + Gets table metadata + + Swagger operation ID: `GetTable_V2`. + + Args: + dataset: Select an Environment. + table: Select atable. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/$metadata.json" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tables( + self, + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + GetTables + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTables_V2`. + + Args: + dataset: dataset. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def patch_item( + self, + input: PatchItemInput | Mapping[str, Any], + dataset: str, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a row (legacy) + + This operation updates an existing row for a table + + Swagger operation ID: `PatchItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Select an Environment. + table: Select a table. + id: Identifier for the row. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def post_item( + self, + input: PostItemInput | Mapping[str, Any], + dataset: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add a new row (legacy) + + This operation adds a new row of a table + + Swagger operation ID: `PostItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Select an Environment. + table: Select a table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/documentdb.py b/src/azure/connectors/aio/documentdb.py new file mode 100644 index 0000000..7cc1603 --- /dev/null +++ b/src/azure/connectors/aio/documentdb.py @@ -0,0 +1,1333 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# DocumentdbClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.documentdb import ( + CosmosDbAccount, + CosmosDbAccountList, + CreateStoredProcedureInput, + CreateStoredProcedureResponse, + DataWithSensitivityLabelInfo, + DocumentsCollection, + DocumentsQuery, + ExecuteStoredProcedureInput, + GetAccountResponse, + GetCollectionResponse, + GetCollectionsResponse, + GetDatabaseResponse, + GetDatabasesResponse, + GetDocumentResponse, + GetDocumentsResponse, + GetStoredProceduresResponse, + ObjectEntity, + ObjectWithoutType, + PostDocumentsRequest, + PostDocumentsResponse, + PutDocumentRequest, + PutDocumentResponse, + QueryDocumentsResponse, + QueryRequest, + QueryResponse, + ReplaceStoredProcedureInput, + SensitivityLabelMetadata, +) + +__all__ = [ + "DocumentdbClient", + "CosmosDbAccount", + "CosmosDbAccountList", + "CreateStoredProcedureInput", + "CreateStoredProcedureResponse", + "DataWithSensitivityLabelInfo", + "DocumentsCollection", + "DocumentsQuery", + "ExecuteStoredProcedureInput", + "GetAccountResponse", + "GetCollectionResponse", + "GetCollectionsResponse", + "GetDatabaseResponse", + "GetDatabasesResponse", + "GetDocumentResponse", + "GetDocumentsResponse", + "GetStoredProceduresResponse", + "ObjectEntity", + "ObjectWithoutType", + "PostDocumentsRequest", + "PostDocumentsResponse", + "PutDocumentRequest", + "PutDocumentResponse", + "QueryDocumentsResponse", + "QueryRequest", + "QueryResponse", + "ReplaceStoredProcedureInput", + "SensitivityLabelMetadata", +] + + +# Type Definitions + +# Client Class + +class DocumentdbClient(ConnectorClientBase): + """Typed client for documentdb connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a DocumentdbClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "documentdb" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_document( + self, + input: PostDocumentsRequest | Mapping[str, Any], + cosmos_db_account_name: str, + database_id: str, + collection_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create or update document + + Create or update document. When creating a document in DocumentDB, the + body must include an id property. + + Swagger operation ID: `CreateDocument_V3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/cosmosdb" + f"/{quote(str(cosmos_db_account_name), safe='')}" + f"/dbs" + f"/{quote(str(database_id), safe='')}" + f"/colls" + f"/{quote(str(collection_id), safe='')}" + f"/docs" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_stored_procedure( + self, + input: CreateStoredProcedureInput | Mapping[str, Any], + cosmos_db_account_name: str, + database_id: str, + collection_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create stored procedure + + Create stored procedure. + + Swagger operation ID: `CreateStoredProcedure_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/cosmosdb" + f"/{quote(str(cosmos_db_account_name), safe='')}" + f"/dbs" + f"/{quote(str(database_id), safe='')}" + f"/colls" + f"/{quote(str(collection_id), safe='')}" + f"/sprocs" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_document( + self, + cosmos_db_account_name: str, + database_id: str, + collection_id: str, + document_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a document + + Delete a document. + + Swagger operation ID: `DeleteDocument_V2`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + document_id: The identifier of the document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/cosmosdb" + f"/{quote(str(cosmos_db_account_name), safe='')}" + f"/dbs" + f"/{quote(str(database_id), safe='')}" + f"/colls" + f"/{quote(str(collection_id), safe='')}" + f"/docs" + f"/{quote(str(document_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def delete_stored_procedure( + self, + cosmos_db_account_name: str, + database_id: str, + collection_id: str, + sproc_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete stored procedure + + Delete stored procedure. + + Swagger operation ID: `DeleteStoredProcedure_V2`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + sproc_id: The name of the stored procedure. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/cosmosdb" + f"/{quote(str(cosmos_db_account_name), safe='')}" + f"/dbs" + f"/{quote(str(database_id), safe='')}" + f"/colls" + f"/{quote(str(collection_id), safe='')}" + f"/sprocs" + f"/{quote(str(sproc_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def execute_stored_procedure( + self, + input: ExecuteStoredProcedureInput, + cosmos_db_account_name: str, + database_id: str, + collection_id: str, + sproc_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Execute stored procedure + + Execute stored procedure in specified collection. + + Swagger operation ID: `ExecuteStoredProcedure_V2`. + + Args: + input: The request body. + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + sproc_id: The name of the stored procedure. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/cosmosdb" + f"/{quote(str(cosmos_db_account_name), safe='')}" + f"/dbs" + f"/{quote(str(database_id), safe='')}" + f"/colls" + f"/{quote(str(collection_id), safe='')}" + f"/sprocs" + f"/{quote(str(sproc_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_document( + self, + cosmos_db_account_name: str, + database_id: str, + collection_id: str, + document_id: str, + *, + extract_sensitivity_label: Optional[bool] = None, + purview_account_name: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get a document + + Get a document. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetDocument_V2`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + document_id: The identifier for the document. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/cosmosdb" + f"/{quote(str(cosmos_db_account_name), safe='')}" + f"/dbs" + f"/{quote(str(database_id), safe='')}" + f"/colls" + f"/{quote(str(collection_id), safe='')}" + f"/docs" + f"/{quote(str(document_id), safe='')}" + ) + query_params = [] + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if purview_account_name is not None: + value = str(purview_account_name) + if isinstance(purview_account_name, bool): + value = value.lower() + query_params.append(f"purviewAccountName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("@metadata", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_documents( + self, + cosmos_db_account_name: str, + database_id: str, + collection_id: str, + *, + extract_sensitivity_label: Optional[bool] = None, + purview_account_name: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get all documents + + Get all documents. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetDocuments_V3`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/cosmosdb" + f"/{quote(str(cosmos_db_account_name), safe='')}" + f"/dbs" + f"/{quote(str(database_id), safe='')}" + f"/colls" + f"/{quote(str(collection_id), safe='')}" + f"/docs" + ) + query_params = [] + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if purview_account_name is not None: + value = str(purview_account_name) + if isinstance(purview_account_name, bool): + value = value.lower() + query_params.append(f"purviewAccountName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("Documents", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_stored_procedures( + self, + cosmos_db_account_name: str, + database_id: str, + collection_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get stored procedures + + Get stored procedures in the specified collection. + + Swagger operation ID: `GetStoredProcedures_V2`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/cosmosdb" + f"/{quote(str(cosmos_db_account_name), safe='')}" + f"/dbs" + f"/{quote(str(database_id), safe='')}" + f"/colls" + f"/{quote(str(collection_id), safe='')}" + f"/sprocs" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_query_documents( + self, + cosmos_db_account_name: str, + database_id: str, + container_id: str, + *, + query_text: Optional[str] = None, + partition_key: Optional[str] = None, + max_item_count: Optional[int] = None, + consistency_level: Optional[str] = None, + session_token: Optional[str] = None, + extract_sensitivity_label: Optional[bool] = None, + purview_account_name: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Query documents + + Query documents. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `QueryDocuments_V5`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + container_id: The name of the container. + query_text: SQL query. If empty, will return all documents. + partition_key: Value must be provided according to its type + (\"string\", 42, 0.5). If empty, all partitions will be used to + search for documents. + max_item_count: An integer indicating the maximum number of items + to be returned per page. + consistency_level: Consistency level required for the feed + (query/read feed) operation. + session_token: The session token for use with session consistency. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v5" + f"/cosmosdb" + f"/{quote(str(cosmos_db_account_name), safe='')}" + f"/dbs" + f"/{quote(str(database_id), safe='')}" + f"/colls" + f"/{quote(str(container_id), safe='')}" + f"/query" + ) + query_params = [] + if query_text is not None: + value = str(query_text) + if isinstance(query_text, bool): + value = value.lower() + query_params.append(f"queryText={quote(value, safe='')}") + if partition_key is not None: + value = str(partition_key) + if isinstance(partition_key, bool): + value = value.lower() + query_params.append(f"partitionKey={quote(value, safe='')}") + if max_item_count is not None: + value = str(max_item_count) + if isinstance(max_item_count, bool): + value = value.lower() + query_params.append(f"maxItemCount={quote(value, safe='')}") + if consistency_level is not None: + value = str(consistency_level) + if isinstance(consistency_level, bool): + value = value.lower() + query_params.append(f"consistencyLevel={quote(value, safe='')}") + if session_token is not None: + value = str(session_token) + if isinstance(session_token, bool): + value = value.lower() + query_params.append(f"sessionToken={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if purview_account_name is not None: + value = str(purview_account_name) + if isinstance(purview_account_name, bool): + value = value.lower() + query_params.append(f"purviewAccountName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def replace_document( + self, + input: PutDocumentRequest | Mapping[str, Any], + cosmos_db_account_name: str, + database_id: str, + collection_id: str, + document_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Replace a document + + Replace a document. + + Swagger operation ID: `ReplaceDocument_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + document_id: The identifier of the document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/cosmosdb" + f"/{quote(str(cosmos_db_account_name), safe='')}" + f"/dbs" + f"/{quote(str(database_id), safe='')}" + f"/colls" + f"/{quote(str(collection_id), safe='')}" + f"/docs" + f"/{quote(str(document_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def replace_stored_procedure( + self, + input: ReplaceStoredProcedureInput | Mapping[str, Any], + cosmos_db_account_name: str, + database_id: str, + collection_id: str, + sproc_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Replace stored procedure + + Replace stored procedure. + + Swagger operation ID: `ReplaceStoredProcedure_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + sproc_id: The name of the stored procedure. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/cosmosdb" + f"/{quote(str(cosmos_db_account_name), safe='')}" + f"/dbs" + f"/{quote(str(database_id), safe='')}" + f"/colls" + f"/{quote(str(collection_id), safe='')}" + f"/sprocs" + f"/{quote(str(sproc_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_cosmos_db_accounts( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Cosmos DB accounts + + This operation list the user's Azure Cosmos DB accounts. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetCosmosDbAccounts`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/cosmosdbaccounts" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_databases( + self, + cosmos_db_account_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get all databases + + Get all databases. + + Swagger operation ID: `GetDatabases_V2`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/cosmosdb/{quote(str(cosmos_db_account_name), safe='')}/dbs" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_collections( + self, + cosmos_db_account_name: str, + database_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get all collections + + Get all collections. + + Swagger operation ID: `GetCollections_V2`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/cosmosdb" + f"/{quote(str(cosmos_db_account_name), safe='')}" + f"/dbs" + f"/{quote(str(database_id), safe='')}" + f"/colls" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/docusign.py b/src/azure/connectors/aio/docusign.py new file mode 100644 index 0000000..1442cae --- /dev/null +++ b/src/azure/connectors/aio/docusign.py @@ -0,0 +1,5445 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# DocusignClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.docusign import ( + AccountCustomFields, + Activity, + ActivityListResponseEnvelope, + AddDocumentsResponse, + AddDocumentsToEnvelopeInput, + AddRecipientTabsResponse, + AddRecipientToEnvelopeRequest, + AddRemindersResponse, + AddVerificationToRecipientResponse, + AdditionalRecipientData, + AdditionalRecipientParamsSchema, + AdditionalURL, + AdditionalURLForSenderView, + AnchorTabSchema, + ApiError, + ApplyTemplatesToDocumentsInput, + AuditResponse, + BuildNumberResponse, + BuildNumberSchema, + BulkSendListGuid, + CombinedEmailBodyAndCustomFields, + CompositeTemplateSchema, + CompositeTemplatesResponse, + CreateBulkSendListInput, + CreateEnvelopeResponse, + CreateHookEnvelopeInput, + CreateHookEnvelopeResponse, + CreateOrgHookEnvelopeInput, + CreateOrgHookEnvelopeResponse, + DeclineReasonWithoutType, + DocGenFormField, + DocGenFormFieldsResponse, + DocumentRecord, + DocumentRecordListResponseEnvelope, + DocumentType, + DocumentTypesResponse, + DynamicRecipients, + DynamicSigners, + DynamicSigningUrlFields, + EmailSummary, + EmailSummaryResponse, + EmbeddedSenderResponse, + EmbeddedSigningResponse, + Envelope, + EnvelopeCustomFieldResponse, + EnvelopeDocument, + EnvelopeDocumentField, + EnvelopeIDsResponse, + EnvelopeIds, + EnvelopeResendResponse, + EnvelopeTemplate, + EnvelopeVoidResponse, + FilteredEnvelopeListResponse, + FilteredEnvelopes, + FilteredSalesCopilotEnvelopeListResponse, + Folder, + FolderItem, + FontName, + FontNamesResponse, + GetDocGenTemplateTabsResponse, + GetDocumentsResponse, + GetDynamicRecipientsResponse, + GetDynamicSignersResponse, + GetLoginAccountsResponse, + GetOrganizationsResponse, + GetWorkFlowIdsResponse, + KeySales, + KeySalesResponse, + ListDocumentsResponse, + ListEnvelopeDocumentFieldsResponse, + ListEnvelopesResponse, + ListFoldersResponse, + ListRecipientsResponse, + ListSigningGroupResponse, + ListTabsResponse, + ListTemplateDocumentsResponse, + ListTemplatesResponse, + LoginAccount, + MaestroInputVariables, + OnEnvelopeStatusChangesResponse, + Organization, + RecipientTab, + RecipientTabsResponse, + RecipientType, + RecipientTypesResponse, + SalesCopilotFilteredEnvelopes, + SendDraftEnvelopeResponse, + SignatureType, + SignatureTypesResponse, + Signer, + SignerRequest, + SigningGroup, + StaticResponseForAnchorTabSchemaResponse, + StaticResponseForBuildNumberSchemaResponse, + StaticResponseForCompositeTemplatesResponse, + StaticResponseForEmbeddedSenderSchemaResponse, + StaticResponseForEmbeddedSigningSchemaResponse, + StaticResponseForRecipientTypeSchemaResponse, + StaticResponseForVerificationTypeSchemaResponse, + Tab, + TabType, + TabTypesResponse, + TriggerMaestroFlowResponse, + UpdateDocgenFormFieldsInput, + UpdateEnvelopeCustomFieldResponse, + UpdateEnvelopePrefillTabsInput, + UpdateRecipientTabsValuesInput, + WebhookEnvelopeResponse, + WebhookOrganizationResponse, + WebhookRequest, + WorkflowDefPayloadSchema, + WorkflowDefinition, + WorkflowDefinitionResponse, + WorkflowDefinitionsResponse, + WorkflowId, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "DocusignClient", + "AccountCustomFields", + "Activity", + "ActivityListResponseEnvelope", + "AddDocumentsResponse", + "AddDocumentsToEnvelopeInput", + "AddRecipientTabsResponse", + "AddRecipientToEnvelopeRequest", + "AddRemindersResponse", + "AddVerificationToRecipientResponse", + "AdditionalRecipientData", + "AdditionalRecipientParamsSchema", + "AdditionalURL", + "AdditionalURLForSenderView", + "AnchorTabSchema", + "ApiError", + "ApplyTemplatesToDocumentsInput", + "AuditResponse", + "BuildNumberResponse", + "BuildNumberSchema", + "BulkSendListGuid", + "CombinedEmailBodyAndCustomFields", + "CompositeTemplateSchema", + "CompositeTemplatesResponse", + "CreateBulkSendListInput", + "CreateEnvelopeResponse", + "CreateHookEnvelopeInput", + "CreateHookEnvelopeResponse", + "CreateOrgHookEnvelopeInput", + "CreateOrgHookEnvelopeResponse", + "DeclineReasonWithoutType", + "DocGenFormField", + "DocGenFormFieldsResponse", + "DocumentRecord", + "DocumentRecordListResponseEnvelope", + "DocumentType", + "DocumentTypesResponse", + "DynamicRecipients", + "DynamicSigners", + "DynamicSigningUrlFields", + "EmailSummary", + "EmailSummaryResponse", + "EmbeddedSenderResponse", + "EmbeddedSigningResponse", + "Envelope", + "EnvelopeCustomFieldResponse", + "EnvelopeDocument", + "EnvelopeDocumentField", + "EnvelopeIDsResponse", + "EnvelopeIds", + "EnvelopeResendResponse", + "EnvelopeTemplate", + "EnvelopeVoidResponse", + "FilteredEnvelopeListResponse", + "FilteredEnvelopes", + "FilteredSalesCopilotEnvelopeListResponse", + "Folder", + "FolderItem", + "FontName", + "FontNamesResponse", + "GetDocGenTemplateTabsResponse", + "GetDocumentsResponse", + "GetDynamicRecipientsResponse", + "GetDynamicSignersResponse", + "GetLoginAccountsResponse", + "GetOrganizationsResponse", + "GetWorkFlowIdsResponse", + "KeySales", + "KeySalesResponse", + "ListDocumentsResponse", + "ListEnvelopeDocumentFieldsResponse", + "ListEnvelopesResponse", + "ListFoldersResponse", + "ListRecipientsResponse", + "ListSigningGroupResponse", + "ListTabsResponse", + "ListTemplateDocumentsResponse", + "ListTemplatesResponse", + "LoginAccount", + "MaestroInputVariables", + "OnEnvelopeStatusChangesResponse", + "Organization", + "RecipientTab", + "RecipientTabsResponse", + "RecipientType", + "RecipientTypesResponse", + "SalesCopilotFilteredEnvelopes", + "SendDraftEnvelopeResponse", + "SignatureType", + "SignatureTypesResponse", + "Signer", + "SignerRequest", + "SigningGroup", + "StaticResponseForAnchorTabSchemaResponse", + "StaticResponseForBuildNumberSchemaResponse", + "StaticResponseForCompositeTemplatesResponse", + "StaticResponseForEmbeddedSenderSchemaResponse", + "StaticResponseForEmbeddedSigningSchemaResponse", + "StaticResponseForRecipientTypeSchemaResponse", + "StaticResponseForVerificationTypeSchemaResponse", + "Tab", + "TabType", + "TabTypesResponse", + "TriggerMaestroFlowResponse", + "UpdateDocgenFormFieldsInput", + "UpdateEnvelopeCustomFieldResponse", + "UpdateEnvelopePrefillTabsInput", + "UpdateRecipientTabsValuesInput", + "WebhookEnvelopeResponse", + "WebhookOrganizationResponse", + "WebhookRequest", + "WorkflowDefPayloadSchema", + "WorkflowDefinition", + "WorkflowDefinitionResponse", + "WorkflowDefinitionsResponse", + "WorkflowId", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class DocusignClient(ConnectorClientBase): + """Typed client for docusign connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a DocusignClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "docusign" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_docgen_form_fields( + self, + account_id: str, + envelope_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get document generation form fields from envelope + + Get document generation form fields from envelope + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetDocgenFormFields`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/docGenFormFields" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("docgenFields", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_docgen_form_fields( + self, + input: UpdateDocgenFormFieldsInput, + account_id: str, + envelope_id: str, + document_guid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update document generation form fields from envelope + + Update document generation form fields from envelope + + Swagger operation ID: `UpdateDocgenFormFields`. + + Args: + input: The request body. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + document_guid: Document GUID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/docGenFormFields" + ) + query_params = [] + value = str(document_guid) + if isinstance(document_guid, bool): + value = value.lower() + query_params.append(f"documentGuid={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_doc_gen_template_tabs( + self, + account_id: str, + template_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get document generation form fields from template (bulk send templates + only) + + Get document generation form fields from template (bulk send templates + only) + + Swagger operation ID: `GetDocGenTemplateTabs`. + + Args: + account_id: Enter or select an account ID. + template_id: Enter or select a template ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/templates" + f"/{quote(str(template_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def void_envelope( + self, + account_id: str, + envelope_id: str, + voided_reason: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Void the envelope + + Void the envelope. + + Swagger operation ID: `VoidEnvelope`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + voided_reason: Voided reason. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/voidEnvelope" + ) + query_params = [] + value = str(voided_reason) + if isinstance(voided_reason, bool): + value = value.lower() + query_params.append(f"voidedReason={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def resend_envelope( + self, + envelope_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Resend the envelope + + This action resends a Docusign envelope or sends a reminder to + recipients who need to sign a Docusign agreement based on a provided + EnvelopeId. + + Swagger operation ID: `ResendEnvelope`. + + Args: + envelope_id: Enter an envelope ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/copilotAccount" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/resendEnvelope" + ) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_reminders( + self, + account_id: str, + envelope_id: str, + reminder_enabled: bool, + reminder_delay: str, + reminder_frequency: str, + *, + expire_after: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add reminders for an envelope + + Add reminders for an envelope + + Swagger operation ID: `AddReminders`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + reminder_enabled: When set to false the reminders are disabled. + Default is false. + reminder_delay: Add number of days after which recipient receives + reminder email. + reminder_frequency: Add number of days between reminder emails. + expire_after: Add number of days before expiry. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/notification" + ) + query_params = [] + value = str(reminder_enabled) + if isinstance(reminder_enabled, bool): + value = value.lower() + query_params.append(f"reminderEnabled={quote(value, safe='')}") + value = str(reminder_delay) + if isinstance(reminder_delay, bool): + value = value.lower() + query_params.append(f"reminderDelay={quote(value, safe='')}") + value = str(reminder_frequency) + if isinstance(reminder_frequency, bool): + value = value.lower() + query_params.append(f"reminderFrequency={quote(value, safe='')}") + if expire_after is not None: + value = str(expire_after) + if isinstance(expire_after, bool): + value = value.lower() + query_params.append(f"expireAfter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_envelope_document_tabs( + self, + account_id: str, + envelope_id: str, + document_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get document tabs from envelope + + Get document tabs from envelope + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetEnvelopeDocumentTabs`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + document_id: Enter a document ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/tabs" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("tabs", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_envelope_prefill_tabs( + self, + input: UpdateEnvelopePrefillTabsInput, + account_id: str, + envelope_id: str, + document_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update envelope prefill tabs + + Update values for a list of prefill tabs + + Swagger operation ID: `UpdateEnvelopePrefillTabs`. + + Args: + input: The request body. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + document_id: Enter a document ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/tabs" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + def list_template_document_tabs( + self, + account_id: str, + template_id: str, + document_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get document tabs from template + + Get document tabs from template + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTemplateDocumentTabs`. + + Args: + account_id: Enter or select an account ID. + template_id: Enter or select a template ID. + document_id: Enter a document ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/templates" + f"/{quote(str(template_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/tabs" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("tabs", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_envelope_document_fields( + self, + account_id: str, + envelope_id: str, + document_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get document custom fields from envelope + + Get document custom fields from envelope + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetEnvelopeDocumentFields`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + document_id: Enter a document ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("envelopeDocumentFields", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def composite_templates( + self, + input: CompositeTemplateSchema | Mapping[str, Any], + account_id: str, + email_subject: str, + status: str, + *, + email_body: Optional[str] = None, + merge_roles_on_draft: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create envelope using composite templates + + Create envelope using composite templates + + Swagger operation ID: `CompositeTemplates`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + email_subject: Subject of the email. + status: Envelope status. + email_body: Body of the email. + merge_roles_on_draft: Merge roles and delete empty recipients. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/compositeTemplates" + ) + query_params = [] + value = str(email_subject) + if isinstance(email_subject, bool): + value = value.lower() + query_params.append(f"emailSubject={quote(value, safe='')}") + if email_body is not None: + value = str(email_body) + if isinstance(email_body, bool): + value = value.lower() + query_params.append(f"emailBody={quote(value, safe='')}") + value = str(status) + if isinstance(status, bool): + value = value.lower() + query_params.append(f"status={quote(value, safe='')}") + if merge_roles_on_draft is not None: + value = str(merge_roles_on_draft) + if isinstance(merge_roles_on_draft, bool): + value = value.lower() + query_params.append(f"merge_roles_on_draft={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def search_list_envelopes( + self, + account_id: str, + *, + recipient_name: Optional[str] = None, + recipient_email_id: Optional[str] = None, + envelope_title: Optional[str] = None, + custom_field_name: Optional[str] = None, + custom_field_value: Optional[str] = None, + search_text: Optional[str] = None, + envelope_status: Optional[str] = None, + folder_ids: Optional[str] = None, + order_by: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + from_date: Optional[str] = None, + to_date: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + List envelopes + + This action brings back relevant Docusign envelopes based on envelope + status, date range, recipient name, recipient email address, envelope + title, document name, or envelope custom field value. The output is the + title, description, Envelope ID, document names, sender names, envelope + status, status date, date sent, and a URL of the envelope which can be + used as a link to view the envelope in Docusign. + + Swagger operation ID: `SearchListEnvelopes`. + + Args: + account_id: Enter or select an account ID. + recipient_name: This action lists envelopes based on recipient + name. + recipient_email_id: Filters envelopes by recipient email. + envelope_title: Filters envelopes by envelope subject. + custom_field_name: This action lists envelopes based on a name of + its custom fields. + custom_field_value: Filters by custom field value. + search_text: Enter one keyword to find matches in envelope + subjects, recipients, and custom fields. + envelope_status: This action lists envelopes based on status of the + envelope. + folder_ids: Filters envelopes by the selected folder. + order_by: Sorts envelopes in the selected order. + top: Specify the number of envelopes to return (default is 10; + maximum is 1,000). + skip: Specify the number of envelopes to skip from the start. + from_date: Enter start date-time in UTC format: 2017-05-02T01:44z. + to_date: Enter end date-time in UTC format: 2017-05-02T01:44z. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/SearchListEnvelopes" + ) + query_params = [] + if recipient_name is not None: + value = str(recipient_name) + if isinstance(recipient_name, bool): + value = value.lower() + query_params.append(f"recipientName={quote(value, safe='')}") + if recipient_email_id is not None: + value = str(recipient_email_id) + if isinstance(recipient_email_id, bool): + value = value.lower() + query_params.append(f"recipientEmailId={quote(value, safe='')}") + if envelope_title is not None: + value = str(envelope_title) + if isinstance(envelope_title, bool): + value = value.lower() + query_params.append(f"envelopeTitle={quote(value, safe='')}") + if custom_field_name is not None: + value = str(custom_field_name) + if isinstance(custom_field_name, bool): + value = value.lower() + query_params.append(f"customFieldName={quote(value, safe='')}") + if custom_field_value is not None: + value = str(custom_field_value) + if isinstance(custom_field_value, bool): + value = value.lower() + query_params.append(f"customFieldValue={quote(value, safe='')}") + if search_text is not None: + value = str(search_text) + if isinstance(search_text, bool): + value = value.lower() + query_params.append(f"search_text={quote(value, safe='')}") + if envelope_status is not None: + value = str(envelope_status) + if isinstance(envelope_status, bool): + value = value.lower() + query_params.append(f"envelopeStatus={quote(value, safe='')}") + if folder_ids is not None: + value = str(folder_ids) + if isinstance(folder_ids, bool): + value = value.lower() + query_params.append(f"folder_ids={quote(value, safe='')}") + if order_by is not None: + value = str(order_by) + if isinstance(order_by, bool): + value = value.lower() + query_params.append(f"order_by={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"skip={quote(value, safe='')}") + if from_date is not None: + value = str(from_date) + if isinstance(from_date, bool): + value = value.lower() + query_params.append(f"from_date={quote(value, safe='')}") + if to_date is not None: + value = str(to_date) + if isinstance(to_date, bool): + value = value.lower() + query_params.append(f"to_date={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_envelope_from_template_no_recipients( + self, + account_id: str, + template_id: str, + status: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create envelope using template + + Create a new envelope using a specified template. + + Swagger operation ID: `CreateEnvelopeFromTemplateNoRecipients`. + + Args: + account_id: Enter or select an account ID. + template_id: Enter or select a template ID. + status: Envelope status. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/createFromTemplateNoRecipients" + ) + query_params = [] + value = str(template_id) + if isinstance(template_id, bool): + value = value.lower() + query_params.append(f"templateId={quote(value, safe='')}") + value = str(status) + if isinstance(status, bool): + value = value.lower() + query_params.append(f"status={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_envelope( + self, + input: DynamicSigners | Mapping[str, Any], + account_id: str, + status: str, + template_id: str, + *, + email_subject: Optional[str] = None, + email_body: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create envelope using template with recipients + + Create a new envelope using a specified template and specify + recipients. + + Swagger operation ID: `SendEnvelope`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + status: Envelope status. + template_id: Enter or select a template ID. + email_subject: Email subject. + email_body: Email body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts/{quote(str(account_id), safe='')}/envelopes" + ) + query_params = [] + value = str(status) + if isinstance(status, bool): + value = value.lower() + query_params.append(f"status={quote(value, safe='')}") + value = str(template_id) + if isinstance(template_id, bool): + value = value.lower() + query_params.append(f"templateId={quote(value, safe='')}") + if email_subject is not None: + value = str(email_subject) + if isinstance(email_subject, bool): + value = value.lower() + query_params.append(f"emailSubject={quote(value, safe='')}") + if email_body is not None: + value = str(email_body) + if isinstance(email_body, bool): + value = value.lower() + query_params.append(f"emailBody={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_envelope_with_recipient_fields( + self, + input: DynamicRecipients | Mapping[str, Any], + account_id: str, + template_id: str, + *, + merge_roles_on_draft: Optional[str] = None, + email_subject: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create envelope using template with recipients and tabs + + Create envelope using template with recipients and tabs + + Swagger operation ID: `SendEnvelopeWithRecipientFields`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + template_id: Enter or select a template ID. + merge_roles_on_draft: Merge roles and delete empty recipients. + email_subject: Email subject. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/createWithRecipientFields" + ) + query_params = [] + value = str(template_id) + if isinstance(template_id, bool): + value = value.lower() + query_params.append(f"templateId={quote(value, safe='')}") + if merge_roles_on_draft is not None: + value = str(merge_roles_on_draft) + if isinstance(merge_roles_on_draft, bool): + value = value.lower() + query_params.append(f"merge_roles_on_draft={quote(value, safe='')}") + if email_subject is not None: + value = str(email_subject) + if isinstance(email_subject, bool): + value = value.lower() + query_params.append(f"emailSubject={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_draft_envelope( + self, + account_id: str, + envelope_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send envelope + + Send an existing envelope. + + Swagger operation ID: `SendDraftEnvelope`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_envelope_custom_field( + self, + account_id: str, + envelope_id: str, + field_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get envelope custom field info + + Get envelope custom field info. + + Swagger operation ID: `GetEnvelopeCustomField`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + field_name: Custom Field Name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/custom_fields" + ) + query_params = [] + value = str(field_name) + if isinstance(field_name, bool): + value = value.lower() + query_params.append(f"fieldName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_envelope_custom_field( + self, + account_id: str, + envelope_id: str, + field_id: str, + field_type: str, + name: str, + value: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update envelope custom field + + Update value for the specified envelope custom field + + Swagger operation ID: `UpdateEnvelopeCustomField`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + field_id: Custom Field ID. + field_type: Custom Field Type. + name: Custom Field Name. + value: Custom Field Value. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/custom_fields" + ) + query_params = [] + value = str(field_id) + if isinstance(field_id, bool): + value = value.lower() + query_params.append(f"fieldId={quote(value, safe='')}") + value = str(field_type) + if isinstance(field_type, bool): + value = value.lower() + query_params.append(f"fieldType={quote(value, safe='')}") + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + value = str(value) + if isinstance(value, bool): + value = value.lower() + query_params.append(f"value={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def generate_embedded_sender_url( + self, + input: AdditionalURLForSenderView | Mapping[str, Any], + account_id: str, + envelope_id: str, + open_in: str, + return_url: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Generate Embedded Sender URL + + Generate Embedded Sender URL + + Swagger operation ID: `GenerateEmbeddedSenderURL`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + open_in: Open in. + return_url: Return URL. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/views" + f"/sender" + ) + query_params = [] + value = str(open_in) + if isinstance(open_in, bool): + value = value.lower() + query_params.append(f"openIn={quote(value, safe='')}") + value = str(return_url) + if isinstance(return_url, bool): + value = value.lower() + query_params.append(f"returnUrl={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_recipient_status( + self, + account_id: str, + envelope_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + List recipients from an envelope + + List recipients from an envelope + + Swagger operation ID: `GetRecipientStatus`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/recipients" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def remove_recipient_from_envelope( + self, + account_id: str, + envelope_id: str, + folder_id: str, + remove_recipient_from_envelope_recipient_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Remove recipient from an envelope + + Remove recipient from an envelope + + Swagger operation ID: `RemoveRecipientFromEnvelope`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + folder_id: Folder ID. + remove_recipient_from_envelope_recipient_id: Recipient ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/recipients" + ) + query_params = [] + value = str(folder_id) + if isinstance(folder_id, bool): + value = value.lower() + query_params.append(f"folderId={quote(value, safe='')}") + value = str(remove_recipient_from_envelope_recipient_id) + if isinstance(remove_recipient_from_envelope_recipient_id, bool): + value = value.lower() + query_params.append(f"RemoveRecipientFromEnvelopeRecipientId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_recipient_fields( + self, + account_id: str, + envelope_id: str, + *, + recipient_email: Optional[str] = None, + area_code: Optional[str] = None, + phone_number: Optional[str] = None, + recipient_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get recipient info from envelope + + Get recipient info from envelope + + Swagger operation ID: `GetRecipientFields`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_email: Recipient email. + area_code: Area code of the recipient. + phone_number: Phone number of the recipient. + recipient_id: Enter a recipient ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/recipientFields" + ) + query_params = [] + if recipient_email is not None: + value = str(recipient_email) + if isinstance(recipient_email, bool): + value = value.lower() + query_params.append(f"recipientEmail={quote(value, safe='')}") + if area_code is not None: + value = str(area_code) + if isinstance(area_code, bool): + value = value.lower() + query_params.append(f"areaCode={quote(value, safe='')}") + if phone_number is not None: + value = str(phone_number) + if isinstance(phone_number, bool): + value = value.lower() + query_params.append(f"phoneNumber={quote(value, safe='')}") + if recipient_id is not None: + value = str(recipient_id) + if isinstance(recipient_id, bool): + value = value.lower() + query_params.append(f"recipientId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_audit_events( + self, + account_id: str, + envelope_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get audit event list + + Get audit event list + + Swagger operation ID: `GetAuditEvents`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/audit_events" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_verification_to_recipient( + self, + input: AdditionalRecipientData | Mapping[str, Any], + account_id: str, + envelope_id: str, + recipient_id: str, + recipient_type: str, + verification_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add verification type to a recipient + + Add verification type to a recipient. + + Swagger operation ID: `AddVerificationToRecipient`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_id: Enter a recipient ID. + recipient_type: Enter or select a recipient type. + verification_type: Verification type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/recipients" + f"/addRecipientV2" + ) + query_params = [] + value = str(recipient_id) + if isinstance(recipient_id, bool): + value = value.lower() + query_params.append(f"recipientId={quote(value, safe='')}") + value = str(recipient_type) + if isinstance(recipient_type, bool): + value = value.lower() + query_params.append(f"recipientType={quote(value, safe='')}") + value = str(verification_type) + if isinstance(verification_type, bool): + value = value.lower() + query_params.append(f"verificationType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_envelope_recipient( + self, + input: AdditionalRecipientParamsSchema | Mapping[str, Any], + account_id: str, + envelope_id: str, + recipient_id: str, + recipient_type: str, + *, + signature_type: Optional[str] = None, + client_user_id: Optional[str] = None, + embedded_recipient_start_u_r_l: Optional[str] = None, + routing_order: Optional[str] = None, + email_notification_language: Optional[str] = None, + email_notification_subject: Optional[str] = None, + email_notification_body: Optional[str] = None, + note: Optional[str] = None, + role_name: Optional[str] = None, + country_code: Optional[str] = None, + phone_number: Optional[str] = None, + signing_group_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update recipient on an envelope + + Update recipient on an envelope + + Swagger operation ID: `UpdateEnvelopeRecipient`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_id: Enter a recipient ID. + recipient_type: Recipient type. + signature_type: DocuSign standards-based-signature (SBS) types. + client_user_id: Client user ID for embedded signer. + embedded_recipient_start_u_r_l: A sender-provided URL string for + redirecting an embedded recipient. + routing_order: The signing order of the recipient. + email_notification_language: Language for the email notification. + email_notification_subject: Subject of the email notification. + email_notification_body: Body of the email notification. + note: Custom note for the recipient. + role_name: Role name associated with the recipient. + country_code: For SMS notifications, the country code, without + leading + sign. + phone_number: Signer email or SMS phone required. Exclude country + code for phone number. + signing_group_id: Signing Group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/recipients" + f"/updateRecipient" + ) + query_params = [] + value = str(recipient_id) + if isinstance(recipient_id, bool): + value = value.lower() + query_params.append(f"recipientId={quote(value, safe='')}") + if signature_type is not None: + value = str(signature_type) + if isinstance(signature_type, bool): + value = value.lower() + query_params.append(f"signatureType={quote(value, safe='')}") + value = str(recipient_type) + if isinstance(recipient_type, bool): + value = value.lower() + query_params.append(f"recipientType={quote(value, safe='')}") + if client_user_id is not None: + value = str(client_user_id) + if isinstance(client_user_id, bool): + value = value.lower() + query_params.append(f"clientUserId={quote(value, safe='')}") + if embedded_recipient_start_u_r_l is not None: + value = str(embedded_recipient_start_u_r_l) + if isinstance(embedded_recipient_start_u_r_l, bool): + value = value.lower() + query_params.append(f"embeddedRecipientStartURL={quote(value, safe='')}") + if routing_order is not None: + value = str(routing_order) + if isinstance(routing_order, bool): + value = value.lower() + query_params.append(f"routingOrder={quote(value, safe='')}") + if email_notification_language is not None: + value = str(email_notification_language) + if isinstance(email_notification_language, bool): + value = value.lower() + query_params.append(f"emailNotificationLanguage={quote(value, safe='')}") + if email_notification_subject is not None: + value = str(email_notification_subject) + if isinstance(email_notification_subject, bool): + value = value.lower() + query_params.append(f"emailNotificationSubject={quote(value, safe='')}") + if email_notification_body is not None: + value = str(email_notification_body) + if isinstance(email_notification_body, bool): + value = value.lower() + query_params.append(f"emailNotificationBody={quote(value, safe='')}") + if note is not None: + value = str(note) + if isinstance(note, bool): + value = value.lower() + query_params.append(f"note={quote(value, safe='')}") + if role_name is not None: + value = str(role_name) + if isinstance(role_name, bool): + value = value.lower() + query_params.append(f"roleName={quote(value, safe='')}") + if country_code is not None: + value = str(country_code) + if isinstance(country_code, bool): + value = value.lower() + query_params.append(f"countryCode={quote(value, safe='')}") + if phone_number is not None: + value = str(phone_number) + if isinstance(phone_number, bool): + value = value.lower() + query_params.append(f"phoneNumber={quote(value, safe='')}") + if signing_group_id is not None: + value = str(signing_group_id) + if isinstance(signing_group_id, bool): + value = value.lower() + query_params.append(f"signingGroupId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def apply_templates_to_documents( + self, + input: ApplyTemplatesToDocumentsInput | Mapping[str, Any], + account_id: str, + envelope_id: str, + template_id: str, + *, + preserve_template_recipient: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Apply a template to documents + + Apply a template to documents + + Swagger operation ID: `ApplyTemplatesToDocuments`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + template_id: Enter or select a template ID. + preserve_template_recipient: False. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/templates" + ) + query_params = [] + value = str(template_id) + if isinstance(template_id, bool): + value = value.lower() + query_params.append(f"templateId={quote(value, safe='')}") + if preserve_template_recipient is not None: + value = str(preserve_template_recipient) + if isinstance(preserve_template_recipient, bool): + value = value.lower() + query_params.append(f"preserve_template_recipient={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def create_bulk_send_list( + self, + input: CreateBulkSendListInput | Mapping[str, Any], + account_id: str, + name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create bulk send list + + Create bulk send list + + Swagger operation ID: `CreateBulkSendList`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + name: Bulk send list name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts/{quote(str(account_id), safe='')}/bulk_send_lists" + ) + query_params = [] + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def bulk_send( + self, + account_id: str, + bulk_send_list_id: str, + envelope_or_template_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Bulk send envelope using template + + Bulk send envelope using template + + Swagger operation ID: `BulkSend`. + + Args: + account_id: Enter or select an account ID. + bulk_send_list_id: Bulk send list GUID. + envelope_or_template_id: Enter the template ID, or choose a + template from the dropdown. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/bulk_send_lists" + f"/{quote(str(bulk_send_list_id), safe='')}" + f"/send" + ) + query_params = [] + value = str(envelope_or_template_id) + if isinstance(envelope_or_template_id, bool): + value = value.lower() + query_params.append(f"envelopeOrTemplateId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_login_accounts( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Login + + Login + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetLoginAccounts`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/oauth/userinfo" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("loginAccounts", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_envelope_templates( + self, + account_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List templates + + List templates for a specific account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetEnvelopeTemplates`. + + Args: + account_id: Enter or select an account ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts/{quote(str(account_id), safe='')}/templates" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("envelopeTemplates", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def add_documents_to_envelope( + self, + input: AddDocumentsToEnvelopeInput | Mapping[str, Any], + account_id: str, + envelope_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add documents to an envelope + + Add documents to an envelope. + + Swagger operation ID: `AddDocumentsToEnvelope`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/documents" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_template_documents( + self, + account_id: str, + template_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List documents from a template + + List documents from a template + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTemplateDocuments`. + + Args: + account_id: Enter or select an account ID. + template_id: Enter or select a template ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/templates" + f"/{quote(str(template_id), safe='')}" + f"/documents" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("templateDocuments", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_envelope_documents( + self, + account_id: str, + envelope_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List documents from an envelope + + List documents from an envelope + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListEnvelopeDocuments`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/envelopeDocuments" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("envelopeDocuments", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_envelope_document_info( + self, + account_id: str, + envelope_id: str, + document_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get document info from envelope + + Get document info from envelope + + Swagger operation ID: `GetEnvelopeDocumentInfo`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + document_name: File name with extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/get_document_info" + ) + query_params = [] + value = str(document_name) + if isinstance(document_name, bool): + value = value.lower() + query_params.append(f"documentName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_tab_info( + self, + account_id: str, + envelope_id: str, + recipient_id: str, + tab_label: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get info for recipient tab + + Returns the value of the tab for the given recipient + + Swagger operation ID: `GetTabInfo`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_id: Enter a recipient ID. + tab_label: Tab label. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/recipients" + f"/{quote(str(recipient_id), safe='')}" + f"/tabs" + ) + query_params = [] + value = str(tab_label) + if isinstance(tab_label, bool): + value = value.lower() + query_params.append(f"tabLabel={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_recipient_tabs( + self, + input: AnchorTabSchema | Mapping[str, Any], + account_id: str, + envelope_id: str, + recipient_id: str, + tab_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add tabs for a recipient on an envelope + + Add tabs for a recipient on an envelope + + Swagger operation ID: `AddRecipientTabs`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_id: Enter a recipient ID. + tab_type: Tab type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/recipients" + f"/{quote(str(recipient_id), safe='')}" + f"/tabs" + ) + query_params = [] + value = str(tab_type) + if isinstance(tab_type, bool): + value = value.lower() + query_params.append(f"tabType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_recipient_tabs_values( + self, + input: UpdateRecipientTabsValuesInput, + account_id: str, + envelope_id: str, + recipient_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update recipient tab values on an envelope + + Update recipient tab values on an envelope + + Swagger operation ID: `UpdateRecipientTabsValues`. + + Args: + input: The request body. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_id: Enter a recipient ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/recipients" + f"/{quote(str(recipient_id), safe='')}" + f"/tabs" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + def list_envelope_recipient_tabs( + self, + account_id: str, + envelope_id: str, + recipient_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get recipient tabs from envelope + + Get recipient tabs from envelope + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetEnvelopeRecipientTabs`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_id: Enter a recipient ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/recipients" + f"/{quote(str(recipient_id), safe='')}" + f"/recipientTabs" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("recipientTabs", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def trigger_maestro_flow( + self, + input: MaestroInputVariables | Mapping[str, Any], + account_id: str, + workflow_id: str, + instance_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Start Docusign workflow + + Start Docusign workflow + + Swagger operation ID: `TriggerMaestroFlow`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + workflow_id: Enter the workflow ID or select the workflow name from + the dropdown. + instance_name: Name of the workflow instance. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/maestro-workflows" + f"/trigger" + f"/{quote(str(workflow_id), safe='')}" + ) + query_params = [] + value = str(instance_name) + if isinstance(instance_name, bool): + value = value.lower() + query_params.append(f"instanceName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def build_number( + self, + input: BuildNumberSchema | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Show build Number (For reference only. Do not include in a flow for + execution) + + Identifier for the currently deployed build. + + Swagger operation ID: `BuildNumber`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/build_number" + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_recipient_to_envelope( + self, + input: AdditionalRecipientParamsSchema | Mapping[str, Any], + account_id: str, + envelope_id: str, + recipient_type: str, + *, + client_user_id: Optional[str] = None, + recipient_id: Optional[str] = None, + embedded_recipient_start_u_r_l: Optional[str] = None, + routing_order: Optional[str] = None, + email_notification_language: Optional[str] = None, + email_notification_subject: Optional[str] = None, + email_notification_body: Optional[str] = None, + note: Optional[str] = None, + role_name: Optional[str] = None, + country_code: Optional[str] = None, + phone_number: Optional[str] = None, + signing_group_id: Optional[str] = None, + signature_type: Optional[str] = None, + workflow_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add recipient to an envelope + + Add recipient to an envelope. + + Swagger operation ID: `AddRecipientToEnvelopeV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_type: Enter or select a recipient type. + client_user_id: Client user ID for embedded signer. + recipient_id: Enter a recipient ID. + embedded_recipient_start_u_r_l: A sender-provided URL string for + redirecting an embedded recipient. + routing_order: The signing order of the recipient. + email_notification_language: Language for the email notification. + email_notification_subject: Subject of the email notification. + email_notification_body: Body of the email notification. + note: Custom note for the recipient. + role_name: Role name associated with the recipient. + country_code: For SMS notifications, the country code, without + leading + sign. + phone_number: Signer email or SMS phone required. Exclude country + code for phone number. + signing_group_id: Signing Group. + signature_type: DocuSign standards-based-signature (SBS) types. + workflow_id: IDV workflows with pen signature types must be + selected here. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/recipients" + f"/addRecipientV2" + ) + query_params = [] + value = str(recipient_type) + if isinstance(recipient_type, bool): + value = value.lower() + query_params.append(f"recipientType={quote(value, safe='')}") + if client_user_id is not None: + value = str(client_user_id) + if isinstance(client_user_id, bool): + value = value.lower() + query_params.append(f"clientUserId={quote(value, safe='')}") + if recipient_id is not None: + value = str(recipient_id) + if isinstance(recipient_id, bool): + value = value.lower() + query_params.append(f"recipientId={quote(value, safe='')}") + if embedded_recipient_start_u_r_l is not None: + value = str(embedded_recipient_start_u_r_l) + if isinstance(embedded_recipient_start_u_r_l, bool): + value = value.lower() + query_params.append(f"embeddedRecipientStartURL={quote(value, safe='')}") + if routing_order is not None: + value = str(routing_order) + if isinstance(routing_order, bool): + value = value.lower() + query_params.append(f"routingOrder={quote(value, safe='')}") + if email_notification_language is not None: + value = str(email_notification_language) + if isinstance(email_notification_language, bool): + value = value.lower() + query_params.append(f"emailNotificationLanguage={quote(value, safe='')}") + if email_notification_subject is not None: + value = str(email_notification_subject) + if isinstance(email_notification_subject, bool): + value = value.lower() + query_params.append(f"emailNotificationSubject={quote(value, safe='')}") + if email_notification_body is not None: + value = str(email_notification_body) + if isinstance(email_notification_body, bool): + value = value.lower() + query_params.append(f"emailNotificationBody={quote(value, safe='')}") + if note is not None: + value = str(note) + if isinstance(note, bool): + value = value.lower() + query_params.append(f"note={quote(value, safe='')}") + if role_name is not None: + value = str(role_name) + if isinstance(role_name, bool): + value = value.lower() + query_params.append(f"roleName={quote(value, safe='')}") + if country_code is not None: + value = str(country_code) + if isinstance(country_code, bool): + value = value.lower() + query_params.append(f"countryCode={quote(value, safe='')}") + if phone_number is not None: + value = str(phone_number) + if isinstance(phone_number, bool): + value = value.lower() + query_params.append(f"phoneNumber={quote(value, safe='')}") + if signing_group_id is not None: + value = str(signing_group_id) + if isinstance(signing_group_id, bool): + value = value.lower() + query_params.append(f"signingGroupId={quote(value, safe='')}") + if signature_type is not None: + value = str(signature_type) + if isinstance(signature_type, bool): + value = value.lower() + query_params.append(f"signatureType={quote(value, safe='')}") + if workflow_id is not None: + value = str(workflow_id) + if isinstance(workflow_id, bool): + value = value.lower() + query_params.append(f"workflowId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_blank_envelope( + self, + input: CombinedEmailBodyAndCustomFields | Mapping[str, Any], + account_id: str, + email_subject: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create envelope + + Create a new blank envelope. + + Swagger operation ID: `CreateBlankEnvelopeV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + email_subject: Subject of the email. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/createBlankEnvelopeV2" + ) + query_params = [] + value = str(email_subject) + if isinstance(email_subject, bool): + value = value.lower() + query_params.append(f"emailSubject={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def generate_embedded_signing_url( + self, + input: DynamicSigningUrlFields | Mapping[str, Any], + account_id: str, + envelope_id: str, + is_in_person_signer: str, + authentication_method: str, + return_url: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Generate Embedded Signing URL + + Generate Embedded Signing URL + + Swagger operation ID: `GenerateEmbeddedSigningURLV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + is_in_person_signer: Yes/No. + authentication_method: Authentication Method. + return_url: Return URL. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/views" + f"/recipientV2" + ) + query_params = [] + value = str(is_in_person_signer) + if isinstance(is_in_person_signer, bool): + value = value.lower() + query_params.append(f"isInPersonSigner={quote(value, safe='')}") + value = str(authentication_method) + if isinstance(authentication_method, bool): + value = value.lower() + query_params.append(f"authenticationMethod={quote(value, safe='')}") + value = str(return_url) + if isinstance(return_url, bool): + value = value.lower() + query_params.append(f"returnUrl={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_documents( + self, + account_id: str, + envelope_id: str, + document_id: str, + *, + language: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get documents from an envelope + + Get documents from an envelope + + Swagger operation ID: `GetDocumentsV2`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + document_id: Enter \"string(document ID)\" to get a single + document, or select a format. + language: Select language. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/envelopes" + f"/{quote(str(envelope_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/documentsDownload" + ) + query_params = [] + if language is not None: + value = str(language) + if isinstance(language, bool): + value = value.lower() + query_params.append(f"language={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_organizations( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get organizations + + Get organizations + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetOrganizations`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/Management/v2/organizations" + ) + query_params = [] + query_params.append("mode=" + quote("org_admin", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("organizations", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_account_custom_fields( + self, + account_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get account custom fields + + Get the custom fields for a specified account. + + Swagger operation ID: `GetAccountCustomFields`. + + Args: + account_id: Account id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/account_custom_fields" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + def list_get_folder( + self, + account_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List folders + + List folders for a specific account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetFolderList`. + + Args: + account_id: Account id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts/{quote(str(account_id), safe='')}/folders" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("folders", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_get_folder_envelope( + self, + account_id: str, + folder_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List envelopes + + List envelopes under a particular folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetFolderEnvelopeList`. + + Args: + account_id: Enter or select an account ID. + folder_id: Folder id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/folders" + f"/{quote(str(folder_id), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("folderItems", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_static_response_for_recipient_types( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + StaticResponseForRecipientTypes + + Get recipient types. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `StaticResponseForRecipientTypes`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/recipient_types" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("tabTypes", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_static_response_for_signature_types( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + StaticResponseForSignatureTypes + + Get signature types. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `StaticResponseForSignatureTypes`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/signature_types" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("tabTypes", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_signing_groups( + self, + account_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + GetSigningGroups + + List signing groups for a specific account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetSigningGroups`. + + Args: + account_id: Account id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts/{quote(str(account_id), safe='')}/signing_groups" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("signingGroups", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_static_response_for_tab_types( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + StaticResponseForTabTypes + + Get tab types. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `StaticResponseForTabTypes`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/tab_types" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("tabTypes", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_maestro_workflow_definitions( + self, + account_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Maestro Workflow Definitions + + Get Maestro Workflow Definitions + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMaestroWorkflowDefinitions`. + + Args: + account_id: accountId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts/{quote(str(account_id), safe='')}/maestro-workflows" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("WorkflowDefinitions", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_all_workflow_i_ds( + self, + account_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get All Workflow Ids + + Get All workflow ids + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAllWorkflowIDs`. + + Args: + account_id: Account id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/all_identity_verification" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("workflowIds", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_maestro_workflow_definition( + self, + account_id: str, + workflow_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Maestro Workflow Definition + + Get Maestro Workflow Definition + + Swagger operation ID: `GetMaestroWorkflowDefinition`. + + Args: + account_id: accountId. + workflow_id: workflowId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/maestro-workflows" + f"/{quote(str(workflow_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_dynamic_signers( + self, + account_id: str, + template_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get the signers of a template in dynamic schema format + + Get the signers of a template in dynamic schema format. + + Swagger operation ID: `GetDynamicSigners`. + + Args: + account_id: Account to get the signers for. + template_id: Template to get the signers for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/signers" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/templates" + f"/{quote(str(template_id), safe='')}" + f"/recipients" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_dynamic_recipients( + self, + account_id: str, + template_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get the signers of a template in dynamic schema format + + Get the signers of a template in dynamic schema format. + + Swagger operation ID: `GetDynamicRecipients`. + + Args: + account_id: Account to get the signers for. + template_id: Template to get the signers for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/signers" + f"/accounts" + f"/{quote(str(account_id), safe='')}" + f"/templates" + f"/{quote(str(template_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def static_response_for_recipient_type_schema( + self, + recipient_type: str, + *, + signature_type: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + StaticResponseForRecipientTypeSchema + + Get schema for a specific recipient type. + + Swagger operation ID: `StaticResponseForRecipientTypeSchema`. + + Args: + recipient_type: recipient type. + signature_type: signature type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/recipienttype_schema" + query_params = [] + value = str(recipient_type) + if isinstance(recipient_type, bool): + value = value.lower() + query_params.append(f"recipientType={quote(value, safe='')}") + if signature_type is not None: + value = str(signature_type) + if isinstance(signature_type, bool): + value = value.lower() + query_params.append(f"signatureType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def static_response_for_verification_type_schema( + self, + verification_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + StaticResponseForVerificationTypeSchema + + Get schema for a verification type. + + Swagger operation ID: `StaticResponseForVerificationTypeSchema`. + + Args: + verification_type: Verification Type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/verificationtype_schema" + query_params = [] + value = str(verification_type) + if isinstance(verification_type, bool): + value = value.lower() + query_params.append(f"verificationType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def static_response_for_embedded_sender_schema( + self, + return_url: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + StaticResponseForEmbeddedSenderSchema + + Get schema for return URL. + + Swagger operation ID: `StaticResponseForEmbeddedSenderSchema`. + + Args: + return_url: Return URL. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/embeddedSender_schema" + query_params = [] + value = str(return_url) + if isinstance(return_url, bool): + value = value.lower() + query_params.append(f"returnUrl={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def static_response_for_embedded_signing_schema( + self, + return_url: str, + is_in_person_signer: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + StaticResponseForEmbeddedSigningSchema + + Get schema for return URL. + + Swagger operation ID: `StaticResponseForEmbeddedSigningSchemaV2`. + + Args: + return_url: Return URL. + is_in_person_signer: Is this an in-person signer? + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/embeddedSigning_schema_v2" + ) + query_params = [] + value = str(return_url) + if isinstance(return_url, bool): + value = value.lower() + query_params.append(f"returnUrl={quote(value, safe='')}") + value = str(is_in_person_signer) + if isinstance(is_in_person_signer, bool): + value = value.lower() + query_params.append(f"isInPersonSigner={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def static_response_for_build_number_schema( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + StaticResponseForBuildNumberSchema + + Get schema for a build number. + + Swagger operation ID: `StaticResponseForBuildNumberSchema`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/build_number_schema" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_custom_fields( + self, + account_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get custom fields from an account + + Get custom fields from an account + + Swagger operation ID: `GetCustomFields`. + + Args: + account_id: Account id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/accounts/{quote(str(account_id), safe='')}/custom_fields" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + async def static_response_for_anchor_tab_schema( + self, + tab_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + StaticResponseForAnchorTabSchema + + Get schema for a specific anchor tab. + + Swagger operation ID: `StaticResponseForAnchorTabSchema`. + + Args: + tab_type: tab type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/anchortab_schema" + query_params = [] + value = str(tab_type) + if isinstance(tab_type, bool): + value = value.lower() + query_params.append(f"tabType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def static_response_for_composite_templates( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + StaticResponseForCompositeTemplates + + Get schema for a composite templates. + + Swagger operation ID: `StaticResponseForCompositeTemplates`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/composite_templates_schema" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/docuware.py b/src/azure/connectors/aio/docuware.py new file mode 100644 index 0000000..2f83360 --- /dev/null +++ b/src/azure/connectors/aio/docuware.py @@ -0,0 +1,1359 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# DocuwareClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.docuware import ( + GetDialogFieldsResponse, + GetDialogsResponse, + GetDocumentInformationResponse, + GetFileCabinetFieldsResponse, + GetFileCabinetsResponse, + GetOrganizationResponse, + GetStampFieldsResponse, + GetStampsResponse, + ListDocumentsInDocumentTrayResponse, + PlaceAStampInput, + PlaceAStampResponse, + SearchForDocumentsInFileCabinetInput, + SearchForDocumentsInFileCabinetResponse, + TransferDocumentInput, + TransferDocumentResponse, + UpdateIndexFieldsInput, + UpdateIndexFieldsResponse, +) + +__all__ = [ + "DocuwareClient", + "GetDialogFieldsResponse", + "GetDialogsResponse", + "GetDocumentInformationResponse", + "GetFileCabinetFieldsResponse", + "GetFileCabinetsResponse", + "GetOrganizationResponse", + "GetStampFieldsResponse", + "GetStampsResponse", + "ListDocumentsInDocumentTrayResponse", + "PlaceAStampInput", + "PlaceAStampResponse", + "SearchForDocumentsInFileCabinetInput", + "SearchForDocumentsInFileCabinetResponse", + "TransferDocumentInput", + "TransferDocumentResponse", + "UpdateIndexFieldsInput", + "UpdateIndexFieldsResponse", +] + + +# Type Definitions + +# Client Class + +class DocuwareClient(ConnectorClientBase): + """Typed client for docuware connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a DocuwareClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "docuware" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def search_for_documents_in_file_cabinet( + self, + input: SearchForDocumentsInFileCabinetInput | Mapping[str, Any], + file_cabinet: str, + search_dialog_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Search in file cabinet + + Search a file cabinet for documents matching the specified criteria. + + Swagger operation ID: `SearchForDocumentsInFileCabinet`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + file_cabinet: Select the File Cabinet to search. + search_dialog_id: Select the search dialog to use for searching. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/FileCabinets/{quote(str(file_cabinet), safe='')}/Search" + ) + query_params = [] + value = str(search_dialog_id) + if isinstance(search_dialog_id, bool): + value = value.lower() + query_params.append(f"SearchDialogId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_organization( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get organization + + Get the organization name. + + Swagger operation ID: `GetOrganization`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Organization" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_file_cabinets( + self, + file_cabinet_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get file cabinets and document trays + + Gets a list of file cabinets and/or document trays. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetFileCabinets`. + + Args: + file_cabinet_type: Select which types you want returned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/FileCabinets" + query_params = [] + value = str(file_cabinet_type) + if isinstance(file_cabinet_type, bool): + value = value.lower() + query_params.append(f"FileCabinetType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("FileCabinets", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_document_information( + self, + file_cabinet_id: str, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get document information + + Gets information about a document. + + Swagger operation ID: `GetDocumentInformation`. + + Args: + file_cabinet_id: Select the File Cabinet or Document Tray with your + document. + document_id: Specify the ID of the document you want information + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/FileCabinets" + f"/{quote(str(file_cabinet_id), safe='')}" + f"/Documents" + f"/{quote(str(document_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_document( + self, + file_cabinet_id: str, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a document + + Deletes a document from a file cabinet or document tray. + + Swagger operation ID: `DeleteDocument`. + + Args: + file_cabinet_id: Select the File Cabinet or Document Tray with your + document. + document_id: Specify the ID of the document you want to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/FileCabinets" + f"/{quote(str(file_cabinet_id), safe='')}" + f"/Documents" + f"/{quote(str(document_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def download_file( + self, + file_cabinet_id: str, + document_id: int, + file_number: str, + document_format: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Download a file + + Downloads a file/section of a document stored in a file cabinet or + document tray. + + Swagger operation ID: `DownloadFile`. + + Args: + file_cabinet_id: Select the File Cabinet or Document Tray with your + document. + document_id: Specify the ID of the document with the file you want + to download. + file_number: Specify the file number of the file you want to + download. + document_format: Select the format for the downloaded document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/FileCabinets" + f"/{quote(str(file_cabinet_id), safe='')}" + f"/Documents" + f"/{quote(str(document_id), safe='')}" + f"/Sections" + f"/{quote(str(file_number), safe='')}" + f"/Download" + ) + query_params = [] + value = str(document_format) + if isinstance(document_format, bool): + value = value.lower() + query_params.append(f"DocumentFormat={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def download_document( + self, + file_cabinet_id: str, + document_id: int, + document_format: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Download a document + + Downloads a document from a file cabinet or document tray. + + Swagger operation ID: `DownloadDocument`. + + Args: + file_cabinet_id: Select the File Cabinet or Document Tray with your + document. + document_id: Specify the ID of the document you want to download. + document_format: Select the format for the downloaded document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/FileCabinets" + f"/{quote(str(file_cabinet_id), safe='')}" + f"/Documents" + f"/{quote(str(document_id), safe='')}" + f"/Download" + ) + query_params = [] + value = str(document_format) + if isinstance(document_format, bool): + value = value.lower() + query_params.append(f"DocumentFormat={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def update_index_fields( + self, + input: UpdateIndexFieldsInput, + file_cabinet_id: str, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update index fields + + Updates the index fields of a document. + + Swagger operation ID: `UpdateIndexFields`. + + Args: + input: The request body. + file_cabinet_id: Select the File Cabinet with the document to + update. + document_id: Specify the ID of the document to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/FileCabinets" + f"/{quote(str(file_cabinet_id), safe='')}" + f"/Documents" + f"/{quote(str(document_id), safe='')}" + f"/Fields" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def transfer_document( + self, + input: TransferDocumentInput | Mapping[str, Any], + destination_file_cabinet_id: str, + *, + store_dialog_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Transfer documents + + Moves one or more documents from one file cabinet/document tray to + another. + + Swagger operation ID: `TransferDocument`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + destination_file_cabinet_id: Select the destination File Cabinet or + Document Tray. + store_dialog_id: Select the store dialog for indexing the documents + being moved. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/FileCabinets" + f"/{quote(str(destination_file_cabinet_id), safe='')}" + f"/Task" + f"/Transfer" + ) + query_params = [] + if store_dialog_id is not None: + value = str(store_dialog_id) + if isinstance(store_dialog_id, bool): + value = value.lower() + query_params.append(f"StoreDialogID={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def place_a_stamp( + self, + input: PlaceAStampInput | Mapping[str, Any], + file_cabinet_id: str, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Place a stamp + + Places a stamp on a document. + + Swagger operation ID: `PlaceAStamp`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + file_cabinet_id: Select the File Cabinet or Document Tray with your + document. + document_id: Specify the ID of the document you want to stamp. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/FileCabinets" + f"/{quote(str(file_cabinet_id), safe='')}" + f"/Documents" + f"/{quote(str(document_id), safe='')}" + f"/Annotation" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_dialogs( + self, + file_cabinet: str, + *, + dialog_type: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get dialogs + + Gets a list of dialogs for a file cabinet or document tray. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetDialogs`. + + Args: + file_cabinet: Select the File Cabinet or Document Tray to get + dialogs from. + dialog_type: Select the type of dialogs to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/FileCabinets/{quote(str(file_cabinet), safe='')}/Dialogs" + ) + query_params = [] + if dialog_type is not None: + value = str(dialog_type) + if isinstance(dialog_type, bool): + value = value.lower() + query_params.append(f"DialogType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("Dialogs", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_stamps( + self, + file_cabinet: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get stamps + + Gets a list of stamps for a file cabinet or document tray. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetStamps`. + + Args: + file_cabinet: Select the File Cabinet or Document Tray to get + stamps from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/FileCabinets/{quote(str(file_cabinet), safe='')}/Stamps" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("Stamps", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_stamp_fields( + self, + file_cabinet: str, + stamp: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get stamp fields + + Gets a list of fields for a stamp. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetStampFields`. + + Args: + file_cabinet: Select the File Cabinet or Document Tray with the + desired stamp. + stamp: Select the stamp to get its fields. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/FileCabinets" + f"/{quote(str(file_cabinet), safe='')}" + f"/Stamps" + f"/{quote(str(stamp), safe='')}" + f"/Fields" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("Fields", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_file_cabinet_fields( + self, + file_cabinet: str, + *, + field_type: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get file cabinet fields + + Gets a list of fields for a file cabinet. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetFileCabinetFields`. + + Args: + file_cabinet: Select the File Cabinet to get fields for. + field_type: Select the type of fields to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/FileCabinets/{quote(str(file_cabinet), safe='')}/Fields" + ) + query_params = [] + if field_type is not None: + value = str(field_type) + if isinstance(field_type, bool): + value = value.lower() + query_params.append(f"FieldType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("Fields", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_dialog_fields( + self, + file_cabinet: str, + dialog_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get dialog fields + + Gets the fields for a dialog + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetDialogFields`. + + Args: + file_cabinet: Select the File Cabinet. + dialog_id: Select the dialog to get the fields for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/FileCabinets" + f"/{quote(str(file_cabinet), safe='')}" + f"/Dialogs" + f"/{quote(str(dialog_id), safe='')}" + f"/Fields" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("Fields", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_documents_in_document_tray( + self, + document_tray: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List documents in document tray + + List documents from the specified document tray. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListDocumentsInDocumentTray`. + + Args: + document_tray: Select the Document Tray to search. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/DocumentTrays/{quote(str(document_tray), safe='')}/Search" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("Documents", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/dropbox.py b/src/azure/connectors/aio/dropbox.py new file mode 100644 index 0000000..9d7a959 --- /dev/null +++ b/src/azure/connectors/aio/dropbox.py @@ -0,0 +1,914 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# DropboxClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.dropbox import ( + BlobDataSetsMetadata, + BlobMetadata, + BlobMetadataPage, + BlobMetadataResponse, + DataSetsMetadata, + ObjectEntity, + TabularDataSetsMetadata, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "DropboxClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "BlobMetadataPage", + "BlobMetadataResponse", + "DataSetsMetadata", + "ObjectEntity", + "TabularDataSetsMetadata", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class DropboxClient(ConnectorClientBase): + """Typed client for dropbox connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a DropboxClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "dropbox" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def get_file_metadata( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file metadata + + This operation gets the metadata for a file. + + Swagger operation ID: `GetFileMetadata`. + + Args: + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_file( + self, + input: bytes, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update file + + This operation updates a file. + + Swagger operation ID: `UpdateFile`. + + Args: + input: The binary request body. + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PUT", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_file( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete file + + This operation deletes a file. + + Swagger operation ID: `DeleteFile`. + + Args: + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_file_metadata_by_path( + self, + path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file metadata using path + + This operation gets the metadata of a file using the path. + + Swagger operation ID: `GetFileMetadataByPath`. + + Args: + path: The unique path of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/GetFileByPath" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_file_content_by_path( + self, + path: str, + *, + infer_content_type: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file content using path + + This operation gets the content of a file using the path. + + Swagger operation ID: `GetFileContentByPath`. + + Args: + path: The unique path of the file. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/GetFileContentByPath" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def get_file_content( + self, + id: str, + *, + infer_content_type: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file content + + This operation gets the content of a file. + + Swagger operation ID: `GetFileContent`. + + Args: + id: The unique identifier of the file. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/content" + ) + query_params = [] + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def create_file( + self, + input: bytes, + folder_path: str, + name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create file + + This operation creates a file in a folder. + + Swagger operation ID: `CreateFile`. + + Args: + input: The binary request body. + folder_path: The path to the folder. + name: The name of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/datasets/default/files" + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def copy_file( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Copy file + + This operation copies a file to Dropbox. + + Swagger operation ID: `CopyFile`. + + Args: + source: The url to source file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/copyFile" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_folder( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List files in folder + + This operation gets the list of files and subfolders in a folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListFolder`. + + Args: + id: The unique identifier of the folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/folders" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_root_folder( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List files in root folder + + This operation gets the list of files and subfolders in the root + folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListRootFolder`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/folders" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def extract_folder( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Extract archive to folder + + This operation extracts an archive file into a folder (example: .zip). + + Swagger operation ID: `ExtractFolderV2`. + + Args: + source: The path to the archive file. + destination: The path to extract the archive contents. + overwrite: Overwrites the destination files if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/extractFolderV2" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/dynamicsax.py b/src/azure/connectors/aio/dynamicsax.py new file mode 100644 index 0000000..0a227ff --- /dev/null +++ b/src/azure/connectors/aio/dynamicsax.py @@ -0,0 +1,1300 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# DynamicsaxClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.dynamicsax import ( + AxOnlineProcedureResult, + BlobDataSetsMetadata, + BusinessEventData, + BusinessEventSubscription, + BusinessEventSubscriptionResponse, + BusinessEventsList, + DataSet, + DataSetsList, + DataSetsMetadata, + ExecuteProcedureInput, + ExportableItem, + ExportableItemsList, + GetItemResponse, + Item, + ItemsList, + ObjectEntity, + PassThroughNativeQuery, + PatchItemInput, + PatchItemResponse, + PostItemInput, + PostItemResponse, + Procedure, + ProcedureMetadata, + ProceduresList, + Table, + TableCapabilitiesMetadata, + TableFilterRestrictionsMetadata, + TableMetadata, + TableSelectRestrictionsMetadata, + TableSortRestrictionsMetadata, + TablesList, + TabularDataSetsMetadata, + TriggerFieldData, + TriggerFieldDataList, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "DynamicsaxClient", + "AxOnlineProcedureResult", + "BlobDataSetsMetadata", + "BusinessEventData", + "BusinessEventSubscription", + "BusinessEventSubscriptionResponse", + "BusinessEventsList", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "ExecuteProcedureInput", + "ExportableItem", + "ExportableItemsList", + "GetItemResponse", + "Item", + "ItemsList", + "ObjectEntity", + "PassThroughNativeQuery", + "PatchItemInput", + "PatchItemResponse", + "PostItemInput", + "PostItemResponse", + "Procedure", + "ProcedureMetadata", + "ProceduresList", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TablesList", + "TabularDataSetsMetadata", + "TriggerFieldData", + "TriggerFieldDataList", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class DynamicsaxClient(ConnectorClientBase): + """Typed client for dynamicsax connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a DynamicsaxClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "dynamicsax" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def execute_procedure( + self, + input: ExecuteProcedureInput | Mapping[str, Any], + dataset: str, + procedure: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Execute action + + Execute action + + Swagger operation ID: `ExecuteProcedure`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: The Dynamics 365 for Fin & Ops instance. + procedure: Name of action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/procedures" + f"/{quote(quote(str(procedure), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_items( + self, + dataset: str, + table: str, + *, + apply: Optional[str] = None, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + select: Optional[str] = None, + cross_company: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Lists items present in table + + Lists items present in table + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItems`. + + Args: + dataset: The Dynamics 365 for Fin & Ops instance. + table: Entity name. + apply: A sequence of OData aggregation transformations. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + cross_company: Query across companies (default = no). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + query_params = [] + if apply is not None: + value = str(apply) + if isinstance(apply, bool): + value = value.lower() + query_params.append(f"$apply={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if cross_company is not None: + value = str(cross_company) + if isinstance(cross_company, bool): + value = value.lower() + query_params.append(f"cross-company={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def post_item( + self, + input: PostItemInput | Mapping[str, Any], + dataset: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create record + + Create a new record in an entity + + Swagger operation ID: `PostItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: The Dynamics 365 for Fin & Ops instance. + table: Entity name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_item( + self, + dataset: str, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a record + + Retrieves a single record + + Swagger operation ID: `GetItem`. + + Args: + dataset: The Dynamics 365 for Fin & Ops instance. + table: Entity name. + id: Unique identifier of the object to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_item( + self, + dataset: str, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete record + + Deletes a single record in an entity + + Swagger operation ID: `DeleteItem`. + + Args: + dataset: The Dynamics 365 for Fin & Ops instance. + table: Entity name. + id: Unique identifier of the object to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def patch_item( + self, + input: PatchItemInput | Mapping[str, Any], + dataset: str, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a record + + Updates a single record in an entity + + Swagger operation ID: `PatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: The Dynamics 365 for Fin & Ops instance. + table: Entity name. + id: Unique identifier of the object to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tables( + self, + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get list of entities + + Retrieves a list of entities + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTables`. + + Args: + dataset: The Dynamics 365 for Fin & Ops instance. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/{quote(quote(str(dataset), safe=''), safe='')}/tables" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_data_sets( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get instances + + Retrieves a list of accessable Dynamics 365 for Fin & Ops instances + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetDataSets`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/datasets" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_business_event_categories( + self, + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Gets business events categories + + Gets business events categories. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetBusinessEventCategories`. + + Args: + dataset: Data set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/businesseventcategories" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_business_events( + self, + dataset: str, + businesseventcategory: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Gets business events + + Gets business events. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetBusinessEvents`. + + Args: + dataset: Data set. + businesseventcategory: Business event category. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/businesseventcategories" + f"/{quote(quote(str(businesseventcategory), safe=''), safe='')}" + f"/businessevents" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_legal_entities( + self, + dataset: str, + businesseventcategory: str, + businessevent: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Gets legal entities + + Gets legal entities. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetLegalEntities`. + + Args: + dataset: Data set. + businesseventcategory: Business event category. + businessevent: Business event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/legalentities" + ) + query_params = [] + value = str(businesseventcategory) + if isinstance(businesseventcategory, bool): + value = value.lower() + query_params.append(f"businesseventcategory={quote(value, safe='')}") + value = str(businessevent) + if isinstance(businessevent, bool): + value = value.lower() + query_params.append(f"businessevent={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_procedures( + self, + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get actions + + Get actions + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetProcedures`. + + Args: + dataset: The Dynamics 365 for Fin & Ops instance. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/procedures" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_procedure( + self, + dataset: str, + procedure: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get actions metadata + + Get actions metadata. + + Swagger operation ID: `GetProcedure`. + + Args: + dataset: The Dynamics 365 for Fin & Ops instance. + procedure: Name of action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/$metadata.json" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/procedures" + f"/{quote(quote(str(procedure), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_table( + self, + dataset: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get entity metadata + + Retrieves metadata for an entity + + Swagger operation ID: `GetTable`. + + Args: + dataset: The Dynamics 365 for Fin & Ops instance. + table: Entity name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/$metadata.json" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/elfsquaddata.py b/src/azure/connectors/aio/elfsquaddata.py new file mode 100644 index 0000000..85df164 --- /dev/null +++ b/src/azure/connectors/aio/elfsquaddata.py @@ -0,0 +1,862 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# ElfsquaddataClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.elfsquaddata import ( + CreateTriggerInput, + GetEntitiesResponse, + GetEntityByIdResponse, + InvokeFunctionInput, + InvokeFunctionResponse, + PostEntityByIdInput, + PostEntityByIdResponse, + PutEntityByIdInput, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "ElfsquaddataClient", + "CreateTriggerInput", + "GetEntitiesResponse", + "GetEntityByIdResponse", + "InvokeFunctionInput", + "InvokeFunctionResponse", + "PostEntityByIdInput", + "PostEntityByIdResponse", + "PutEntityByIdInput", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class ElfsquaddataClient(ConnectorClientBase): + """Typed client for elfsquaddata connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a ElfsquaddataClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "elfsquaddata" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_entities( + self, + entity_name: str, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + orderby: Optional[str] = None, + filter: Optional[str] = None, + select: Optional[str] = None, + expand: Optional[str] = None, + count: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get entities + + Get entities + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `get_entities`. + + Args: + entity_name: Entity name. + top: Top. + skip: Skip. + orderby: Order by. + filter: Filter items. + select: Select properties. + expand: Expand. + count: Count. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/data/1/{quote(str(entity_name), safe='')}" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if expand is not None: + value = str(expand) + if isinstance(expand, bool): + value = value.lower() + query_params.append(f"$expand={quote(value, safe='')}") + if count is not None: + value = str(count) + if isinstance(count, bool): + value = value.lower() + query_params.append(f"$count={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def post_entity_by_id( + self, + input: PostEntityByIdInput | Mapping[str, Any], + entity_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create entity + + Create entity + + Swagger operation ID: `post_entity_by_id`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entity_name: Entity name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/data/1/{quote(str(entity_name), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_entity_by_id( + self, + entity_name: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get entity by id + + Get entity by id + + Swagger operation ID: `get_entity_by_id`. + + Args: + entity_name: Entity name. + id: Identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/data" + f"/1" + f"/{quote(str(entity_name), safe='')}({quote(str(id), safe='')})" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_entity_by_id( + self, + entity_name: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete entity + + Delete entity + + Swagger operation ID: `delete_entity_by_id`. + + Args: + entity_name: Entity name. + id: Identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/data" + f"/1" + f"/{quote(str(entity_name), safe='')}({quote(str(id), safe='')})" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def put_entity_by_id( + self, + input: PutEntityByIdInput | Mapping[str, Any], + entity_name: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update entity + + Update entity + + Swagger operation ID: `put_entity_by_id`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entity_name: Entity name. + id: Identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/data" + f"/1" + f"/{quote(str(entity_name), safe='')}({quote(str(id), safe='')})" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + async def invoke_function( + self, + input: InvokeFunctionInput | Mapping[str, Any], + function_path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Invoke function + + Invoke function + + Swagger operation ID: `invoke_function`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + function_path: Function path. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(str(function_path), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_triggers( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get triggers + + Swagger operation ID: `get_triggers`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/data/1/$triggers" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_schemas( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get schemas + + Swagger operation ID: `get_schemas`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/data/1" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_schema( + self, + entity_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get schema + + Swagger operation ID: `get_schema`. + + Args: + entity_name: entity_name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/data/1/{quote(str(entity_name), safe='')}/$schema" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_functions( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get function + + Swagger operation ID: `get_functions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/data/1/$functions" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_function_definition( + self, + function_path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get function definition + + Swagger operation ID: `get_function_definition`. + + Args: + function_path: function_path. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/data/1/$functions/$schema/{quote(str(function_path), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_trigger_schema( + self, + trigger_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get trigger schema + + Swagger operation ID: `get_trigger_schema`. + + Args: + trigger_name: trigger_name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/data/1/$triggers/{quote(str(trigger_name), safe='')}/$schema" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) diff --git a/src/azure/connectors/aio/etsy.py b/src/azure/connectors/aio/etsy.py new file mode 100644 index 0000000..72d5a31 --- /dev/null +++ b/src/azure/connectors/aio/etsy.py @@ -0,0 +1,5108 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# EtsyClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping +from urllib.parse import quote +import json + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, +) + +from azure.connectors.etsy import ( + ApplicationListingsInventoryRequest, + ApplicationShopsListingsVariationImagesRequest, + Channel, + DestinationRegion, + DestinationRegion1, + ErrorSchema, + Include, + Includes, + Includes1, + ItemDimensionsUnit, + ItemDimensionsUnit2, + ItemWeightUnit, + ItemWeightUnit2, + ListingCreateInput, + ListingCreateTranslationInput, + ListingImage, + ListingImages, + ListingInventory, + ListingInventoryProduct, + ListingInventoryProductOffering, + ListingInventoryWithAssociations, + ListingPropertyValue, + ListingPropertyValues, + ListingTranslation, + ListingUpdateInput, + ListingUpdateInventoryInput, + ListingUpdatePropertyInput, + ListingUpdateTranslationInput, + ListingUpdateVariationInput, + ListingUploadImageInput, + ListingUploadInput, + ListingVariationImage, + ListingVariationImages, + Money, + Occasion, + Offering, + Payment, + PaymentAccountLedgerEntries, + PaymentAccountLedgerEntry, + PaymentAdjustment, + Payments, + Pong, + ProcessingTimeUnit, + Product, + ProfileType, + PropertyValue, + ReceiptCreateShipmentInput, + Recipient, + SellerTaxonomyNode, + SellerTaxonomyNodes, + ShippingCarrier, + ShippingCarrierMailClass, + ShippingCarriers, + ShippingCreateDestinationInput, + ShippingCreateProfileInput, + ShippingCreateUpgradeInput, + ShippingUpdateProfileDestinationInput, + ShippingUpdateProfileInput, + ShippingUpdateProfileUpgradeInput, + Shop, + ShopCreateSectionInput, + ShopListing, + ShopListingFile, + ShopListingFiles, + ShopListingWithAssociations, + ShopListings, + ShopListingsWithAssociations, + ShopProductionPartner, + ShopProductionPartners, + ShopReceipt, + ShopReceiptShipment, + ShopReceiptTransaction, + ShopReceiptTransactions, + ShopReceipts, + ShopSection, + ShopSections, + ShopShippingProfile, + ShopShippingProfileDestination, + ShopShippingProfileDestinations, + ShopShippingProfileUpgrade, + ShopShippingProfileUpgrades, + ShopShippingProfiles, + ShopUpdateInput, + Shops, + SortOn, + SortOrder, + State, + State2, + TaxonomyNodeProperties, + TaxonomyNodeProperty, + TaxonomyPropertyScale, + TaxonomyPropertyValue, + TransactionReview, + TransactionReviews, + Type, + Type1, + User, + UserAddress, + UserAddresses, + VariationImage, + WhenMade, + WhenMade2, + WhoMade, + WhoMade2, +) + +__all__ = [ + "EtsyClient", + "ApplicationListingsInventoryRequest", + "ApplicationShopsListingsVariationImagesRequest", + "Channel", + "DestinationRegion", + "DestinationRegion1", + "ErrorSchema", + "Include", + "Includes", + "Includes1", + "ItemDimensionsUnit", + "ItemDimensionsUnit2", + "ItemWeightUnit", + "ItemWeightUnit2", + "ListingCreateInput", + "ListingCreateTranslationInput", + "ListingImage", + "ListingImages", + "ListingInventory", + "ListingInventoryProduct", + "ListingInventoryProductOffering", + "ListingInventoryWithAssociations", + "ListingPropertyValue", + "ListingPropertyValues", + "ListingTranslation", + "ListingUpdateInput", + "ListingUpdateInventoryInput", + "ListingUpdatePropertyInput", + "ListingUpdateTranslationInput", + "ListingUpdateVariationInput", + "ListingUploadImageInput", + "ListingUploadInput", + "ListingVariationImage", + "ListingVariationImages", + "Money", + "Occasion", + "Offering", + "Payment", + "PaymentAccountLedgerEntries", + "PaymentAccountLedgerEntry", + "PaymentAdjustment", + "Payments", + "Pong", + "ProcessingTimeUnit", + "Product", + "ProfileType", + "PropertyValue", + "ReceiptCreateShipmentInput", + "Recipient", + "SellerTaxonomyNode", + "SellerTaxonomyNodes", + "ShippingCarrier", + "ShippingCarrierMailClass", + "ShippingCarriers", + "ShippingCreateDestinationInput", + "ShippingCreateProfileInput", + "ShippingCreateUpgradeInput", + "ShippingUpdateProfileDestinationInput", + "ShippingUpdateProfileInput", + "ShippingUpdateProfileUpgradeInput", + "Shop", + "ShopCreateSectionInput", + "ShopListing", + "ShopListingFile", + "ShopListingFiles", + "ShopListingWithAssociations", + "ShopListings", + "ShopListingsWithAssociations", + "ShopProductionPartner", + "ShopProductionPartners", + "ShopReceipt", + "ShopReceiptShipment", + "ShopReceiptTransaction", + "ShopReceiptTransactions", + "ShopReceipts", + "ShopSection", + "ShopSections", + "ShopShippingProfile", + "ShopShippingProfileDestination", + "ShopShippingProfileDestinations", + "ShopShippingProfileUpgrade", + "ShopShippingProfileUpgrades", + "ShopShippingProfiles", + "ShopUpdateInput", + "Shops", + "SortOn", + "SortOrder", + "State", + "State2", + "TaxonomyNodeProperties", + "TaxonomyNodeProperty", + "TaxonomyPropertyScale", + "TaxonomyPropertyValue", + "TransactionReview", + "TransactionReviews", + "Type", + "Type1", + "User", + "UserAddress", + "UserAddresses", + "VariationImage", + "WhenMade", + "WhenMade2", + "WhoMade", + "WhoMade2", +] + + +# Type Definitions + +# Client Class + +class EtsyClient(ConnectorClientBase): + """Typed client for etsy connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a EtsyClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "etsy" + + async def ping( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Ping + + Check to confirm connectivity to the Etsy API with an application. + + Swagger operation ID: `Ping`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/openapi-ping" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def payment_ledger_entries( + self, + shop_id: int, + min_created: int, + max_created: int, + *, + limit: Optional[int] = None, + offset: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a shop payment account ledger's entries + + Retrieve the entries of a shop's payment account ledger. + + Swagger operation ID: `PaymentLedgerEntries`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + min_created: The earliest unix timestamp for when a record was + created. + max_created: The latest unix timestamp for when a record was + created. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/payment-account" + f"/ledger-entries" + ) + query_params = [] + value = str(min_created) + if isinstance(min_created, bool): + value = value.lower() + query_params.append(f"min_created={quote(value, safe='')}") + value = str(max_created) + if isinstance(max_created, bool): + value = value.lower() + query_params.append(f"max_created={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def payment_get_entry_id( + self, + shop_id: int, + ledger_entry_ids: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a payment from a payment account ledger entry ID + + Get a Payment from a Payment Account Ledger Entry ID, if applicable. + + Swagger operation ID: `PaymentGetEntryID`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + ledger_entry_ids: Array of integers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/payment-account" + f"/ledger-entries" + f"/payments" + ) + query_params = [] + value = str(ledger_entry_ids) + if isinstance(ledger_entry_ids, bool): + value = value.lower() + query_params.append(f"ledger_entry_ids={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def payment_get_receipt( + self, + shop_id: int, + receipt_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a payment from a specific receipt + + Retrieves a payment from a specific receipt, identified by receipt ID, + from a specific shop, identified by shop ID. + + Swagger operation ID: `PaymentGetReceipt`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + receipt_id: The numeric ID for the receipt associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/receipts" + f"/{quote(str(receipt_id), safe='')}" + f"/payments" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def payments_get( + self, + shop_id: int, + payment_ids: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a list of payments + + Retrieves a list of payments from a shop identified by shop ID. You can + also filter results using a list of payment IDs. + + Swagger operation ID: `PaymentsGet`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + payment_ids: A comma-separated array of Payment IDs numbers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops/{quote(str(shop_id), safe='')}/payments" + ) + query_params = [] + value = str(payment_ids) + if isinstance(payment_ids, bool): + value = value.lower() + query_params.append(f"payment-ids={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def receipt_get( + self, + shop_id: int, + receipt_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a receipt + + Retrieves a receipt, identified by a receipt ID, from an Etsy shop. + + Swagger operation ID: `ReceiptGet`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + receipt_id: The numeric ID for the receipt associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/receipts" + f"/{quote(str(receipt_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def receipts_get( + self, + shop_id: int, + *, + min_created: Optional[int] = None, + max_created: Optional[int] = None, + min_last_modified: Optional[int] = None, + max_last_modified: Optional[int] = None, + limit: Optional[int] = None, + offset: Optional[int] = None, + was_paid: Optional[bool] = None, + was_shipped: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get receipts + + Requests the shop receipts from a specific shop, unfiltered or filtered + by receipt ID range or offset, date, paid, and/or shipped purchases. + + Swagger operation ID: `ReceiptsGet`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + min_created: The earliest unix timestamp for when a record was + created. + max_created: The latest unix timestamp for when a record was + created. + min_last_modified: The earliest unix timestamp for when a record + last changed. + max_last_modified: The latest unix timestamp for when a record last + changed. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + was_paid: When true, the seller received payment for the product(s) + in this receipt. + was_shipped: When true, the seller shipped the product(s) in this + receipt. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops/{quote(str(shop_id), safe='')}/receipts" + ) + query_params = [] + if min_created is not None: + value = str(min_created) + if isinstance(min_created, bool): + value = value.lower() + query_params.append(f"min_created={quote(value, safe='')}") + if max_created is not None: + value = str(max_created) + if isinstance(max_created, bool): + value = value.lower() + query_params.append(f"max_created={quote(value, safe='')}") + if min_last_modified is not None: + value = str(min_last_modified) + if isinstance(min_last_modified, bool): + value = value.lower() + query_params.append(f"min_last_modified={quote(value, safe='')}") + if max_last_modified is not None: + value = str(max_last_modified) + if isinstance(max_last_modified, bool): + value = value.lower() + query_params.append(f"max_last_modified={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if was_paid is not None: + value = str(was_paid) + if isinstance(was_paid, bool): + value = value.lower() + query_params.append(f"was_paid={quote(value, safe='')}") + if was_shipped is not None: + value = str(was_shipped) + if isinstance(was_shipped, bool): + value = value.lower() + query_params.append(f"was_shipped={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def receipt_create_shipment( + self, + input: ReceiptCreateShipmentInput | Mapping[str, Any], + shop_id: int, + receipt_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a Shipment Receipt + + Submits tracking information for a shop receipt, which creates a shop + receipt Shipment entry for the given receipt ID. Each time you + successfully submit tracking info, Etsy sends a notification email to + the buyer User. When send BCC is true, Etsy sends shipping + notifications to the seller as well. When tracking code and carrier + name aren't sent, the receipt is marked as shipped only. + + Swagger operation ID: `ReceiptCreateShipment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + receipt_id: The receipt to submit tracking for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/receipts" + f"/{quote(str(receipt_id), safe='')}" + f"/tracking" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def transactions_listing( + self, + shop_id: int, + listing_id: int, + *, + limit: Optional[int] = None, + offset: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Retrieve a listing's transactions + + Retrieves the list of transactions associated with a listing. + + Swagger operation ID: `TransactionsListing`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/transactions" + ) + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def transaction_receipt( + self, + shop_id: int, + receipt_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a receipt's transaction + + Retrieves the list of transactions associated with a specific receipt. + + Swagger operation ID: `TransactionReceipt`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + receipt_id: The numeric ID for the receipt associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/receipts" + f"/{quote(str(receipt_id), safe='')}" + f"/transactions" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def transaction_get( + self, + shop_id: int, + transaction_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a transaction + + Retrieves a transaction by transaction ID. + + Swagger operation ID: `TransactionGet`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + transaction_id: The unique numeric ID for a transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/transactions" + f"/{quote(str(transaction_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def transaction_get_shop( + self, + shop_id: int, + *, + limit: Optional[int] = None, + offset: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a shop's transaction + + Retrieves the list of transactions associated with a shop. + + Swagger operation ID: `TransactionGetShop`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops/{quote(str(shop_id), safe='')}/transactions" + ) + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def reviews_get( + self, + shop_id: int, + *, + limit: Optional[int] = None, + offset: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get reviews + + Retrieves the reviews from a shop given its ID. + + Swagger operation ID: `ReviewsGet`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops/{quote(str(shop_id), safe='')}/reviews" + ) + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shipping_carriers( + self, + origin_country_iso: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get shipping carriers + + Retrieves a list of available shipping carriers and the mail classes + associated with them for a given country. + + Swagger operation ID: `ShippingCarriers`. + + Args: + origin_country_iso: The ISO code of the country from which the + listing ships. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/shipping-carriers" + query_params = [] + value = str(origin_country_iso) + if isinstance(origin_country_iso, bool): + value = value.lower() + query_params.append(f"origin_country_iso={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shipping_profiles( + self, + shop_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get shipping profiles + + Retrieves a list of shipping profiles available in the specific Etsy + shop identified by its shop ID. + + Swagger operation ID: `ShippingProfiles`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops/{quote(str(shop_id), safe='')}/shipping-profiles" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shipping_create_profile( + self, + input: ShippingCreateProfileInput | Mapping[str, Any], + shop_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a shipping profile + + Creates a new shipping profile. You can pass a country ISO code or a + region when creating a shipping profile, but not both. Only one is + required. You must pass either a shipping carrier ID and mail class, or + both min and max delivery days. + + Swagger operation ID: `ShippingCreateProfile`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops/{quote(str(shop_id), safe='')}/shipping-profiles" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shipping_get_profile( + self, + shop_id: int, + shipping_profile_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get a shipping profile + + Retrieves a shipping profile referenced by shipping profile ID. + + Swagger operation ID: `ShippingGetProfile`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/shipping-profiles" + f"/{quote(str(shipping_profile_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + async def shipping_delete_profile( + self, + shop_id: int, + shipping_profile_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete a shipping profile + + Deletes a shipping profile by given ID. + + Swagger operation ID: `ShippingDeleteProfile`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/shipping-profiles" + f"/{quote(str(shipping_profile_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shipping_update_profile( + self, + input: ShippingUpdateProfileInput | Mapping[str, Any], + shop_id: int, + shipping_profile_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a shipping profile + + Changes the settings in a shipping profile. + + Swagger operation ID: `ShippingUpdateProfile`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/shipping-profiles" + f"/{quote(str(shipping_profile_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shipping_get_destinations( + self, + shop_id: int, + shipping_profile_id: int, + *, + limit: Optional[int] = None, + offset: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get profile destinations by shipping profile + + Retrieves a list of shipping destination objects associated with a + shipping profile. + + Swagger operation ID: `ShippingGetDestinations`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/shipping-profiles" + f"/{quote(str(shipping_profile_id), safe='')}" + f"/destinations" + ) + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shipping_create_destination( + self, + input: ShippingCreateDestinationInput | Mapping[str, Any], + shop_id: int, + shipping_profile_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a shipping profile destination + + Creates a new shipping destination, which sets the shipping cost, + carrier, and class for a destination in a shipping profile. This + assigns costs using the currency of the associated shop. Set the + destination using either destination country ISO or destination region; + destination country ISO and destination region are mutually exclusive - + set one or the other. Setting both triggers error 400. If the request + sets neither destination country ISO nor destination region, the + default destination is everywhere. You must also either assign both a + shipping carrier ID and mail class or both min delivery days and max + delivery days. + + Swagger operation ID: `ShippingCreateDestination`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/shipping-profiles" + f"/{quote(str(shipping_profile_id), safe='')}" + f"/destinations" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shipping_delete_profile_destination( + self, + shop_id: int, + shipping_profile_id: int, + shipping_profile_destination_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a shipping profile destination + + Deletes a shipping destination and removes the destination option from + every listing that uses the associated shipping profile. A shipping + profile requires at least one shipping destination, so this endpoint + cannot delete the final shipping destination for any shipping profile. + To delete the final shipping destination from a shipping profile, you + must delete the entire shipping profile. + + Swagger operation ID: `ShippingDeleteProfileDestination`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + shipping_profile_destination_id: The numeric ID of the shipping + profile destination in the shipping profile associated with the + listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/shipping-profiles" + f"/{quote(str(shipping_profile_id), safe='')}" + f"/destinations" + f"/{quote(str(shipping_profile_destination_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def shipping_update_profile_destination( + self, + input: ShippingUpdateProfileDestinationInput | Mapping[str, Any], + shop_id: int, + shipping_profile_id: str, + shipping_profile_destination_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a shipping profile destination + + Updates an existing shipping destination, which can set or reassign the + shipping cost, carrier, and class for a destination. + + Swagger operation ID: `ShippingUpdateProfileDestination`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + shipping_profile_destination_id: The numeric ID of the shipping + profile destinationassociated with the listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/shipping-profiles" + f"/{quote(str(shipping_profile_id), safe='')}" + f"/destinations" + f"/{quote(str(shipping_profile_destination_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shipping_get_profile_upgrades( + self, + shop_id: int, + shipping_profile_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get shipping profile upgrades + + Retrieves the list of shipping profile upgrades assigned to a specific + shipping profile. + + Swagger operation ID: `ShippingGetProfileUpgrades`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/shipping-profiles" + f"/{quote(str(shipping_profile_id), safe='')}" + f"/upgrades" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shipping_create_upgrade( + self, + input: ShippingCreateUpgradeInput | Mapping[str, Any], + shop_id: int, + shipping_profile_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a shipping profile upgrade + + Creates a new shipping profile upgrade, which can establish a price for + a shipping option, such as an alternate carrier or faster delivery. + + Swagger operation ID: `ShippingCreateUpgrade`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/shipping-profiles" + f"/{quote(str(shipping_profile_id), safe='')}" + f"/upgrades" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shipping_delete_profile_upgrade( + self, + shop_id: int, + shipping_profile_id: int, + upgrade_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a shipping profile upgrade + + Deletes a shipping profile upgrade and removes the upgrade option from + every listing that uses the associated shipping profile. + + Swagger operation ID: `ShippingDeleteProfileUpgrade`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile. + upgrade_id: The numeric ID that is associated with a shipping + upgrade. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/shipping-profiles" + f"/{quote(str(shipping_profile_id), safe='')}" + f"/upgrades" + f"/{quote(str(upgrade_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def shipping_update_profile_upgrade( + self, + input: ShippingUpdateProfileUpgradeInput | Mapping[str, Any], + shop_id: int, + shipping_profile_id: int, + upgrade_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a shipping profile upgrade + + Updates a shipping profile upgrade and updates any listings that use + the shipping profile. + + Swagger operation ID: `ShippingUpdateProfileUpgrade`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + upgrade_id: The numeric ID that is associated with a shipping + upgrade. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/shipping-profiles" + f"/{quote(str(shipping_profile_id), safe='')}" + f"/upgrades" + f"/{quote(str(upgrade_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shop_update( + self, + input: ShopUpdateInput | Mapping[str, Any], + shop_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a shop + + Update a shop. Assumes that all string parameters are provided in the + shop's primary language. + + Swagger operation ID: `ShopUpdate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops/{quote(str(shop_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shop_get_by_owner_id( + self, + user_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get shop by owner ID + + Retrieves the shop identified by the shop owner's user ID. + + Swagger operation ID: `ShopGetByOwnerID`. + + Args: + user_id: The numeric user ID of the user who owns this shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/users/{quote(str(user_id), safe='')}/shops" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shop_search( + self, + shop_name: str, + *, + limit: Optional[int] = None, + offset: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Search shops + + Returns a list of shops with the matching name. + + Swagger operation ID: `ShopSearch`. + + Args: + shop_name: The shop's name string. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/shops" + query_params = [] + value = str(shop_name) + if isinstance(shop_name, bool): + value = value.lower() + query_params.append(f"shop_name={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shop_get_sections( + self, + shop_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get shop sections + + Retrieves the list of shop sections in a specific shop identified by + shop ID. + + Swagger operation ID: `ShopGetSections`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops/{quote(str(shop_id), safe='')}/sections" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shop_create_section( + self, + input: ShopCreateSectionInput | Mapping[str, Any], + shop_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a shop section + + Creates a new section in a specific shop. + + Swagger operation ID: `ShopCreateSection`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops/{quote(str(shop_id), safe='')}/sections" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def user_get( + self, + user_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get user + + Returns user profile for the user identified by a user ID. + + Swagger operation ID: `UserGet`. + + Args: + user_id: The unique positive non-zero numeric ID for an user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/users/{quote(str(user_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shop_get_section( + self, + shop_id: int, + shop_section_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get shop section + + Retrieves a shop section, referenced by section ID and shop ID. + + Swagger operation ID: `ShopGetSection`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shop_section_id: The numeric ID of a section in a specific Etsy + shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/sections" + f"/{quote(str(shop_section_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def user_get_address( + self, + user_address_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get user's address + + Retrieves the user's address. Development for this endpoint is in + progress. It will only return a 501 response. + + Swagger operation ID: `UserGetAddress`. + + Args: + user_address_id: The numeric ID of the user's address. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/user/addresses/{quote(str(user_address_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def user_get_addresses( + self, + *, + limit: Optional[int] = None, + offset: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get user addresses + + Retrieve a list of user addresses. + + Swagger operation ID: `UserGetAddresses`. + + Args: + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/user/addresses" + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_taxonomy_nodes( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get seller taxonomy nodes + + Retrieves the full hierarchy tree of seller taxonomy nodes. + + Swagger operation ID: `ListingGetTaxonomyNodes`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/seller-taxonomy/nodes" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_properties_by_taxonomy( + self, + taxonomy_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get product properties by taxonomy ID + + Retrieves a list of product properties, with applicable scales and + values, supported for a specific seller taxonomy ID. + + Swagger operation ID: `ListingGetPropertiesByTaxonomy`. + + Args: + taxonomy_id: The unique numeric ID of an Etsy taxonomy node, which + is a metadata category for listings organized into the seller + taxonomy hierarchy tree. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/seller-taxonomy" + f"/nodes" + f"/{quote(str(taxonomy_id), safe='')}" + f"/properties" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_shop( + self, + shop_id: int, + *, + state: Optional[str] = None, + limit: Optional[int] = None, + offset: Optional[int] = None, + sort_on: Optional[str] = None, + sort_order: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get listings by shop + + Returns listings that belong to a Shop. Listings can be filtered using + the state parameter. + + Swagger operation ID: `ListingGetShop`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + state: An enumerated string from any of: active or inactive. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + sort_on: The value to sort a search result of listings on. + sort_order: The ascending(up) or descending(down) order to sort + listings by. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops/{quote(str(shop_id), safe='')}/listings" + ) + query_params = [] + if state is not None: + value = str(state) + if isinstance(state, bool): + value = value.lower() + query_params.append(f"State={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if sort_on is not None: + value = str(sort_on) + if isinstance(sort_on, bool): + value = value.lower() + query_params.append(f"Sort On={quote(value, safe='')}") + if sort_order is not None: + value = str(sort_order) + if isinstance(sort_order, bool): + value = value.lower() + query_params.append(f"Sort Order={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_create( + self, + input: ListingCreateInput | Mapping[str, Any], + shop_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a draft listing + + Creates a physical draft listing product in a shop on the Etsy channel. + + Swagger operation ID: `ListingCreate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops/{quote(str(shop_id), safe='')}/listings" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get( + self, + listing_id: int, + *, + includes: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get a listing + + Retrieves a listing record by listing ID. + + Swagger operation ID: `ListingGet`. + + Args: + listing_id: The numeric ID for the listing associated to this + transaction. + includes: An enumerated string that attaches a valid association. + Acceptable inputs are 'shop', 'images' and 'user'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/listings/{quote(str(listing_id), safe='')}" + ) + query_params = [] + if includes is not None: + value = str(includes) + if isinstance(includes, bool): + value = value.lower() + query_params.append(f"includes={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + async def listing_delete( + self, + listing_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a listing + + This action deletes a shop listing. A listing can be deleted only if + the state is one of the following: SOLD_OUT, DRAFT, EXPIRED, INACTIVE, + ACTIVE and is_available or ACTIVE and has seller flags: SUPRESSED + (frozen), VACATION, CUSTOM_SHOPS (pattern), SELL_ON_FACEBOOK + + Swagger operation ID: `ListingDelete`. + + Args: + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/listings/{quote(str(listing_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def listing_get_active( + self, + *, + limit: Optional[int] = None, + offset: Optional[int] = None, + keywords: Optional[str] = None, + sort_on: Optional[str] = None, + sort_order: Optional[str] = None, + min_price: Optional[float] = None, + max_price: Optional[float] = None, + taxonomy_id: Optional[int] = None, + shop_location: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get active listings + + A list of all active listings on Etsy paginated by their creation date. + Without sort order listings will be returned newest-first by default. + + Swagger operation ID: `ListingGetActive`. + + Args: + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + keywords: Search term or phrase that must appear in all results. + sort_on: The value to sort a search result of listings on. NOTE: + sort on only works when combined with one of the search options + (keywords, region, etc.). + sort_order: The ascending(up) or descending(down) order to sort + listings by. NOTE: sort_order only works when combined with one + of the search options (keywords, region, etc.). + min_price: The minimum price of listings to be returned by a search + result. + max_price: The maximum price of listings to be returned by a search + result. + taxonomy_id: The numeric taxonomy ID of the listing. The seller + manages listing taxonomy IDs for their shop. + shop_location: Filters by shop location. If location cannot be + parsed, Etsy responds with an error. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/listings/active" + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if keywords is not None: + value = str(keywords) + if isinstance(keywords, bool): + value = value.lower() + query_params.append(f"keywords={quote(value, safe='')}") + if sort_on is not None: + value = str(sort_on) + if isinstance(sort_on, bool): + value = value.lower() + query_params.append(f"sort_on={quote(value, safe='')}") + if sort_order is not None: + value = str(sort_order) + if isinstance(sort_order, bool): + value = value.lower() + query_params.append(f"sort_order={quote(value, safe='')}") + if min_price is not None: + value = str(min_price) + if isinstance(min_price, bool): + value = value.lower() + query_params.append(f"min_price={quote(value, safe='')}") + if max_price is not None: + value = str(max_price) + if isinstance(max_price, bool): + value = value.lower() + query_params.append(f"max_price={quote(value, safe='')}") + if taxonomy_id is not None: + value = str(taxonomy_id) + if isinstance(taxonomy_id, bool): + value = value.lower() + query_params.append(f"taxonomy_id={quote(value, safe='')}") + if shop_location is not None: + value = str(shop_location) + if isinstance(shop_location, bool): + value = value.lower() + query_params.append(f"shop_location={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_active_by_shop( + self, + shop_id: int, + *, + limit: Optional[int] = None, + offset: Optional[int] = None, + keywords: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get active listings by shop + + Retrieves a list of all active listings on Etsy in a specific shop, + paginated by listing creation date. + + Swagger operation ID: `ListingGetActiveByShop`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + keywords: Search term or phrase that must appear in all results. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops/{quote(str(shop_id), safe='')}/listings/active" + ) + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if keywords is not None: + value = str(keywords) + if isinstance(keywords, bool): + value = value.lower() + query_params.append(f"keywords={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_by_id( + self, + listing_ids: str, + *, + includes: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get listings by ID + + Allows to query multiple listing IDs at once. Limit 100 IDs maximum per + query. + + Swagger operation ID: `ListingGetByID`. + + Args: + listing_ids: The array of numeric IDs for the listings in a + specific Etsy shop. + includes: An enumerated string that attaches a valid association. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/listings/batch" + query_params = [] + value = str(listing_ids) + if isinstance(listing_ids, bool): + value = value.lower() + query_params.append(f"listing_ids={quote(value, safe='')}") + if includes is not None: + value = str(includes) + if isinstance(includes, bool): + value = value.lower() + query_params.append(f"includes={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_featured( + self, + shop_id: int, + *, + limit: Optional[int] = None, + offset: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get featured listings by shop + + Retrieves listings associated to a shop that are featured. + + Swagger operation ID: `ListingGetFeatured`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops/{quote(str(shop_id), safe='')}/listings/featured" + ) + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_delete_property( + self, + shop_id: int, + listing_id: int, + property_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a listing property + + Deletes a property from a listing. + + Swagger operation ID: `ListingDeleteProperty`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + property_id: The unique ID of an Etsy listing property. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/properties" + f"/{quote(str(property_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def listing_update_property( + self, + input: ListingUpdatePropertyInput | Mapping[str, Any], + shop_id: int, + listing_id: int, + property_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a listing property + + Updates or populates the properties list defining product offerings for + a listing. Each offering requires both a value and a value ID that are + valid for a scale ID assigned to the listing or that you assign to the + listing with this request. + + Swagger operation ID: `ListingUpdateProperty`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + property_id: The unique ID of an Etsy listing property. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/properties" + f"/{quote(str(property_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_property( + self, + listing_id: int, + property_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a listing's property (Beta) + + Retrieves a listing's property. Development for this endpoint is in + progress. It will only return a 501 response. + + Swagger operation ID: `ListingGetProperty`. + + Args: + listing_id: The numeric ID for the listing associated to this + transaction. + property_id: The unique ID of an Etsy listing property. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/properties" + f"/{quote(str(property_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_properties( + self, + shop_id: int, + listing_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a listing's properties + + Returns a list of a listing's properties. + + Swagger operation ID: `ListingGetProperties`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/properties" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_update( + self, + input: ListingUpdateInput | Mapping[str, Any], + shop_id: int, + listing_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a listing + + Updates a listing, identified by a listing ID, for a specific shop + identified by a shop ID. + + Swagger operation ID: `ListingUpdate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_by_receipt( + self, + shop_id: int, + receipt_id: int, + *, + limit: Optional[int] = None, + offset: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get listings by shop receipt + + Gets all listings associated with a receipt. + + Swagger operation ID: `ListingGetByReceipt`. + + Args: + shop_id: The numeric ID for the receipt associated to this + transaction. + receipt_id: The unique positive non-zero numeric ID for an Etsy + Shop. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/receipts" + f"/{quote(str(receipt_id), safe='')}" + f"/listings" + ) + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_by_section_id( + self, + shop_id: int, + shop_section_ids: str, + *, + limit: Optional[int] = None, + offset: Optional[int] = None, + sort_on: Optional[str] = None, + sort_order: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get listings by shop section ID + + Retrieves all the listings from the section of a specific shop. + + Swagger operation ID: `ListingGetBySectionID`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shop_section_ids: A array of numeric IDs for all sections in a + specific Etsy shop. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + sort_on: The value to sort a search result of listings on. + sort_order: The ascending(up) or descending(down) order to sort + listings by. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops/{quote(str(shop_id), safe='')}/shop-sections/listings" + ) + query_params = [] + value = str(shop_section_ids) + if isinstance(shop_section_ids, bool): + value = value.lower() + query_params.append(f"shop_section_ids={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if sort_on is not None: + value = str(sort_on) + if isinstance(sort_on, bool): + value = value.lower() + query_params.append(f"sort_on={quote(value, safe='')}") + if sort_order is not None: + value = str(sort_order) + if isinstance(sort_order, bool): + value = value.lower() + query_params.append(f"sort_order={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_file( + self, + shop_id: int, + listing_id: int, + listing_file_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a file from a listing + + Retrieves a single file associated with the given digital listing. + Requesting a file from a physical listing returns an empty result. + + Swagger operation ID: `ListingGetFile`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + listing_file_id: The unique numeric ID of a file associated with a + digital listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/files" + f"/{quote(str(listing_file_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_delete_file( + self, + shop_id: int, + listing_id: int, + listing_file_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a file from listing + + When you delete the final file for a digital listing, the listing + converts into a physical listing. The response to a delete request + returns a list of the remaining file records associated with the given + listing. + + Swagger operation ID: `ListingDeleteFile`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + listing_file_id: The unique numeric ID of a file associated with a + digital listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/files" + f"/{quote(str(listing_file_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def listing_get_files( + self, + shop_id: int, + listing_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get all listing files + + Retrieves all the files associated with the given digital listing. + Requesting files from a physical listing returns an empty result. + + Swagger operation ID: `ListingGetFiles`. + + Args: + shop_id: The numeric ID for the listing associated to this + transaction. + listing_id: The unique positive non-zero numeric ID for an Etsy + Shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/files" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_upload( + self, + input: ListingUploadInput | Mapping[str, Any], + shop_id: int, + listing_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Upload a listing file + + Uploads a new file for a digital listing, or associates an existing + file with a specific listing. You must either provide the listing file + ID of an existing file, or the name and binary file data for a file to + upload. Associating an existing file to a physical listing converts the + physical listing into a digital listing, which removes all shipping + costs and any product and inventory variations. + + Swagger operation ID: `ListingUpload`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/files" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_image( + self, + shop_id: int, + listing_id: int, + listing_image_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a listing image + + Retrieves the references and metadata for a listing image with a + specific image ID. + + Swagger operation ID: `ListingGetImage`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + listing_image_id: The numeric ID of the primary listing image for + this transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/images" + f"/{quote(str(listing_image_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_delete_image( + self, + shop_id: int, + listing_id: int, + listing_image_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a listing image + + Deletes a listing image. A copy of the file remains on our servers, and + so a deleted image may be re-associated with the listing without + re-uploading the original image. + + Swagger operation ID: `ListingDeleteImage`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + listing_image_id: The numeric ID of the primary listing image for + this transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/images" + f"/{quote(str(listing_image_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def listing_get_images( + self, + shop_id: int, + listing_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a listing's images + + Retrieves all listing image resources for a listing with a specific + listing ID. + + Swagger operation ID: `ListingGetImages`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/images" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_upload_image( + self, + input: ListingUploadImageInput | Mapping[str, Any], + shop_id: int, + listing_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Upload a listing image + + Uploads or assigns an image to a listing identified by a shop ID with a + listing ID. To upload a new image, set the image file as the value for + the image parameter. You can assign a previously deleted image to a + listing using the deleted image's image ID in the listing image ID + parameter. When a request contains both image and listing image ID + parameter values, the endpoint uploads the image in the image parameter + only. + + Swagger operation ID: `ListingUploadImage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/images" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_inventory( + self, + listing_id: int, + *, + includes: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a listing's inventory + + Retrieves the inventory record for a listing. Listings you did not edit + using the Etsy.com inventory tools have no inventory records. This + endpoint returns SKU data if you are the owner of the inventory records + being fetched. + + Swagger operation ID: `ListingGetInventory`. + + Args: + listing_id: The numeric ID for the listing associated to this + transaction. + includes: An enumerated string that attaches an valid association. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/listings/{quote(str(listing_id), safe='')}/inventory" + ) + query_params = [] + if includes is not None: + value = str(includes) + if isinstance(includes, bool): + value = value.lower() + query_params.append(f"includes={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_update_inventory( + self, + input: ListingUpdateInventoryInput | Mapping[str, Any], + listing_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a listing's inventory + + Updates the inventory for a listing identified by a listing ID. The + update fails if the supplied values for product SKU, offering quantity, + and/or price are incompatible with values in on property fields. When + setting a price, assign a float equal to amount divided by divisor as + specified in the money resource. + + Swagger operation ID: `ListingUpdateInventory`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/listings/{quote(str(listing_id), safe='')}/inventory" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_offering( + self, + listing_id: int, + product_id: int, + product_offering_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a listing's offering + + Get an offering for a listing. + + Swagger operation ID: `ListingGetOffering`. + + Args: + listing_id: The numeric ID for the listing associated to this + transaction. + product_id: The numeric ID for the product associated to this + transaction. + product_offering_id: The numeric ID for the product offering + associated to this transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/products" + f"/{quote(str(product_id), safe='')}" + f"/offerings" + f"/{quote(str(product_offering_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_product( + self, + listing_id: int, + product_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a listing's product + + Retrieve a listing product by ID. + + Swagger operation ID: `ListingGetProduct`. + + Args: + listing_id: The listing to return a listing product for. + product_id: The numeric ID for a specific product purchased from a + listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/inventory" + f"/products" + f"/{quote(str(product_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_translation( + self, + shop_id: int, + listing_id: int, + language: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a listing's translation + + Returns the translation for a listing in the given language. + + Swagger operation ID: `ListingGetTranslation`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + language: The IETF language tag for the language of this + translation. Ex: de, en, es, fr, it, ja, nl, pl, pt, ru. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/translations" + f"/{quote(str(language), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_create_translation( + self, + input: ListingCreateTranslationInput | Mapping[str, Any], + shop_id: int, + listing_id: int, + language: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a listing translation + + Creates a listing translation by listing ID and language. + + Swagger operation ID: `ListingCreateTranslation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + language: The IETF language tag for the language of this + translation. Ex: de, en, es, fr, it, ja, nl, pl, pt, ru. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/translations" + f"/{quote(str(language), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_update_translation( + self, + input: ListingUpdateTranslationInput | Mapping[str, Any], + shop_id: int, + listing_id: int, + language: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a listing translation + + Updates a listing translation by listing ID and language. + + Swagger operation ID: `ListingUpdateTranslation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + language: The IETF language tag for the language of this + translation. Ex: de, en, es, fr, it, ja, nl, pl, pt, ru. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/translations" + f"/{quote(str(language), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_get_variation( + self, + shop_id: int, + listing_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get listing's variation images + + Gets all variation images on a listing. + + Swagger operation ID: `ListingGetVariation`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/variation-images" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def listing_update_variation( + self, + input: ListingUpdateVariationInput | Mapping[str, Any], + shop_id: int, + listing_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a listing's variation images + + Creates variation images on a listing. + + Swagger operation ID: `ListingUpdateVariation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/shops" + f"/{quote(str(shop_id), safe='')}" + f"/listings" + f"/{quote(str(listing_id), safe='')}" + f"/variation-images" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/eventbrite.py b/src/azure/connectors/aio/eventbrite.py new file mode 100644 index 0000000..18d6cf6 --- /dev/null +++ b/src/azure/connectors/aio/eventbrite.py @@ -0,0 +1,953 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# EventbriteClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.eventbrite import ( + CreateEventResponse, + GetCategoriesResponse, + GetEventsForOrganizationResponse, + GetEventsForOrganizerResponse, + GetMyEventsResponse, + GetMyVenuesResponse, + GetOrdersResponse, + GetOrganizationsResponse, + GetOrganizersResponse, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "EventbriteClient", + "CreateEventResponse", + "GetCategoriesResponse", + "GetEventsForOrganizationResponse", + "GetEventsForOrganizerResponse", + "GetMyEventsResponse", + "GetMyVenuesResponse", + "GetOrdersResponse", + "GetOrganizationsResponse", + "GetOrganizersResponse", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class EventbriteClient(ConnectorClientBase): + """Typed client for eventbrite connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a EventbriteClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "eventbrite" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_event( + self, + organization_id: str, + event_name_html: str, + event_description_html: str, + event_start_utc: str, + event_end_utc: str, + event_start_timezone: str, + event_end_timezone: str, + event_currency: str, + *, + event_organizer_id: Optional[str] = None, + event_venue_id: Optional[str] = None, + event_category_id: Optional[str] = None, + event_password: Optional[str] = None, + event_capacity: Optional[str] = None, + event_shareable: Optional[bool] = None, + event_invite_only: Optional[bool] = None, + event_online_event: Optional[bool] = None, + event_listed: Optional[bool] = None, + event_hide_start_date: Optional[bool] = None, + event_hide_end_date: Optional[bool] = None, + event_show_remaining: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create event + + Create a new Eventbrite event. + + Swagger operation ID: `CreateEventV2`. + + Args: + organization_id: Select the organization. + event_name_html: The name of the event. + event_description_html: The description on the event page. + event_start_utc: Start time (UTC format Ex. 2020-01-12T12:00:00Z). + event_end_utc: End time (UTC format Ex. 2020-01-13T15:00:00Z). + event_start_timezone: Timezone of the event. + event_end_timezone: Timezone of the event. + event_currency: Currency for this Event's transactions. + event_organizer_id: The organizer of the event. + event_venue_id: A previously-created venue to associate with this + event. + event_category_id: The category of the event. + event_password: Password needed to see the event in unlisted mode. + event_capacity: Set specific capacity (if omitted, sums ticket + capacities). + event_shareable: If users can share the event on social media. + event_invite_only: Only invited users can see the event page. + event_online_event: Whether the event is online-only (no venue). + event_listed: If the event is publicly listed and searchable. + event_hide_start_date: Whether the start date should be hidden. + event_hide_end_date: Whether the end date should be hidden. + event_show_remaining: If the remaining number of tickets is + publicly visible on the event page. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v3/organizations/{quote(str(organization_id), safe='')}/events/" + ) + query_params = [] + value = str(event_name_html) + if isinstance(event_name_html, bool): + value = value.lower() + query_params.append(f"event.name.html={quote(value, safe='')}") + value = str(event_description_html) + if isinstance(event_description_html, bool): + value = value.lower() + query_params.append(f"event.description.html={quote(value, safe='')}") + value = str(event_start_utc) + if isinstance(event_start_utc, bool): + value = value.lower() + query_params.append(f"event.start.utc={quote(value, safe='')}") + value = str(event_end_utc) + if isinstance(event_end_utc, bool): + value = value.lower() + query_params.append(f"event.end.utc={quote(value, safe='')}") + value = str(event_start_timezone) + if isinstance(event_start_timezone, bool): + value = value.lower() + query_params.append(f"event.start.timezone={quote(value, safe='')}") + value = str(event_end_timezone) + if isinstance(event_end_timezone, bool): + value = value.lower() + query_params.append(f"event.end.timezone={quote(value, safe='')}") + value = str(event_currency) + if isinstance(event_currency, bool): + value = value.lower() + query_params.append(f"event.currency={quote(value, safe='')}") + if event_organizer_id is not None: + value = str(event_organizer_id) + if isinstance(event_organizer_id, bool): + value = value.lower() + query_params.append(f"event.organizer_id={quote(value, safe='')}") + if event_venue_id is not None: + value = str(event_venue_id) + if isinstance(event_venue_id, bool): + value = value.lower() + query_params.append(f"event.venue_id={quote(value, safe='')}") + if event_category_id is not None: + value = str(event_category_id) + if isinstance(event_category_id, bool): + value = value.lower() + query_params.append(f"event.category_id={quote(value, safe='')}") + if event_password is not None: + value = str(event_password) + if isinstance(event_password, bool): + value = value.lower() + query_params.append(f"event.password={quote(value, safe='')}") + if event_capacity is not None: + value = str(event_capacity) + if isinstance(event_capacity, bool): + value = value.lower() + query_params.append(f"event.capacity={quote(value, safe='')}") + if event_shareable is not None: + value = str(event_shareable) + if isinstance(event_shareable, bool): + value = value.lower() + query_params.append(f"event.shareable={quote(value, safe='')}") + if event_invite_only is not None: + value = str(event_invite_only) + if isinstance(event_invite_only, bool): + value = value.lower() + query_params.append(f"event.invite_only={quote(value, safe='')}") + if event_online_event is not None: + value = str(event_online_event) + if isinstance(event_online_event, bool): + value = value.lower() + query_params.append(f"event.online_event={quote(value, safe='')}") + if event_listed is not None: + value = str(event_listed) + if isinstance(event_listed, bool): + value = value.lower() + query_params.append(f"event.listed={quote(value, safe='')}") + if event_hide_start_date is not None: + value = str(event_hide_start_date) + if isinstance(event_hide_start_date, bool): + value = value.lower() + query_params.append(f"event.hide_start_date={quote(value, safe='')}") + if event_hide_end_date is not None: + value = str(event_hide_end_date) + if isinstance(event_hide_end_date, bool): + value = value.lower() + query_params.append(f"event.hide_end_date={quote(value, safe='')}") + if event_show_remaining is not None: + value = str(event_show_remaining) + if isinstance(event_show_remaining, bool): + value = value.lower() + query_params.append(f"event.show_remaining={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_event( + self, + id: str, + organization_id: str, + event_start_timezone: str, + event_end_timezone: str, + event_currency: str, + *, + event_name_html: Optional[str] = None, + event_description_html: Optional[str] = None, + event_start_utc: Optional[str] = None, + event_end_utc: Optional[str] = None, + event_organizer_id: Optional[str] = None, + event_venue_id: Optional[str] = None, + event_category_id: Optional[str] = None, + event_password: Optional[str] = None, + event_capacity: Optional[str] = None, + event_shareable: Optional[bool] = None, + event_invite_only: Optional[bool] = None, + event_online_event: Optional[bool] = None, + event_listed: Optional[bool] = None, + event_hide_start_date: Optional[bool] = None, + event_hide_end_date: Optional[bool] = None, + event_show_remaining: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update event + + Update an existing event. + + Swagger operation ID: `UpdateEventV2`. + + Args: + id: Event to update. + organization_id: Select the organization. + event_start_timezone: Timezone of the event. + event_end_timezone: Timezone of the event. + event_currency: Currency for this Event's transactions. + event_name_html: The name of the event. + event_description_html: The description on the event page. + event_start_utc: Start time (UTC format Ex. 2017-01-12T13:45:30Z). + event_end_utc: End time (UTC format Ex. 2017-01-12T16:45:30Z). + event_organizer_id: The organizer of the event. + event_venue_id: A previously-created venue to associate with this + event. + event_category_id: The category of the event. + event_password: Password needed to see the event in unlisted mode. + event_capacity: Set specific capacity (if omitted, sums ticket + capacities). + event_shareable: Set specific capacity (if omitted, sums ticket + capacities). + event_invite_only: Only invited users can see the event page. + event_online_event: Whether the event is online-only (no venue). + event_listed: If the event is publicly listed and searchable. + event_hide_start_date: Whether the start date should be hidden. + event_hide_end_date: Whether the start date should be hidden. + event_show_remaining: If the remaining number of tickets is + publicly visible on the event page. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/v3/events/{quote(str(id), safe='')}/" + ) + query_params = [] + value = str(organization_id) + if isinstance(organization_id, bool): + value = value.lower() + query_params.append(f"organization_id={quote(value, safe='')}") + if event_name_html is not None: + value = str(event_name_html) + if isinstance(event_name_html, bool): + value = value.lower() + query_params.append(f"event.name.html={quote(value, safe='')}") + if event_description_html is not None: + value = str(event_description_html) + if isinstance(event_description_html, bool): + value = value.lower() + query_params.append(f"event.description.html={quote(value, safe='')}") + if event_start_utc is not None: + value = str(event_start_utc) + if isinstance(event_start_utc, bool): + value = value.lower() + query_params.append(f"event.start.utc={quote(value, safe='')}") + if event_end_utc is not None: + value = str(event_end_utc) + if isinstance(event_end_utc, bool): + value = value.lower() + query_params.append(f"event.end.utc={quote(value, safe='')}") + value = str(event_start_timezone) + if isinstance(event_start_timezone, bool): + value = value.lower() + query_params.append(f"event.start.timezone={quote(value, safe='')}") + value = str(event_end_timezone) + if isinstance(event_end_timezone, bool): + value = value.lower() + query_params.append(f"event.end.timezone={quote(value, safe='')}") + value = str(event_currency) + if isinstance(event_currency, bool): + value = value.lower() + query_params.append(f"event.currency={quote(value, safe='')}") + if event_organizer_id is not None: + value = str(event_organizer_id) + if isinstance(event_organizer_id, bool): + value = value.lower() + query_params.append(f"event.organizer_id={quote(value, safe='')}") + if event_venue_id is not None: + value = str(event_venue_id) + if isinstance(event_venue_id, bool): + value = value.lower() + query_params.append(f"event.venue_id={quote(value, safe='')}") + if event_category_id is not None: + value = str(event_category_id) + if isinstance(event_category_id, bool): + value = value.lower() + query_params.append(f"event.category_id={quote(value, safe='')}") + if event_password is not None: + value = str(event_password) + if isinstance(event_password, bool): + value = value.lower() + query_params.append(f"event.password={quote(value, safe='')}") + if event_capacity is not None: + value = str(event_capacity) + if isinstance(event_capacity, bool): + value = value.lower() + query_params.append(f"event.capacity={quote(value, safe='')}") + if event_shareable is not None: + value = str(event_shareable) + if isinstance(event_shareable, bool): + value = value.lower() + query_params.append(f"event.shareable={quote(value, safe='')}") + if event_invite_only is not None: + value = str(event_invite_only) + if isinstance(event_invite_only, bool): + value = value.lower() + query_params.append(f"event.invite_only={quote(value, safe='')}") + if event_online_event is not None: + value = str(event_online_event) + if isinstance(event_online_event, bool): + value = value.lower() + query_params.append(f"event.online_event={quote(value, safe='')}") + if event_listed is not None: + value = str(event_listed) + if isinstance(event_listed, bool): + value = value.lower() + query_params.append(f"event.listed={quote(value, safe='')}") + if event_hide_start_date is not None: + value = str(event_hide_start_date) + if isinstance(event_hide_start_date, bool): + value = value.lower() + query_params.append(f"event.hide_start_date={quote(value, safe='')}") + if event_hide_end_date is not None: + value = str(event_hide_end_date) + if isinstance(event_hide_end_date, bool): + value = value.lower() + query_params.append(f"event.hide_end_date={quote(value, safe='')}") + if event_show_remaining is not None: + value = str(event_show_remaining) + if isinstance(event_show_remaining, bool): + value = value.lower() + query_params.append(f"event.show_remaining={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_organizations( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + GetOrganizations + + Get a list of organizations for your account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetOrganizations`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v3/users/me/organizations/" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_organizers( + self, + organization_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get organizers + + Get a list of organizers for organization. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetOrganizersV2`. + + Args: + organization_id: Select the organization. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v3" + f"/organizations" + f"/{quote(str(organization_id), safe='')}" + f"/organizers" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("organizers", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_my_venues( + self, + organization_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get venues + + Get venues for organization. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMyVenuesV2`. + + Args: + organization_id: Select the organization. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v3/organizations/{quote(str(organization_id), safe='')}/venues/" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("venues", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_categories( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get categories + + Get the Eventbrite event categories. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetCategories`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v3/categories/" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("categories", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_organization_events( + self, + organization_id: str, + order_by: str, + status: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get organization events + + Get organization events. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetOrganizationEvents`. + + Args: + organization_id: Select the organization. + order_by: Order of the returned events. + status: Status of the returned events. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v3/organizations/{quote(str(organization_id), safe='')}/events/" + ) + query_params = [] + value = str(order_by) + if isinstance(order_by, bool): + value = value.lower() + query_params.append(f"order_by={quote(value, safe='')}") + value = str(status) + if isinstance(status, bool): + value = value.lower() + query_params.append(f"status={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("events", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/eventhubs.py b/src/azure/connectors/aio/eventhubs.py new file mode 100644 index 0000000..111af02 --- /dev/null +++ b/src/azure/connectors/aio/eventhubs.py @@ -0,0 +1,659 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# EventhubsClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.eventhubs import ( + Event, + ObjectEntity, + SendEvent, + SendEventsInput, + SystemProperties, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "EventhubsClient", + "Event", + "ObjectEntity", + "SendEvent", + "SendEventsInput", + "SystemProperties", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class EventhubsClient(ConnectorClientBase): + """Typed client for eventhubs connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a EventhubsClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "eventhubs" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def send_event( + self, + input: SendEvent | Mapping[str, Any], + event_hub_name: str, + *, + partition_key: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Send event + + Send event. + + Swagger operation ID: `SendEvent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + event_hub_name: Name of the Event Hub. + partition_key: Partition key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(str(event_hub_name), safe='')}/events" + ) + query_params = [] + if partition_key is not None: + value = str(partition_key) + if isinstance(partition_key, bool): + value = value.lower() + query_params.append(f"partitionKey={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def send_events( + self, + input: SendEventsInput, + event_hub_name: str, + partition_key: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Send one or more events to the Event Hub partition + + Send one or more events to the Event Hub partition. + + Swagger operation ID: `SendEvents`. + + Args: + input: The request body. + event_hub_name: Name of the Event Hub. + partition_key: Partition key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(str(event_hub_name), safe='')}/events/batch" + ) + query_params = [] + value = str(partition_key) + if isinstance(partition_key, bool): + value = value.lower() + query_params.append(f"partitionKey={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_event_hubs( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[str]: + """ + Get all Event Hubs in a namespace + + Get all Event Hubs in a namespace. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetEventHubs`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[str]: An Azure Core pager over connector results. + Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/eventhubs" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[str]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_content_types( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[str]: + """ + Get all content types + + Get all content types. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetContentTypes`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[str]: An Azure Core pager over connector results. + Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/contenttypes" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[str]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_consumer_groups( + self, + event_hub_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[str]: + """ + Get all the consumer groups for an event hub + + Get all the consumer groups for an event hub. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetConsumerGroups`. + + Args: + event_hub_name: The Event Hub name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[str]: An Azure Core pager over connector results. + Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/consumergroups" + query_params = [] + value = str(event_hub_name) + if isinstance(event_hub_name, bool): + value = value.lower() + query_params.append(f"eventHubName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[str]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_partition_keys( + self, + event_hub_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[str]: + """ + Get all partition keys in an Event Hub + + Get all partition keys in an Event Hub. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetPartitionKeys`. + + Args: + event_hub_name: The Event Hub name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[str]: An Azure Core pager over connector results. + Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/partitions" + query_params = [] + value = str(event_hub_name) + if isinstance(event_hub_name, bool): + value = value.lower() + query_params.append(f"eventHubName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[str]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def generate_event_schema( + self, + content_type: str, + *, + content_schema: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Generate event schema + + Generate event schema V2. + + Swagger operation ID: `GenerateEventSchemaV2`. + + Args: + content_type: Content type. + content_schema: content schema of the event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/eventschemaV2" + query_params = [] + value = str(content_type) + if isinstance(content_type, bool): + value = value.lower() + query_params.append(f"contentType={quote(value, safe='')}") + if content_schema is not None: + value = str(content_schema) + if isinstance(content_schema, bool): + value = value.lower() + query_params.append(f"contentSchema={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/excelonline.py b/src/azure/connectors/aio/excelonline.py new file mode 100644 index 0000000..bce31f4 --- /dev/null +++ b/src/azure/connectors/aio/excelonline.py @@ -0,0 +1,1154 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# ExcelonlineClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.excelonline import ( + BlobDataSetsMetadata, + BlobMetadata, + CreateWorksheetInput, + DataSetsMetadata, + GetAllWorksheetsResponse, + GetColumnsResponse, + GetTablesResponse, + Item, + ItemsList, + ObjectEntity, + Table, + TableCapabilitiesMetadata, + TableFilterRestrictionsMetadata, + TableMetadata, + TableSelectRestrictionsMetadata, + TableSortRestrictionsMetadata, + TableToCreate, + TablesList, + TabularDataSetsMetadata, + WorksheetMetadata, +) + +__all__ = [ + "ExcelonlineClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "CreateWorksheetInput", + "DataSetsMetadata", + "GetAllWorksheetsResponse", + "GetColumnsResponse", + "GetTablesResponse", + "Item", + "ItemsList", + "ObjectEntity", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TableToCreate", + "TablesList", + "TabularDataSetsMetadata", + "WorksheetMetadata", +] + + +# Type Definitions + +# Client Class + +class ExcelonlineClient(ConnectorClientBase): + """Typed client for excelonline connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a ExcelonlineClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "excelonline" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_table( + self, + input: TableToCreate | Mapping[str, Any], + drive: str, + file: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create table + + Create a new table in the Excel workbook. + + Swagger operation ID: `CreateTable`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/files" + f"/{quote(str(file), safe='')}" + f"/tables" + ) + query_params = [] + query_params.append("source=" + quote("me", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_id_column( + self, + drive: str, + file: str, + table: str, + *, + id_column: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add a key column to a table + + Add a key column to an Excel table. The new column will be appended to + the right. The new key column must be unique in the table. + + Swagger operation ID: `CreateIdColumn`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + id_column: Provide the key column name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/files" + f"/{quote(str(file), safe='')}" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/createIdColumn" + ) + query_params = [] + query_params.append("source=" + quote("me", safe='')) + query_params.append("populateColumn=" + quote("false", safe='')) + if id_column is not None: + value = str(id_column) + if isinstance(id_column, bool): + value = value.lower() + query_params.append(f"idColumn={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_items( + self, + drive: str, + file: str, + table: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + select: Optional[str] = None, + date_time_format: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List rows present in a table + + List rows present in a table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItems`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + filter: An ODATA filter query to restrict the entries returned. + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Comma-separated list of columns to retrieve (first 500 by + default). + date_time_format: DateTime Format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/files" + f"/{quote(str(file), safe='')}" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/items" + ) + query_params = [] + query_params.append("source=" + quote("me", safe='')) + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if date_time_format is not None: + value = str(date_time_format) + if isinstance(date_time_format, bool): + value = value.lower() + query_params.append(f"dateTimeFormat={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_item( + self, + drive: str, + file: str, + table: str, + id: str, + id_column: str, + *, + date_time_format: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a row + + Get a row using a key column. This action will retrieve all the values + of the specified row given a column and key column. + + Swagger operation ID: `GetItem`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + id: Enter the key value. + id_column: Select a column from the drop-down. + date_time_format: DateTime Format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/files" + f"/{quote(str(file), safe='')}" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + query_params = [] + query_params.append("source=" + quote("me", safe='')) + value = str(id_column) + if isinstance(id_column, bool): + value = value.lower() + query_params.append(f"idColumn={quote(value, safe='')}") + if date_time_format is not None: + value = str(date_time_format) + if isinstance(date_time_format, bool): + value = value.lower() + query_params.append(f"dateTimeFormat={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_item( + self, + drive: str, + file: str, + table: str, + id: str, + id_column: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a row + + Delete a row using a key column. + + Swagger operation ID: `DeleteItem`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + id: Enter the key value. + id_column: Select a column from the drop-down. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/files" + f"/{quote(str(file), safe='')}" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + query_params = [] + query_params.append("source=" + quote("me", safe='')) + value = str(id_column) + if isinstance(id_column, bool): + value = value.lower() + query_params.append(f"idColumn={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def patch_item( + self, + input: Item | Mapping[str, Any], + drive: str, + file: str, + table: str, + id: str, + id_column: str, + *, + date_time_format: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a row + + Update a row using a key column. The input value will overwrite the + specified cells and columns left blank will not be updated. In order to + append (instead of overwrite) a value, use the \"Get a row\" action to + retrieve the content first. + + Swagger operation ID: `PatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + id: Enter the key value. + id_column: Select a column from the drop-down. + date_time_format: DateTime Format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/files" + f"/{quote(str(file), safe='')}" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + query_params = [] + query_params.append("source=" + quote("me", safe='')) + value = str(id_column) + if isinstance(id_column, bool): + value = value.lower() + query_params.append(f"idColumn={quote(value, safe='')}") + if date_time_format is not None: + value = str(date_time_format) + if isinstance(date_time_format, bool): + value = value.lower() + query_params.append(f"dateTimeFormat={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_all_worksheets( + self, + drive: str, + file: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get worksheets + + Get a list of worksheets in the Excel workbook. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAllWorksheets`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/items" + f"/{quote(str(file), safe='')}" + f"/workbook" + f"/worksheets" + ) + query_params = [] + query_params.append("source=" + quote("me", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_worksheet( + self, + input: CreateWorksheetInput | Mapping[str, Any], + drive: str, + file: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create worksheet + + Create a new worksheet in the Excel workbook. + + Swagger operation ID: `CreateWorksheet`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/items" + f"/{quote(str(file), safe='')}" + f"/workbook" + f"/worksheets" + ) + query_params = [] + query_params.append("source=" + quote("me", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tables( + self, + drive: str, + file: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get tables + + Get a list of tables in the Excel workbook. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTables`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/items" + f"/{quote(str(file), safe='')}" + f"/workbook" + f"/tables" + ) + query_params = [] + query_params.append("source=" + quote("me", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def add_row( + self, + input: Item | Mapping[str, Any], + drive: str, + file: str, + table: str, + *, + date_time_format: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add a row into a table + + Add a new row into the Excel table. + + Swagger operation ID: `AddRowV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + date_time_format: DateTime Format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.2" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/items" + f"/{quote(str(file), safe='')}" + f"/workbook" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/rows" + ) + query_params = [] + query_params.append("source=" + quote("me", safe='')) + if date_time_format is not None: + value = str(date_time_format) + if isinstance(date_time_format, bool): + value = value.lower() + query_params.append(f"dateTimeFormat={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_columns( + self, + drive: str, + file: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get table columns + + Get table columns. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetColumns`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/items" + f"/{quote(str(file), safe='')}" + f"/workbook" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/columns" + ) + query_params = [] + query_params.append("source=" + quote("me", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/excelonlinebusiness.py b/src/azure/connectors/aio/excelonlinebusiness.py new file mode 100644 index 0000000..6ceff7f --- /dev/null +++ b/src/azure/connectors/aio/excelonlinebusiness.py @@ -0,0 +1,2027 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# ExcelonlinebusinessClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.excelonlinebusiness import ( + BlobDataSetsMetadata, + BlobMetadata, + Comment, + CommentDetails, + CommentsList, + CreateFileMetadata, + CreateWorksheetInput, + DataSetsMetadata, + GetAllWorksheetsResponse, + GetColumnsResponse, + GetDrivesResponse, + GetItemResponse, + GetSingleScriptResponse, + GetSourcesResponse, + GetTablesResponse, + Item, + ItemsList, + ObjectEntity, + RawAndFormattedTableSchema, + RunScriptProdInput, + RunScriptProdResponse, + ScriptParameters, + ScriptReturnValues, + SensitivityLabelMetadata, + Table, + TableCapabilitiesMetadata, + TableFilterRestrictionsMetadata, + TableMetadata, + TableSelectRestrictionsMetadata, + TableSortRestrictionsMetadata, + TableToCreate, + TablesList, + TabularDataSetsMetadata, + TabularItem, + TabularItemsList, + WorkbookRange, + WorksheetMetadata, +) + +__all__ = [ + "ExcelonlinebusinessClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "Comment", + "CommentDetails", + "CommentsList", + "CreateFileMetadata", + "CreateWorksheetInput", + "DataSetsMetadata", + "GetAllWorksheetsResponse", + "GetColumnsResponse", + "GetDrivesResponse", + "GetItemResponse", + "GetSingleScriptResponse", + "GetSourcesResponse", + "GetTablesResponse", + "Item", + "ItemsList", + "ObjectEntity", + "RawAndFormattedTableSchema", + "RunScriptProdInput", + "RunScriptProdResponse", + "ScriptParameters", + "ScriptReturnValues", + "SensitivityLabelMetadata", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TableToCreate", + "TablesList", + "TabularDataSetsMetadata", + "TabularItem", + "TabularItemsList", + "WorkbookRange", + "WorksheetMetadata", +] + + +# Type Definitions + +# Client Class + +class ExcelonlinebusinessClient(ConnectorClientBase): + """Typed client for excelonlinebusiness connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a ExcelonlinebusinessClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "excelonlinebusiness" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_table( + self, + input: TableToCreate | Mapping[str, Any], + drive: str, + file: str, + source: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create table + + Create a new table in the Excel workbook. + + Swagger operation ID: `CreateTable`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/files" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/tables" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_id_column( + self, + drive: str, + file: str, + table: str, + source: str, + *, + id_column: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add a key column to a table + + Add a key column to an Excel table. The new column will be appended to + the right. + + Swagger operation ID: `CreateIdColumn`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + id_column: Provide the key column name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/files" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/createIdColumn" + ) + query_params = [] + query_params.append("populateColumn=" + quote("false", safe='')) + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if id_column is not None: + value = str(id_column) + if isinstance(id_column, bool): + value = value.lower() + query_params.append(f"idColumn={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_items( + self, + drive: str, + file: str, + table: str, + source: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + select: Optional[str] = None, + date_time_format: Optional[str] = None, + extract_sensitivity_label: Optional[bool] = None, + fetch_sensitivity_label_metadata: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List rows present in a table + + List rows present in a table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItems`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + filter: An ODATA filter query to restrict the entries returned. + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Comma-separated list of columns to retrieve (first 500 by + default). + date_time_format: DateTime Format. + extract_sensitivity_label: A boolean whether to extract sensitivity + label Id for associated artefact. + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/files" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/items" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if date_time_format is not None: + value = str(date_time_format) + if isinstance(date_time_format, bool): + value = value.lower() + query_params.append(f"dateTimeFormat={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if fetch_sensitivity_label_metadata is not None: + value = str(fetch_sensitivity_label_metadata) + if isinstance(fetch_sensitivity_label_metadata, bool): + value = value.lower() + query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_comments( + self, + drive: str, + file: str, + *, + source: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all comments present in a workbook + + List all comments present in a workbook. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetComments`. + + Args: + drive: Ask user to select a document library from the drop-down. + file: Ask user to select an Excel file through File Browse. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/items" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/workbook" + f"/comments" + ) + query_params = [] + if source is not None: + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_comment( + self, + drive: str, + file: str, + commentid: str, + *, + source: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a comment present in a workbook + + Get a comment present in a workbook. + + Swagger operation ID: `GetComment`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + commentid: Provide a comment Id . + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/items" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/workbook" + f"/comments" + f"/{quote(str(commentid), safe='')}" + ) + query_params = [] + if source is not None: + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def reply_comment( + self, + input: CommentDetails | Mapping[str, Any], + drive: str, + file: str, + commentid: str, + *, + source: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Reply to a comment present in a workbook + + Reply to a comment present in a workbook. + + Swagger operation ID: `ReplyComment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Ask user to select a document library from the drop-down. + file: Ask user to select an Excel file through File Browse. + commentid: Provide a comment Id . + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/items" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/workbook" + f"/comments" + f"/{quote(str(commentid), safe='')}" + f"/replies" + ) + query_params = [] + if source is not None: + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_item( + self, + drive: str, + file: str, + table: str, + id: str, + source: str, + id_column: str, + *, + date_time_format: Optional[str] = None, + extract_sensitivity_label: Optional[bool] = None, + fetch_sensitivity_label_metadata: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a row + + Get a row using a key column. + + Swagger operation ID: `GetItem`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + id: Enter the key value. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + id_column: Select a column from the drop-down. + date_time_format: DateTime Format. + extract_sensitivity_label: A boolean whether to extract sensitivity + label Id for associated artefact. + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/files" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(id_column) + if isinstance(id_column, bool): + value = value.lower() + query_params.append(f"idColumn={quote(value, safe='')}") + if date_time_format is not None: + value = str(date_time_format) + if isinstance(date_time_format, bool): + value = value.lower() + query_params.append(f"dateTimeFormat={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if fetch_sensitivity_label_metadata is not None: + value = str(fetch_sensitivity_label_metadata) + if isinstance(fetch_sensitivity_label_metadata, bool): + value = value.lower() + query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_item( + self, + drive: str, + file: str, + table: str, + id: str, + source: str, + id_column: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a row + + Delete a row using a key column. + + Swagger operation ID: `DeleteItem`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + id: Enter the key value. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + id_column: Select a column from the drop-down. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/files" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(id_column) + if isinstance(id_column, bool): + value = value.lower() + query_params.append(f"idColumn={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def patch_item( + self, + input: Item | Mapping[str, Any], + drive: str, + file: str, + table: str, + id: str, + source: str, + id_column: str, + *, + date_time_format: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a row + + Update a row using a key column. The input value will overwrite the + specified cells and columns left blank will not be updated. In order to + append (instead of overwrite) a value, use the \"Get a row\" action to + retrieve the content first. + + Swagger operation ID: `PatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + id: Enter the key value. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + id_column: Select a column from the drop-down. + date_time_format: DateTime Format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/files" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(id_column) + if isinstance(id_column, bool): + value = value.lower() + query_params.append(f"idColumn={quote(value, safe='')}") + if date_time_format is not None: + value = str(date_time_format) + if isinstance(date_time_format, bool): + value = value.lower() + query_params.append(f"dateTimeFormat={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_all_worksheets( + self, + drive: str, + file: str, + source: str, + *, + extract_sensitivity_label: Optional[bool] = None, + fetch_sensitivity_label_metadata: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get worksheets + + Get a list of worksheets in the Excel workbook. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAllWorksheets`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + extract_sensitivity_label: A boolean whether to extract sensitivity + label Id for associated artefact. + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/items" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/workbook" + f"/worksheets" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if fetch_sensitivity_label_metadata is not None: + value = str(fetch_sensitivity_label_metadata) + if isinstance(fetch_sensitivity_label_metadata, bool): + value = value.lower() + query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_worksheet( + self, + input: CreateWorksheetInput | Mapping[str, Any], + drive: str, + file: str, + source: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create worksheet + + Create a new worksheet in the Excel workbook. + + Swagger operation ID: `CreateWorksheet`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/items" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/workbook" + f"/worksheets" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tables( + self, + drive: str, + file: str, + source: str, + *, + extract_sensitivity_label: Optional[bool] = None, + fetch_sensitivity_label_metadata: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get tables + + Get a list of tables in the Excel workbook. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTables`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + extract_sensitivity_label: A boolean whether to extract sensitivity + label Id for associated artefact. + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/items" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/workbook" + f"/tables" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if fetch_sensitivity_label_metadata is not None: + value = str(fetch_sensitivity_label_metadata) + if isinstance(fetch_sensitivity_label_metadata, bool): + value = value.lower() + query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def add_row( + self, + input: Item | Mapping[str, Any], + drive: str, + file: str, + table: str, + source: str, + *, + date_time_format: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add a row into a table + + Add a new row into the Excel table. + + Swagger operation ID: `AddRowV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + date_time_format: DateTime Format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.2" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/items" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/workbook" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/rows" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if date_time_format is not None: + value = str(date_time_format) + if isinstance(date_time_format, bool): + value = value.lower() + query_params.append(f"dateTimeFormat={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def run_script_prod( + self, + input: RunScriptProdInput | Mapping[str, Any], + drive: str, + file: str, + script_drive: str, + script_id: str, + source: str, + script_source: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Run script from SharePoint library + + Runs an Office Script against an Excel workbook. Use this action when + the script is saved outside of the default location. + + Swagger operation ID: `RunScriptProdV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel workbook through File Browse. + script_drive: Select the SharePoint library of your Office Script + file (.osts) from the drop-down. + script_id: Select an Office Script file (.osts) in a SharePoint + library from the drop-down. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + script_source: Select from the drop-down or specify one of the + following: - \"me\" - \"SharePoint Site URL\" - + \"users/someone's UPN\" - \"groups/group Id\" - + \"sites/SharePoint Site URL:/teams/team name:\" (the colons are + required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/officescripting" + f"/api" + f"/unattended" + f"/run" + f"/{quote(str(drive), safe='')}" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/{quote(str(script_drive), safe='')}" + f"/{quote(quote(str(script_id), safe=''), safe='')}" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(script_source) + if isinstance(script_source, bool): + value = value.lower() + query_params.append(f"scriptSource={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_sources( + self, + *, + top: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get sources + + Get a list of sources. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetSources`. + + Args: + top: Top. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/codeless/v1.0/sources" + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_drives( + self, + source: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get drives + + Get a list of drives. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetDrives`. + + Args: + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/codeless/v1.0/drives" + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_columns( + self, + drive: str, + file: str, + table: str, + source: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get table columns + + Get table columns. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetColumns`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/items" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/workbook" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/columns" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_table( + self, + drive: str, + file: str, + table: str, + source: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get metadata of a table + + Get metadata of a table. + + Swagger operation ID: `GetTable`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/drives" + f"/{quote(str(drive), safe='')}" + f"/items" + f"/{quote(quote(str(file), safe=''), safe='')}" + f"/workbook" + f"/tables" + f"/{quote(str(table), safe='')}" + f"/metadata" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_single_script( + self, + script_source: str, + script_drive: str, + script_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Gets one script + + Gets one of the scripts. + + Swagger operation ID: `GetSingleScriptV2`. + + Args: + script_source: script source. + script_drive: script drive. + script_id: Script chosen to use. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/officescripting/api/storage/script" + ) + query_params = [] + value = str(script_source) + if isinstance(script_source, bool): + value = value.lower() + query_params.append(f"scriptSource={quote(value, safe='')}") + value = str(script_drive) + if isinstance(script_drive, bool): + value = value.lower() + query_params.append(f"scriptDrive={quote(value, safe='')}") + value = str(script_id) + if isinstance(script_id, bool): + value = value.lower() + query_params.append(f"scriptId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/formstackforms.py b/src/azure/connectors/aio/formstackforms.py new file mode 100644 index 0000000..7fc682c --- /dev/null +++ b/src/azure/connectors/aio/formstackforms.py @@ -0,0 +1,209 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# FormstackformsClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping +from urllib.parse import quote +import json + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, +) + +from azure.connectors.formstackforms import ( + FormstackFormSubmittedInput, + FormstackFormSubmittedResponse, + GetAvailableFormsResponse, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "FormstackformsClient", + "FormstackFormSubmittedInput", + "FormstackFormSubmittedResponse", + "GetAvailableFormsResponse", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class FormstackformsClient(ConnectorClientBase): + """Typed client for formstackforms connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a FormstackformsClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "formstackforms" + + async def get_available_forms( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Available Forms + + Returns all available forms + + Swagger operation ID: `GetAvailableForms`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/v2/form/" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_form_schema( + self, + form_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Returns Form Schema from Webhook API + + Used for the x-ms-dynamic-schema + + Swagger operation ID: `GetFormSchema`. + + Args: + form_id: form_id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v2/form/{quote(str(form_id), safe='')}/webhookopenapi/" + ) + query_params = [] + query_params.append("file_transfer_type=" + quote("base64encode", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) diff --git a/src/azure/connectors/aio/freshservice.py b/src/azure/connectors/aio/freshservice.py new file mode 100644 index 0000000..dcf3cf2 --- /dev/null +++ b/src/azure/connectors/aio/freshservice.py @@ -0,0 +1,287 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# FreshserviceClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping +from urllib.parse import quote +import json + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, +) + +from azure.connectors.freshservice import ( + AddNoteRequest, + AddNoteResponse, + CreateTicketRequest, + CreateUpdateTicketResponse, + ListTicketResponse, + ListUsersResponse, + TicketResponse, + UpdateTicketRequest, + UpdateTicketResponse, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "FreshserviceClient", + "AddNoteRequest", + "AddNoteResponse", + "CreateTicketRequest", + "CreateUpdateTicketResponse", + "ListTicketResponse", + "ListUsersResponse", + "TicketResponse", + "UpdateTicketRequest", + "UpdateTicketResponse", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class FreshserviceClient(ConnectorClientBase): + """Typed client for freshservice connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a FreshserviceClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "freshservice" + + async def add_note( + self, + input: AddNoteRequest | Mapping[str, Any], + ticket_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add a note to a ticket + + Add a private or public note to a ticket. + + Swagger operation ID: `AddNoteV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + ticket_id: The ticket id to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v2/tickets/{quote(str(ticket_id), safe='')}/notes" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_ticket( + self, + input: CreateTicketRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a ticket + + Create a ticket. + + Swagger operation ID: `CreateTicketV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/v2/tickets" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_ticket( + self, + input: UpdateTicketRequest | Mapping[str, Any], + ticket_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a ticket + + Update a ticket (only specified values will be updated). + + Swagger operation ID: `UpdateTicketV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + ticket_id: The ticket id to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v2/tickets/{quote(str(ticket_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/ftp.py b/src/azure/connectors/aio/ftp.py new file mode 100644 index 0000000..5963c53 --- /dev/null +++ b/src/azure/connectors/aio/ftp.py @@ -0,0 +1,928 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# FtpClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.ftp import ( + BlobDataSetsMetadata, + BlobMetadata, + BlobMetadataPage, + BlobMetadataResponse, + DataSetsMetadata, + ObjectEntity, + TabularDataSetsMetadata, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "FtpClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "BlobMetadataPage", + "BlobMetadataResponse", + "DataSetsMetadata", + "ObjectEntity", + "TabularDataSetsMetadata", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class FtpClient(ConnectorClientBase): + """Typed client for ftp connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a FtpClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "ftp" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_file( + self, + input: bytes, + folder_path: str, + name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create file + + This operation creates a file. If a file is being deleted/renamed on + server right after it was created, connector may return HTTP 404 error + by it's design. Please use a delay for 1 minute before deleting or + renaming newly created file. + + Swagger operation ID: `CreateFile`. + + Args: + input: The binary request body. + folder_path: Select a folder. + name: Name of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/datasets/default/files" + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_file_metadata( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file metadata + + This operation gets the metadata for a file. + + Swagger operation ID: `GetFileMetadata`. + + Args: + id: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_file( + self, + input: bytes, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update file + + This operation updates a file. If a file is being deleted/renamed on + server right after it was updated, connector may return HTTP 404 error + by it's design. Please use a delay for 1 minute before deleting or + renaming recently updated file. + + Swagger operation ID: `UpdateFile`. + + Args: + input: The binary request body. + id: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PUT", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_file( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete file + + This operation deletes a file. + + Swagger operation ID: `DeleteFile`. + + Args: + id: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def copy_file( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Copy file + + This operation copies a file to an FTP server. If a file is being + deleted/renamed on server right after it was copied, connector may + return HTTP 404 error by it's design. Please use a delay for 1 minute + before deleting or renaming newly created file. + + Swagger operation ID: `CopyFile`. + + Args: + source: Url to source file. + destination: Destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/copyFile" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_file_metadata_by_path( + self, + path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file metadata using path + + This operation gets the metadata of a file using the file path. + + Swagger operation ID: `GetFileMetadataByPath`. + + Args: + path: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/GetFileByPath" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_file_content_by_path( + self, + path: str, + *, + infer_content_type: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file content using path + + This operation gets the content of a file using the file path. + + Swagger operation ID: `GetFileContentByPath`. + + Args: + path: Select a file. + infer_content_type: Infer content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/GetFileContentByPath" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def get_file_content( + self, + id: str, + *, + infer_content_type: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file content + + This operation gets the content of a file. + + Swagger operation ID: `GetFileContent`. + + Args: + id: Select a file. + infer_content_type: Infer content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/content" + ) + query_params = [] + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + def list_folder( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List files in folder + + This operation gets the list of files and subfolders in a folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListFolder`. + + Args: + id: Select a folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/folders" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_root_folder( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List files in root folder + + This operation gets the list of files and subfolders in the root + folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListRootFolder`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/folders" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def extract_folder( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + create_folders: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Extract archive to folder + + This operation extracts an archive file into a folder (example: .zip). + + Swagger operation ID: `ExtractFolderV2`. + + Args: + source: Path to the archive file. + destination: Path to the destination folder. + overwrite: Overwrites the destination files if set to 'true'. + create_folders: Extracts folders from archive if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/extractFolderV2" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if create_folders is not None: + value = str(create_folders) + if isinstance(create_folders, bool): + value = value.lower() + query_params.append(f"createFolders={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/github.py b/src/azure/connectors/aio/github.py new file mode 100644 index 0000000..c2d3c80 --- /dev/null +++ b/src/azure/connectors/aio/github.py @@ -0,0 +1,3220 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# GithubClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.github import ( + ActionsPublicKey, + Commit, + CommitComparison, + CreateReferenceRequest, + CreateRepositorySecretRequest, + CreateRepositoryUsingTemplateRequest, + DiffEntry, + GeneralAPIModel, + GitReference, + GitUser, + GraphQlQuery, + IssueBasicDetailsModel, + IssueDetailsModel, + IssueUpdateModel, + Label, + LicenseDetails, + Link, + Milestone, + MilestoneUpdateModel, + MultipleFetchModel, + MultipleSearchFetchModel, + PullRequest, + PullRequestCreateRequest, + PullRequestFile, + PullRequestMergeRequest, + PullRequestMergeResult, + PullRequestUpdateRequest, + QueryRequest, + RepositoryDetails, + RepositoryDispatchEvent, + RepositoryMiniDetails, + RequestReviewersBody, + SingleSearchFetchModel, + TeamDetails, + UserDetailsModel, + Verification, + WebhookCreationResponse, + WebhookPullRequestResponse, + WebhookRequestBody, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "GithubClient", + "ActionsPublicKey", + "Commit", + "CommitComparison", + "CreateReferenceRequest", + "CreateRepositorySecretRequest", + "CreateRepositoryUsingTemplateRequest", + "DiffEntry", + "GeneralAPIModel", + "GitReference", + "GitUser", + "GraphQlQuery", + "IssueBasicDetailsModel", + "IssueDetailsModel", + "IssueUpdateModel", + "Label", + "LicenseDetails", + "Link", + "Milestone", + "MilestoneUpdateModel", + "MultipleFetchModel", + "MultipleSearchFetchModel", + "PullRequest", + "PullRequestCreateRequest", + "PullRequestFile", + "PullRequestMergeRequest", + "PullRequestMergeResult", + "PullRequestUpdateRequest", + "QueryRequest", + "RepositoryDetails", + "RepositoryDispatchEvent", + "RepositoryMiniDetails", + "RequestReviewersBody", + "SingleSearchFetchModel", + "TeamDetails", + "UserDetailsModel", + "Verification", + "WebhookCreationResponse", + "WebhookPullRequestResponse", + "WebhookRequestBody", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class GithubClient(ConnectorClientBase): + """Typed client for github connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a GithubClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "github" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_issue( + self, + input: IssueBasicDetailsModel | Mapping[str, Any], + repository_owner: str, + repository_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create an issue + + This operation is used to create a new issue for a specific repository. + + Swagger operation ID: `CreateIssue`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/issues" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_issues( + self, + repository_owner: str, + repository_name: str, + *, + milestone: Optional[str] = None, + state: Optional[str] = None, + assignee: Optional[str] = None, + creator: Optional[str] = None, + mentioned: Optional[str] = None, + labels: Optional[str] = None, + sort: Optional[str] = None, + direction: Optional[str] = None, + since: Optional[str] = None, + per_page: Optional[int] = None, + page: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get all issues of a repository + + Get all issues of a repository. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetIssues`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + milestone: Filter by milestone. + state: Filter by state. + assignee: Filter by assignee. + creator: Filter by creator. + mentioned: Filter by mentions. + labels: Filter by label names. + sort: Field to sort results by. + direction: Direction of sort. + since: Filter by issues after given date. + per_page: Number of results per page. + page: Page number to display. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/issues" + ) + query_params = [] + if milestone is not None: + value = str(milestone) + if isinstance(milestone, bool): + value = value.lower() + query_params.append(f"milestone={quote(value, safe='')}") + if state is not None: + value = str(state) + if isinstance(state, bool): + value = value.lower() + query_params.append(f"state={quote(value, safe='')}") + if assignee is not None: + value = str(assignee) + if isinstance(assignee, bool): + value = value.lower() + query_params.append(f"assignee={quote(value, safe='')}") + if creator is not None: + value = str(creator) + if isinstance(creator, bool): + value = value.lower() + query_params.append(f"creator={quote(value, safe='')}") + if mentioned is not None: + value = str(mentioned) + if isinstance(mentioned, bool): + value = value.lower() + query_params.append(f"mentioned={quote(value, safe='')}") + if labels is not None: + value = str(labels) + if isinstance(labels, bool): + value = value.lower() + query_params.append(f"labels={quote(value, safe='')}") + if sort is not None: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if direction is not None: + value = str(direction) + if isinstance(direction, bool): + value = value.lower() + query_params.append(f"direction={quote(value, safe='')}") + if since is not None: + value = str(since) + if isinstance(since, bool): + value = value.lower() + query_params.append(f"since={quote(value, safe='')}") + if per_page is not None: + value = str(per_page) + if isinstance(per_page, bool): + value = value.lower() + query_params.append(f"per_page={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_repository_public_key( + self, + repository_owner: str, + repository_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a repository public key + + Gets your public key, which you need to encrypt secrets. You need to + encrypt a secret before you can create or update secrets. + + Swagger operation ID: `GetRepositoryPublicKey`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/actions" + f"/secrets" + f"/public-key" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_update_repository_secret( + self, + input: CreateRepositorySecretRequest | Mapping[str, Any], + repository_owner: str, + repository_name: str, + secret_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Create or update a repository secret + + Creates or updates a repository secret with an encrypted value. Encrypt + your secret using LibSodium. + + Swagger operation ID: `CreateUpdateRepositorySecret`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + secret_name: Name of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/actions" + f"/secrets" + f"/{quote(str(secret_name), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + async def create_repository_using_template( + self, + input: CreateRepositoryUsingTemplateRequest | Mapping[str, Any], + template_owner: str, + template_repository: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a repository using a template + + Creates a new repository using a repository template. The authenticated + user must own or be a member of an organization that owns the + repository. + + Swagger operation ID: `CreateRepositoryUsingTemplate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + template_owner: Name of the template repository owner. + template_repository: Name of the template repository. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(template_owner), safe='')}" + f"/{quote(str(template_repository), safe='')}" + f"/generate" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_repository_by_id( + self, + repository_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a repository by Id + + Gets a repository by Id. + + Swagger operation ID: `GetRepositoryById`. + + Args: + repository_id: Unique Identifier of the repository. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repositories/{quote(str(repository_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_reference( + self, + input: CreateReferenceRequest | Mapping[str, Any], + repository_owner: str, + repository_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a reference + + Creates a reference for your repository. You are unable to create new + references for empty repositories, even if the commit SHA-1 hash used + exists. Empty repositories are repositories without branches. + + Swagger operation ID: `CreateReference`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/git" + f"/refs" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_reference( + self, + repository_owner: str, + repository_name: str, + reference: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a reference + + Returns a single reference from your Git database. The `reference` + parameter must be formatted as `heads/` for branches and + `tags/` for tags. If the `reference` doesn't match an + existing ref, a `404` is returned. + + Swagger operation ID: `GetReference`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + reference: The ref in the URL must be formatted as heads/ for branches and tags/ for tags. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/git" + f"/ref" + f"/{quote(str(reference), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def merge_pull_request( + self, + input: PullRequestMergeRequest | Mapping[str, Any], + repository_owner: str, + repository_name: str, + pull_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Merge a pull request + + This operation is used to merge a pull request for the repository. + + Swagger operation ID: `MergePullRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + pull_number: Pull Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/pulls" + f"/{quote(str(pull_number), safe='')}" + f"/merge" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_pull_request( + self, + repository_owner: str, + repository_name: str, + pull_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a pull request + + This operation is used to get a pull request for the repository. + + Swagger operation ID: `GetPullRequest`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + pull_number: Pull Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/pulls" + f"/{quote(str(pull_number), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_pull_request( + self, + input: PullRequestUpdateRequest | Mapping[str, Any], + repository_owner: str, + repository_name: str, + pull_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a pull request + + This operation is used to update a pull request for the repository. To + update a pull request in a public repository, you must have write + access to the head or the source branch. For organization-owned + repositories, you must be a member of the organization that owns the + repository to open or update a pull request. + + Swagger operation ID: `UpdatePullRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + pull_number: Pull Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/pulls" + f"/{quote(str(pull_number), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_pull_request_files( + self, + repository_owner: str, + repository_name: str, + pull_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get the list of files from a pull request + + This operation is used to get the list of files from a pull request for + the repository. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetPullRequestFiles`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + pull_number: Pull Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/pulls" + f"/{quote(str(pull_number), safe='')}" + f"/files" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def request_reviewers_pull_request( + self, + input: RequestReviewersBody | Mapping[str, Any], + repository_owner: str, + repository_name: str, + pull_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Request reviewers for a pull request + + Requests reviews for a pull request from a given set of users and/or + teams. + + Swagger operation ID: `RequestReviewersPullRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + pull_number: Pull Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/pulls" + f"/{quote(str(pull_number), safe='')}" + f"/requested_reviewers" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def remove_reviewers_pull_request( + self, + input: RequestReviewersBody | Mapping[str, Any], + repository_owner: str, + repository_name: str, + pull_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Remove requested reviewers from a pull request + + Remove requested reviewers from a pull request from a given set of + users and/or teams. + + Swagger operation ID: `RemoveReviewersPullRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + pull_number: Pull Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/pulls" + f"/{quote(str(pull_number), safe='')}" + f"/requested_reviewers" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def create_pull_request( + self, + input: PullRequestCreateRequest | Mapping[str, Any], + repository_owner: str, + repository_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a pull request + + This operation is to create a pull request in a repository. To open or + update a pull request in a public repository, you must have write + access to the head or the source branch. For organization-owned + repositories, you must be a member of the organization that owns the + repository to create a pull request. + + Swagger operation ID: `CreatePullRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/pulls" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_pull_requests( + self, + repository_owner: str, + repository_name: str, + *, + state: Optional[str] = None, + head: Optional[str] = None, + base: Optional[str] = None, + sort: Optional[str] = None, + direction: Optional[str] = None, + per_page: Optional[int] = None, + page: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get all Pull Requests of A Repository + + Get all Pull Requests of A Repository. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetPullRequests`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + state: Filter by state. + head: Filter by head user or organization. + base: Filter by base branch name. + sort: What to sort the results by. + direction: Direction of sort. + per_page: Number of results per page. + page: Page number to display. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/pulls" + ) + query_params = [] + if state is not None: + value = str(state) + if isinstance(state, bool): + value = value.lower() + query_params.append(f"state={quote(value, safe='')}") + if head is not None: + value = str(head) + if isinstance(head, bool): + value = value.lower() + query_params.append(f"head={quote(value, safe='')}") + if base is not None: + value = str(base) + if isinstance(base, bool): + value = value.lower() + query_params.append(f"base={quote(value, safe='')}") + if sort is not None: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if direction is not None: + value = str(direction) + if isinstance(direction, bool): + value = value.lower() + query_params.append(f"direction={quote(value, safe='')}") + if per_page is not None: + value = str(per_page) + if isinstance(per_page, bool): + value = value.lower() + query_params.append(f"per_page={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_repository_dispatch_event( + self, + input: RepositoryDispatchEvent | Mapping[str, Any], + repository_owner: str, + repository_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Create a repository dispatch event + + This operation is to trigger a webhook event called + `repository_dispatch` when you want activity that happens outside of + GitHub to trigger a GitHub Actions workflow or GitHub App webhook. You + must configure your GitHub Actions workflow or GitHub App to run when + the `repository_dispatch` event occurs. + + Swagger operation ID: `CreateRepositoryDispatchEvent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/dispatches" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def compare_repository_commits( + self, + repository_owner: str, + repository_name: str, + base: str, + head: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Compare two commits + + Both `base` and `head` must be branch names in `repositoryName`. To + compare branches across other repositories in the same network as + `repositoryName`, use the format `:branch`. The response is + equivalent to running the `git log base..head` command; however, + commits are returned in chronological order. + + Swagger operation ID: `CompareRepositoryCommits`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + base: base parameter. + head: head parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/compare" + f"/{quote(str(base), safe='')}...{quote(str(head), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_selected_repo_to_org_secret( + self, + repository_owner: str, + repository_id: int, + secret_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add selected repository to an organization secret + + Adds a repository to an organization secret when the `visibility` for + repository access is set to `selected`. The visibility is set when you + [Create or update an organization + secret](https://developer.github.com/v3/actions/secrets/#create-or-update-an-organization-secret). + You must authenticate using an access token with the `admin:org` scope + to use this endpoint. GitHub Apps must have the `secrets` organization + permission to use this endpoint. + + Swagger operation ID: `AddSelectedRepoToOrgSecret`. + + Args: + repository_owner: Name of the repository owner. + repository_id: Unique Identifier of the repository. + secret_name: Name of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/orgs" + f"/{quote(str(repository_owner), safe='')}" + f"/actions" + f"/secrets" + f"/{quote(str(secret_name), safe='')}" + f"/repositories" + f"/{quote(str(repository_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + async def remove_selected_repo_from_org_secret( + self, + repository_owner: str, + repository_id: int, + secret_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Remove selected repository from an organization secret + + Removes a repository from an organization secret when the `visibility` + for repository access is set to `selected`. The visibility is set when + you [Create or update an organization + secret](https://developer.github.com/v3/actions/secrets/#create-or-update-an-organization-secret). + You must authenticate using an access token with the `admin:org` scope + to use this endpoint. GitHub Apps must have the `secrets` organization + permission to use this endpoint. + + Swagger operation ID: `RemoveSelectedRepoFromOrgSecret`. + + Args: + repository_owner: Name of the repository owner. + repository_id: Unique Identifier of the repository. + secret_name: Name of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/orgs" + f"/{quote(str(repository_owner), safe='')}" + f"/actions" + f"/secrets" + f"/{quote(str(secret_name), safe='')}" + f"/repositories" + f"/{quote(str(repository_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def delete_webhook_trigger( + self, + repository_owner: str, + repository_name: str, + webhook_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Deletes a GitHub Webhook + + Deletes a GitHub Webhook + + Swagger operation ID: `DeleteWebhookTrigger`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + webhook_id: ID of the GitHub Webhook. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/hooks" + f"/{quote(str(webhook_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_issue_num( + self, + repository_owner: str, + repository_name: str, + issue_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a particular issue of a repository + + Get a particular issue of a repository. + + Swagger operation ID: `GetIssueNum`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + issue_number: Issue Number for a given issue. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/issues" + f"/{quote(str(issue_number), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_issue_num( + self, + input: IssueUpdateModel | Mapping[str, Any], + repository_owner: str, + repository_name: str, + issue_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update an Issue + + Update an existing issue given the issue number. + + Swagger operation ID: `UpdateIssueNum`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + issue_number: Issue Number for a given issue. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/issues" + f"/{quote(str(issue_number), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_milestone( + self, + input: MilestoneUpdateModel | Mapping[str, Any], + repository_owner: str, + repository_name: str, + milestone_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a milestone + + Update an existing milestone. + + Swagger operation ID: `UpdateMilestone`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + milestone_number: Milestone number for a given milestone. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/milestones" + f"/{quote(str(milestone_number), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_user( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get the authenticated user + + Get the authenticated user. + + Swagger operation ID: `GetUser`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/user" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def search_github_with_query( + self, + input: GraphQlQuery | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Search Github using Query + + Search Github using Query + + Swagger operation ID: `SearchGithubWithQuery`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/graphql" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_assignees( + self, + repository_owner: str, + repository_name: str, + *, + per_page: Optional[int] = None, + page: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Lists the available assignees for issues in a repository + + Lists the available assignees for issues in a repository. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAssignees`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + per_page: Number of results per page. + page: Page number to display. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/assignees" + ) + query_params = [] + if per_page is not None: + value = str(per_page) + if isinstance(per_page, bool): + value = value.lower() + query_params.append(f"per_page={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_collaborators( + self, + repository_owner: str, + repository_name: str, + *, + per_page: Optional[int] = None, + page: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List repository collaborators + + List repository collaborators. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListCollaborators`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + per_page: Number of results per page. + page: Page number to display. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/collaborators" + ) + query_params = [] + if per_page is not None: + value = str(per_page) + if isinstance(per_page, bool): + value = value.lower() + query_params.append(f"per_page={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def check_collaborator( + self, + repository_owner: str, + repository_name: str, + user_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Check if a user is a repository collaborator + + Check if a user is a repository collaborator. + + Swagger operation ID: `checkCollaborator`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + user_name: The handle for the GitHub user account. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/collaborators" + f"/{quote(str(user_name), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_milestones( + self, + repository_owner: str, + repository_name: str, + *, + state: Optional[str] = None, + sort: Optional[str] = None, + direction: Optional[str] = None, + per_page: Optional[int] = None, + page: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Lists all milestones of a repository + + Lists all milestones of a repository. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMilestones`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + state: State of the milestone. + sort: What to sort the results by. + direction: Direction of sort. + per_page: Number of results per page. + page: Page number to display. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/milestones" + ) + query_params = [] + if state is not None: + value = str(state) + if isinstance(state, bool): + value = value.lower() + query_params.append(f"state={quote(value, safe='')}") + if sort is not None: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if direction is not None: + value = str(direction) + if isinstance(direction, bool): + value = value.lower() + query_params.append(f"direction={quote(value, safe='')}") + if per_page is not None: + value = str(per_page) + if isinstance(per_page, bool): + value = value.lower() + query_params.append(f"per_page={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_labels( + self, + repository_owner: str, + repository_name: str, + *, + per_page: Optional[int] = None, + page: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Lists all labels for a repository + + Lists all labels for a repository. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetLabels`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + per_page: Number of results per page. + page: Page number to display. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/labels" + ) + query_params = [] + if per_page is not None: + value = str(per_page) + if isinstance(per_page, bool): + value = value.lower() + query_params.append(f"per_page={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_issue_labels( + self, + repository_owner: str, + repository_name: str, + issue_number: int, + *, + per_page: Optional[int] = None, + page: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Lists all labels for an issue + + Lists all labels for an issue. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetIssueLabels`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + issue_number: Issue Number for a given issue. + per_page: Number of results per page. + page: Page number to display. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/repos" + f"/{quote(str(repository_owner), safe='')}" + f"/{quote(str(repository_name), safe='')}" + f"/issues" + f"/{quote(str(issue_number), safe='')}" + f"/labels" + ) + query_params = [] + if per_page is not None: + value = str(per_page) + if isinstance(per_page, bool): + value = value.lower() + query_params.append(f"per_page={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_repos( + self, + repository_owner: str, + *, + type_: Optional[str] = None, + sort: Optional[str] = None, + direction: Optional[str] = None, + per_page: Optional[int] = None, + page: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Lists all public repositories for a user + + Lists all public repositories for a user. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetRepos`. + + Args: + repository_owner: Name of the repository owner. + type_: Limit results to repositories of the specified type. + sort: The property to sort the results by. + direction: Direction of sort. + per_page: Number of results per page. + page: Page number to fetch. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/users/{quote(str(repository_owner), safe='')}/repos" + ) + query_params = [] + if type_ is not None: + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if sort is not None: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if direction is not None: + value = str(direction) + if isinstance(direction, bool): + value = value.lower() + query_params.append(f"direction={quote(value, safe='')}") + if per_page is not None: + value = str(per_page) + if isinstance(per_page, bool): + value = value.lower() + query_params.append(f"per_page={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_org_repos( + self, + repository_owner: str, + *, + type_: Optional[str] = None, + sort: Optional[str] = None, + direction: Optional[str] = None, + per_page: Optional[int] = None, + page: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Lists all public repositories for an organization + + Lists all public repositories for an organization. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetOrgRepos`. + + Args: + repository_owner: Name of the repository owner. + type_: Limit results to repositories of the specified type. + sort: The property to sort the results by. + direction: Direction of sort. + per_page: Number of results per page. + page: Page number to fetch. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/orgs/{quote(str(repository_owner), safe='')}/repos" + ) + query_params = [] + if type_ is not None: + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if sort is not None: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if direction is not None: + value = str(direction) + if isinstance(direction, bool): + value = value.lower() + query_params.append(f"direction={quote(value, safe='')}") + if per_page is not None: + value = str(per_page) + if isinstance(per_page, bool): + value = value.lower() + query_params.append(f"per_page={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_user_repos( + self, + *, + visibility: Optional[str] = None, + affiliation: Optional[str] = None, + since: Optional[str] = None, + before: Optional[str] = None, + type_: Optional[str] = None, + sort: Optional[str] = None, + direction: Optional[str] = None, + per_page: Optional[int] = None, + page: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Lists all repositories for the authenticated user + + Lists all repositories (both public and private) for the authenticated + user. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetUserRepos`. + + Args: + visibility: Limit results to repositories of the specified + visibility(public/private/all). + affiliation: Limit results based on affiliation. + since: Limit results to repositories updated after a given time. + before: Limit results to repositories updated before a given time. + type_: Limit results to repositories of the specified type. + sort: The property to sort the results by. + direction: Direction of sort. + per_page: Number of results per page. + page: Page number to fetch. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/user/repos" + query_params = [] + if visibility is not None: + value = str(visibility) + if isinstance(visibility, bool): + value = value.lower() + query_params.append(f"visibility={quote(value, safe='')}") + if affiliation is not None: + value = str(affiliation) + if isinstance(affiliation, bool): + value = value.lower() + query_params.append(f"affiliation={quote(value, safe='')}") + if since is not None: + value = str(since) + if isinstance(since, bool): + value = value.lower() + query_params.append(f"since={quote(value, safe='')}") + if before is not None: + value = str(before) + if isinstance(before, bool): + value = value.lower() + query_params.append(f"before={quote(value, safe='')}") + if type_ is not None: + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if sort is not None: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if direction is not None: + value = str(direction) + if isinstance(direction, bool): + value = value.lower() + query_params.append(f"direction={quote(value, safe='')}") + if per_page is not None: + value = str(per_page) + if isinstance(per_page, bool): + value = value.lower() + query_params.append(f"per_page={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_search_issues( + self, + q: str, + *, + sort: Optional[str] = None, + order: Optional[str] = None, + per_page: Optional[int] = None, + page: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Find issues by state and keyword + + Find issues by state and keyword. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SearchIssues`. + + Args: + q: Search keywords and qualifiers. + sort: The property to sort the results by. + order: Direction of sort. + per_page: Number of results per page. + page: Page number to fetch. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/search/issues" + query_params = [] + value = str(q) + if isinstance(q, bool): + value = value.lower() + query_params.append(f"q={quote(value, safe='')}") + if sort is not None: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if order is not None: + value = str(order) + if isinstance(order, bool): + value = value.lower() + query_params.append(f"order={quote(value, safe='')}") + if per_page is not None: + value = str(per_page) + if isinstance(per_page, bool): + value = value.lower() + query_params.append(f"per_page={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("body", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def invoke_mcp_server( + self, + input: QueryRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Github MCP Server + + Github MCP Server + + Swagger operation ID: `InvokeMCPServer`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/mcp" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) diff --git a/src/azure/connectors/aio/googlecalendar.py b/src/azure/connectors/aio/googlecalendar.py new file mode 100644 index 0000000..7cb939c --- /dev/null +++ b/src/azure/connectors/aio/googlecalendar.py @@ -0,0 +1,676 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# GooglecalendarClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.googlecalendar import ( + CalendarEventChangedList, + CalendarEventList, + CalendarList, + CalendarListEntry, + ObjectEntity, + PatchEvent, + RequestEvent, + ResponseEvent, + ResponseEventWithActionType, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "GooglecalendarClient", + "CalendarEventChangedList", + "CalendarEventList", + "CalendarList", + "CalendarListEntry", + "ObjectEntity", + "PatchEvent", + "RequestEvent", + "ResponseEvent", + "ResponseEventWithActionType", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class GooglecalendarClient(ConnectorClientBase): + """Typed client for googlecalendar connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a GooglecalendarClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "googlecalendar" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_calendars( + self, + *, + min_access_role: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List calendars + + This operation is used to list all calendars in your Google account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListCalendars`. + + Args: + min_access_role: The minimum access role users must have to view + calendars. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/users/me/calendarList" + query_params = [] + if min_access_role is not None: + value = str(min_access_role) + if isinstance(min_access_role, bool): + value = value.lower() + query_params.append(f"minAccessRole={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_events( + self, + calendar_id: str, + *, + time_min: Optional[str] = None, + time_max: Optional[str] = None, + q: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List the events on a calendar + + This operation is used to return the first page of arbitrarily ordered + events on the selected calendar. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListEvents`. + + Args: + calendar_id: Unique ID of the calendar to fetch events from. + time_min: Time format: yyyy-MM-ddTHH:mm:ss.fffZ + (2016-07-20T08:00:00.000Z). + time_max: Time format: yyyy-MM-ddTHH:mm:ss.fffZ + (2016-07-20T09:00:59.000Z). + q: Text search terms to find events that match these terms in any + fields. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/calendars/{quote(str(calendar_id), safe='')}/events" + ) + query_params = [] + if time_min is not None: + value = str(time_min) + if isinstance(time_min, bool): + value = value.lower() + query_params.append(f"timeMin={quote(value, safe='')}") + if time_max is not None: + value = str(time_max) + if isinstance(time_max, bool): + value = value.lower() + query_params.append(f"timeMax={quote(value, safe='')}") + if q is not None: + value = str(q) + if isinstance(q, bool): + value = value.lower() + query_params.append(f"q={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_event( + self, + input: RequestEvent | Mapping[str, Any], + calendar_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create an event + + This operation is used to create an event on a specific calendar. + + Swagger operation ID: `CreateEvent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + calendar_id: Unique ID of the calendar to fetch events from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/calendars/{quote(str(calendar_id), safe='')}/events" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_event( + self, + calendar_id: str, + event_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get an event + + This operation is used to get the details of a specific event from a + calendar. + + Swagger operation ID: `GetEvent`. + + Args: + calendar_id: Unique ID of the calendar to fetch events from. + event_id: Unique ID of the event to get. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/calendars" + f"/{quote(str(calendar_id), safe='')}" + f"/events" + f"/{quote(str(event_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_event( + self, + calendar_id: str, + event_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete an event + + This operation is used to delete an event from a calendar. + + Swagger operation ID: `DeleteEvent`. + + Args: + calendar_id: Unique ID of the calendar to fetch events from. + event_id: Unique ID of the event to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/calendars" + f"/{quote(str(calendar_id), safe='')}" + f"/events" + f"/{quote(str(event_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_event( + self, + input: PatchEvent | Mapping[str, Any], + calendar_id: str, + event_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update an event + + This operation is used to update an existing event on a calendar. + + Swagger operation ID: `UpdateEvent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + calendar_id: Unique ID of the calendar to fetch events from. + event_id: Unique ID of the event to get. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/calendars" + f"/{quote(str(calendar_id), safe='')}" + f"/events" + f"/{quote(str(event_id), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_writable_calendars( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List writable calendars + + This operation is used to list all calendars in your Google account + that you can write to. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListWritableCalendars`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/users/me/calendarList/1" + query_params = [] + query_params.append("minAccessRole=" + quote("writer", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/googledrive.py b/src/azure/connectors/aio/googledrive.py new file mode 100644 index 0000000..863b416 --- /dev/null +++ b/src/azure/connectors/aio/googledrive.py @@ -0,0 +1,934 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# GoogledriveClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.googledrive import ( + BlobDataSetsMetadata, + BlobMetadata, + DataSet, + DataSetsList, + DataSetsMetadata, + Item, + ItemsList, + ObjectEntity, + PassThroughNativeQuery, + Procedure, + Table, + TableCapabilitiesMetadata, + TableFilterRestrictionsMetadata, + TableMetadata, + TableSelectRestrictionsMetadata, + TableSortRestrictionsMetadata, + TablesList, + TabularDataSetsMetadata, +) + +__all__ = [ + "GoogledriveClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "Item", + "ItemsList", + "ObjectEntity", + "PassThroughNativeQuery", + "Procedure", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TablesList", + "TabularDataSetsMetadata", +] + + +# Type Definitions + +# Client Class + +class GoogledriveClient(ConnectorClientBase): + """Typed client for googledrive connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a GoogledriveClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "googledrive" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def get_file_metadata( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file metadata using id + + Retrieves file metadata from Google Drive using id + + Swagger operation ID: `GetFileMetadata`. + + Args: + id: Specify the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_file( + self, + input: bytes, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update file + + Updates a file in Google Drive + + Swagger operation ID: `UpdateFile`. + + Args: + input: The binary request body. + id: Specify the file to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PUT", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_file( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete file + + Deletes a file from Google Drive + + Swagger operation ID: `DeleteFile`. + + Args: + id: Specify the file to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_file_metadata_by_path( + self, + path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file metadata using path + + Retrieves file metadata from Google Drive using path + + Swagger operation ID: `GetFileMetadataByPath`. + + Args: + path: Path of the file in Google Drive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/GetFileByPath" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_file_content_by_path( + self, + path: str, + *, + infer_content_type: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file content using path + + Retrieves file content from Google Drive using path + + Swagger operation ID: `GetFileContentByPath`. + + Args: + path: Path of the file in Google Drive. + infer_content_type: Infer content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/GetFileContentByPath" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def get_file_content( + self, + id: str, + *, + infer_content_type: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file content using id + + Retrieves file content from Google Drive using id + + Swagger operation ID: `GetFileContent`. + + Args: + id: Unique identifier of the file to retrieve in Google Drive. + infer_content_type: Infer content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/content" + ) + query_params = [] + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def copy_file( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Copy file + + Copies a file on Google Drive + + Swagger operation ID: `CopyFile`. + + Args: + source: Url to source file. + destination: Destination file path in Google Drive, including + target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/copyFile" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_folder( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List files in folder + + List files in a Google Drive folder + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListFolder`. + + Args: + id: Specify the folder in Google Drive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/folders" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_root_folder( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List files in root folder + + Lists files in the Google Drive root folder + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListRootFolder`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/folders" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_file( + self, + input: bytes, + folder_id: str, + name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create file + + Uploads a file to a Google Drive folder selected by its identifier + + Swagger operation ID: `CreateFileV2`. + + Args: + input: The binary request body. + folder_id: Folder to upload the file to Google Drive. + name: Name of the file to create in Google Drive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/v2/files" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(folder_id) + if isinstance(folder_id, bool): + value = value.lower() + query_params.append(f"folderId={quote(value, safe='')}") + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def extract_folder( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Extract archive to folder + + Extracts an archive file into a folder in Google Drive (example: .zip) + + Swagger operation ID: `ExtractFolderV2`. + + Args: + source: Path to the archive file. + destination: Path in Google Drive to extract the archive contents. + overwrite: Overwrites the destination files if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/extractFolderV2" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/googletasks.py b/src/azure/connectors/aio/googletasks.py new file mode 100644 index 0000000..608d6af --- /dev/null +++ b/src/azure/connectors/aio/googletasks.py @@ -0,0 +1,479 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# GoogletasksClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.googletasks import ( + TaskCreate, + TaskList, + TaskListCreate, + TaskListEntry, + TaskListList, + TaskObject, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "GoogletasksClient", + "TaskCreate", + "TaskList", + "TaskListCreate", + "TaskListEntry", + "TaskListList", + "TaskObject", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class GoogletasksClient(ConnectorClientBase): + """Typed client for googletasks connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a GoogletasksClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "googletasks" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_task_lists( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List task lists + + List all task lists. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTaskLists`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/users/@me/lists" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_task_list( + self, + input: TaskListCreate | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a task list + + Creates a new task list. + + Swagger operation ID: `CreateTaskList`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/users/@me/lists" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tasks( + self, + task_list_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Lists the tasks for a task list + + Lists the tasks for a specific task list. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTasks`. + + Args: + task_list_id: The id of the task list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(task_list_id), safe='')}/tasks" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_task( + self, + input: TaskCreate | Mapping[str, Any], + task_list_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a task in a task list + + Create a task in a specific task list. + + Swagger operation ID: `CreateTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + task_list_id: The id of the task list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(task_list_id), safe='')}/tasks" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def list_task( + self, + task_list_id: str, + task_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a task from a task list + + Get specific task from the specified task list. + + Swagger operation ID: `ListTask`. + + Args: + task_list_id: The id of the task list. + task_id: The id of the task. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists" + f"/{quote(str(task_list_id), safe='')}" + f"/tasks" + f"/{quote(str(task_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/impexium.py b/src/azure/connectors/aio/impexium.py new file mode 100644 index 0000000..4b021fb --- /dev/null +++ b/src/azure/connectors/aio/impexium.py @@ -0,0 +1,7673 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# ImpexiumClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.impexium import ( + AbandonedCheckoutData, + ActivityData, + AddActivityInput, + AddCategoriesForAnIndividualInput, + AddCategoriesForAnOrganizationInput, + AddEmailToIndividualInput, + AddExamScoresInput, + AddIndividualInput, + AddOrUpdateAListOfCustomFieldsPerIndividualInput, + AddOrUpdateAListOfCustomFieldsPerOrganizationInput, + AddOrganizationInput, + AddRelationshipToIndividualInput, + AddToCommitteeResponse, + AddWebLinkForIndividualInput, + AddWebLinkForOrganizationInput, + AddressSaveData, + AwardData, + AwardNominationData, + AwardRecipientIndividualData, + AwardRecipientOrganizationData, + AwardsGetIndividualAwardRecipientsResponse, + AwardsGetOrganizationAwardRecipientsResponse, + BaseNoteData, + CertificationData, + CommitteeData, + CommitteeMemberCreateData, + CommitteeMemberData, + CommitteeMemberPayload, + CommitteeMemberUpdateData, + CommitteeNomineeData, + CommitteeNomineeSaveData, + CommitteePositionData, + ContactData, + CountryData, + CourseAttendeeData, + CustomFieldData, + CustomFieldResultData, + CustomFieldValueData, + CustomerAddressUpdatedPayload, + CustomerCustomFieldValuePayload, + CustomerMergedPayload, + CustomerPhoneUpdatedPayload, + CustomerRelationshipUpdatedPayload, + CustomerRequestPayload, + DeleteAnIndividualWebLinkInput, + DeleteAnOrganizationWebLinkInput, + EducationCreditData, + EmailData, + EmailPayload, + EventData, + EventRegistrationSubstitutedPayload, + ExamData, + ExamScoreData, + ExamScoreResultData, + ExhibitData, + ExhibitorData, + FindCustomerPhoneResponse, + FindIndividualIdOrEmailResponse, + FindMembersByNameResponse, + FindMembersOrIndividualsByFirstAndLastNameResponse, + FindMembersOrIndividualsByNameResponse, + GetAListOfAllServicesOfAnOrganizationResponse, + GetAListOfLicensesResponse, + GetAbandonedCheckoutsResponse, + GetAllCommitteesResponse, + GetAllEventRegistrationsInformationForAnIndividualResponse, + GetAllEventsResponse, + GetAllOpenOrdersForAnIndividualResponse, + GetAllStatesByCountryResponse, + GetCommitteeInformationForAnIndividualResponse, + GetCourseAttendeesResponse, + GetIndividualsActiveSubscriptionsResponse, + GetIndividualsRelationshipsResponse, + GetListOfActiveCertificationsForAnIndividualResponse, + GetListOfActiveCertificationsForAnOrganizationResponse, + GetNomineesByCommitteeResponse, + GetOrganizationsActiveSubscriptionsResponse, + GetOrganizationsRelationshipsResponse, + GetPositionsByCommitteeResponse, + GetPurchasesForAnIndividualResponse, + GetSubCommitteesResponse, + GetUpcomingEventsResponse, + IndividualData, + IndividualLookupBasicData, + IndividualPayload, + IndividualRequestToBeForgottenPayload, + IndividualsLookupByNameResponse, + LicenseData, + ListAllAwardsResponse, + ListAllCountriesResponse, + ListAllEventCancellationsByEventResponse, + ListAllExhibitorsResponse, + ListAllExhibitsResponse, + ListAllIndividualsResponse, + ListAllOpenCustomerRequestResponse, + ListCompletedUserTasksByUserIdOrEmailResponse, + ListOfAllIndividualMembersResponse, + ListOfAllOrganizationMembersResponse, + ListOfCustomerRelationshipsResponse, + ListOfExamsResponse, + ListPendingUserTasksByUserIdOrEmailResponse, + ListRegistrantsResponse, + MarkRegistrantAttendedInput, + MembershipData, + MembershipTypeTerminatedPayload, + NoteData, + NotificationData, + OrganizationData, + OrganizationLookupBasicData, + OrganizationLookupByNameResponse, + PayableOrderData, + PhoneDataSet, + PhoneSaveData, + ProductPurchasePayload, + PurchaseCancelledPayload, + PurchasedItemData, + RegisterAnIndividualForAFreeSessionInput, + RegistrantCancellationData, + RegistrantData, + RegistrationData, + RelationshipData, + RelationshipTypeData, + RequestData, + RequestSaveData, + RequestUpdateData, + SaveCategoryBasicData, + SaveRelationshipForOrganizationInput, + ServiceData, + SessionRegistrationData, + StateProvinceData, + SubscriptionData, + TaskData, + TaskSaveData, + UpdateAnIndividualEmailInput, + UpdateAwardNominationData, + UpdateOrganizationInput, + UserTaskData, + WhenCommitteeMemberUpdatedInput, + WhenCustomerAddressUpdatedInput, + WhenCustomerCustomFieldValueUpdatedInput, + WhenCustomerIsMergedInput, + WhenCustomerPhoneUpdatedInput, + WhenCustomerRelationshipUpdatedInput, + WhenEmailUpdatedInput, + WhenEventRegistrationSubstitutedInput, + WhenIndividualCreatedInput, + WhenIndividualDeletedInput, + WhenIndividualRequestForgottenInput, + WhenMembershipTerminatedInput, + WhenProductPurchasedInput, + WhenPurchaseCancelledInput, + WhenPurchasePaidInput, + WhenRequestUpdatedInput, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "ImpexiumClient", + "AbandonedCheckoutData", + "ActivityData", + "AddActivityInput", + "AddCategoriesForAnIndividualInput", + "AddCategoriesForAnOrganizationInput", + "AddEmailToIndividualInput", + "AddExamScoresInput", + "AddIndividualInput", + "AddOrUpdateAListOfCustomFieldsPerIndividualInput", + "AddOrUpdateAListOfCustomFieldsPerOrganizationInput", + "AddOrganizationInput", + "AddRelationshipToIndividualInput", + "AddToCommitteeResponse", + "AddWebLinkForIndividualInput", + "AddWebLinkForOrganizationInput", + "AddressSaveData", + "AwardData", + "AwardNominationData", + "AwardRecipientIndividualData", + "AwardRecipientOrganizationData", + "AwardsGetIndividualAwardRecipientsResponse", + "AwardsGetOrganizationAwardRecipientsResponse", + "BaseNoteData", + "CertificationData", + "CommitteeData", + "CommitteeMemberCreateData", + "CommitteeMemberData", + "CommitteeMemberPayload", + "CommitteeMemberUpdateData", + "CommitteeNomineeData", + "CommitteeNomineeSaveData", + "CommitteePositionData", + "ContactData", + "CountryData", + "CourseAttendeeData", + "CustomFieldData", + "CustomFieldResultData", + "CustomFieldValueData", + "CustomerAddressUpdatedPayload", + "CustomerCustomFieldValuePayload", + "CustomerMergedPayload", + "CustomerPhoneUpdatedPayload", + "CustomerRelationshipUpdatedPayload", + "CustomerRequestPayload", + "DeleteAnIndividualWebLinkInput", + "DeleteAnOrganizationWebLinkInput", + "EducationCreditData", + "EmailData", + "EmailPayload", + "EventData", + "EventRegistrationSubstitutedPayload", + "ExamData", + "ExamScoreData", + "ExamScoreResultData", + "ExhibitData", + "ExhibitorData", + "FindCustomerPhoneResponse", + "FindIndividualIdOrEmailResponse", + "FindMembersByNameResponse", + "FindMembersOrIndividualsByFirstAndLastNameResponse", + "FindMembersOrIndividualsByNameResponse", + "GetAListOfAllServicesOfAnOrganizationResponse", + "GetAListOfLicensesResponse", + "GetAbandonedCheckoutsResponse", + "GetAllCommitteesResponse", + "GetAllEventRegistrationsInformationForAnIndividualResponse", + "GetAllEventsResponse", + "GetAllOpenOrdersForAnIndividualResponse", + "GetAllStatesByCountryResponse", + "GetCommitteeInformationForAnIndividualResponse", + "GetCourseAttendeesResponse", + "GetIndividualsActiveSubscriptionsResponse", + "GetIndividualsRelationshipsResponse", + "GetListOfActiveCertificationsForAnIndividualResponse", + "GetListOfActiveCertificationsForAnOrganizationResponse", + "GetNomineesByCommitteeResponse", + "GetOrganizationsActiveSubscriptionsResponse", + "GetOrganizationsRelationshipsResponse", + "GetPositionsByCommitteeResponse", + "GetPurchasesForAnIndividualResponse", + "GetSubCommitteesResponse", + "GetUpcomingEventsResponse", + "IndividualData", + "IndividualLookupBasicData", + "IndividualPayload", + "IndividualRequestToBeForgottenPayload", + "IndividualsLookupByNameResponse", + "LicenseData", + "ListAllAwardsResponse", + "ListAllCountriesResponse", + "ListAllEventCancellationsByEventResponse", + "ListAllExhibitorsResponse", + "ListAllExhibitsResponse", + "ListAllIndividualsResponse", + "ListAllOpenCustomerRequestResponse", + "ListCompletedUserTasksByUserIdOrEmailResponse", + "ListOfAllIndividualMembersResponse", + "ListOfAllOrganizationMembersResponse", + "ListOfCustomerRelationshipsResponse", + "ListOfExamsResponse", + "ListPendingUserTasksByUserIdOrEmailResponse", + "ListRegistrantsResponse", + "MarkRegistrantAttendedInput", + "MembershipData", + "MembershipTypeTerminatedPayload", + "NoteData", + "NotificationData", + "OrganizationData", + "OrganizationLookupBasicData", + "OrganizationLookupByNameResponse", + "PayableOrderData", + "PhoneDataSet", + "PhoneSaveData", + "ProductPurchasePayload", + "PurchaseCancelledPayload", + "PurchasedItemData", + "RegisterAnIndividualForAFreeSessionInput", + "RegistrantCancellationData", + "RegistrantData", + "RegistrationData", + "RelationshipData", + "RelationshipTypeData", + "RequestData", + "RequestSaveData", + "RequestUpdateData", + "SaveCategoryBasicData", + "SaveRelationshipForOrganizationInput", + "ServiceData", + "SessionRegistrationData", + "StateProvinceData", + "SubscriptionData", + "TaskData", + "TaskSaveData", + "UpdateAnIndividualEmailInput", + "UpdateAwardNominationData", + "UpdateOrganizationInput", + "UserTaskData", + "WhenCommitteeMemberUpdatedInput", + "WhenCustomerAddressUpdatedInput", + "WhenCustomerCustomFieldValueUpdatedInput", + "WhenCustomerIsMergedInput", + "WhenCustomerPhoneUpdatedInput", + "WhenCustomerRelationshipUpdatedInput", + "WhenEmailUpdatedInput", + "WhenEventRegistrationSubstitutedInput", + "WhenIndividualCreatedInput", + "WhenIndividualDeletedInput", + "WhenIndividualRequestForgottenInput", + "WhenMembershipTerminatedInput", + "WhenProductPurchasedInput", + "WhenPurchaseCancelledInput", + "WhenPurchasePaidInput", + "WhenRequestUpdatedInput", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class ImpexiumClient(ConnectorClientBase): + """Typed client for impexium connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a ImpexiumClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "impexium" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def get_abandoned_checkouts( + self, + page_number: int, + abandoned_from: str, + *, + product_code: Optional[str] = None, + customer_record_number: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Abandoned Checkouts + + Get Abandoned Checkouts + + Swagger operation ID: `GetAbandonedCheckouts`. + + Args: + page_number: Page Number. + abandoned_from: Abandoned From. + product_code: Product Code. + customer_record_number: Customer Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Shopping" + f"/AbandonedCheckOuts" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + value = str(abandoned_from) + if isinstance(abandoned_from, bool): + value = value.lower() + query_params.append(f"abandonedFrom={quote(value, safe='')}") + if product_code is not None: + value = str(product_code) + if isinstance(product_code, bool): + value = value.lower() + query_params.append(f"productCode={quote(value, safe='')}") + if customer_record_number is not None: + value = str(customer_record_number) + if isinstance(customer_record_number, bool): + value = value.lower() + query_params.append(f"customerRecordNumber={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_all_exhibitors( + self, + exhibit_code: str, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List All Exhibitors + + List All Exhibitors + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `List-All-Exhibitors`. + + Args: + exhibit_code: Exhibit Code. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Exhibits" + f"/{quote(str(exhibit_code), safe='')}" + f"/Exhibitors" + f"/{quote(str(page_number), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_of_exams( + self, + page_number: int, + *, + code: Optional[str] = None, + category_name: Optional[str] = None, + is_public: Optional[bool] = None, + changed_since: Optional[str] = None, + tag: Optional[str] = None, + include_prices: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List of Exams + + List of Exams + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `List-of-Exams`. + + Args: + page_number: The page number of the result set. + code: A specific Exam code. + category_name: A specific Exam Category name. + is_public: When set to true, only public Exams will be displayed; + If it's not specified will display all. + changed_since: When a date (yyyy-MM-ddTHH:mm:ss (UTC)) is + specified, only Exams modified after this date will be + displayed. + tag: Tag. + include_prices: When set to true, add the active price list for + every product. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Products/Exams/{quote(str(page_number), safe='')}" + ) + query_params = [] + if code is not None: + value = str(code) + if isinstance(code, bool): + value = value.lower() + query_params.append(f"Code={quote(value, safe='')}") + if category_name is not None: + value = str(category_name) + if isinstance(category_name, bool): + value = value.lower() + query_params.append(f"categoryName={quote(value, safe='')}") + if is_public is not None: + value = str(is_public) + if isinstance(is_public, bool): + value = value.lower() + query_params.append(f"isPublic={quote(value, safe='')}") + if changed_since is not None: + value = str(changed_since) + if isinstance(changed_since, bool): + value = value.lower() + query_params.append(f"changedSince={quote(value, safe='')}") + if tag is not None: + value = str(tag) + if isinstance(tag, bool): + value = value.lower() + query_params.append(f"Tag={quote(value, safe='')}") + if include_prices is not None: + value = str(include_prices) + if isinstance(include_prices, bool): + value = value.lower() + query_params.append(f"includePrices={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_registrants( + self, + event_code: str, + page_number: int, + *, + session_code: Optional[str] = None, + include_details: Optional[bool] = None, + registered_since: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Registrants + + List Registrants + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `List-Registrants`. + + Args: + event_code: Event Code. + page_number: Page Number. + session_code: Session Code. + include_details: Include Details. + registered_since: Registered Since. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Events" + f"/{quote(str(event_code), safe='')}" + f"/Registrations" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if session_code is not None: + value = str(session_code) + if isinstance(session_code, bool): + value = value.lower() + query_params.append(f"sessionCode={quote(value, safe='')}") + if include_details is not None: + value = str(include_details) + if isinstance(include_details, bool): + value = value.lower() + query_params.append(f"includeDetails={quote(value, safe='')}") + if registered_since is not None: + value = str(registered_since) + if isinstance(registered_since, bool): + value = value.lower() + query_params.append(f"registeredSince={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_course_attendees( + self, + code: str, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Course Attendees + + Get Course Attendees + + Swagger operation ID: `Get-Course-Attendees`. + + Args: + code: Course Code. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Courses" + f"/{quote(str(code), safe='')}" + f"/Attendees" + f"/{quote(str(page_number), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_exam_scores( + self, + input: AddExamScoresInput, + exam_code: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Exam Scores + + Add Exam Scores + + Swagger operation ID: `Add-Exam-Scores`. + + Args: + input: The request body. + exam_code: Exam Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Exams/{quote(str(exam_code), safe='')}/Scores" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def find_members_by_name( + self, + name: str, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Find Members by Name + + Find Members by Name + + Swagger operation ID: `Find-Members-by-Name`. + + Args: + name: Individual or Organization name. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Customers" + f"/Members" + f"/FindByName" + f"/{quote(str(name), safe='')}" + f"/{quote(str(page_number), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_purchases_for_an_individual( + self, + id_or_record_number: str, + page_number: int, + *, + product_code: Optional[str] = None, + purchased_since: Optional[str] = None, + product_category_code: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Purchases for an Individual + + Get Purchases for an Individual + + Swagger operation ID: `Get-Purchases-for-an-Individual`. + + Args: + id_or_record_number: Individual ID or Record Number. + page_number: Page Number. + product_code: Product Code. + purchased_since: yyyy-MM-ddTHH:mm:ss. + product_category_code: Product Category Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Purchases" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if product_code is not None: + value = str(product_code) + if isinstance(product_code, bool): + value = value.lower() + query_params.append(f"productCode={quote(value, safe='')}") + if purchased_since is not None: + value = str(purchased_since) + if isinstance(purchased_since, bool): + value = value.lower() + query_params.append(f"purchasedSince={quote(value, safe='')}") + if product_category_code is not None: + value = str(product_category_code) + if isinstance(product_category_code, bool): + value = value.lower() + query_params.append(f"productCategoryCode={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_or_update_a_list_of_custom_fields_per_organization( + self, + input: AddOrUpdateAListOfCustomFieldsPerOrganizationInput, + id_or_record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add or Update a List of Custom Fields Per Organization + + Add or Update a List of Custom Fields Per Organization + + Swagger operation ID: + `Add-or-Update-a-List-of-Custom-Fields-Per-Organization`. + + Args: + input: The request body. + id_or_record_number: Organization ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/{quote(str(id_or_record_number), safe='')}" + f"/CustomFieldsList" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_nominee( + self, + input: CommitteeNomineeSaveData | Mapping[str, Any], + code: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Nominee + + Add Nominee + + Swagger operation ID: `Add-Nominee`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + code: Committee Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Committees/{quote(str(code), safe='')}/Nominations" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_individual_custom_field_values( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Individual Custom Field Values + + Get Individual Custom Field Values + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Get-Individual-Custom-Field-Values`. + + Args: + id: Individual ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Individuals/{quote(str(id), safe='')}/CustomFields" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_custom_field_value( + self, + input: CustomFieldData | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update Individual Custom Field Values + + Update Individual Custom Field Values. + + Swagger operation ID: `Update-custom-field-value`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Customer ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Individuals/{quote(str(id), safe='')}/CustomFields" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_all_event_cancellations_by_event( + self, + event_code: str, + page_number: int, + *, + include_details: Optional[bool] = None, + cancelled_since: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List All Event Cancellations by Event + + List All Event Cancellations by Event + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `List-All-Event-Cancellations-by-Event`. + + Args: + event_code: A valid Event Code. + page_number: Page Number. + include_details: Indicates if additional information should be + returned. + cancelled_since: The initial date to search cancellations + (yyyy-MM-ddTHH:mm:ss). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Events" + f"/{quote(str(event_code), safe='')}" + f"/Cancellations" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if include_details is not None: + value = str(include_details) + if isinstance(include_details, bool): + value = value.lower() + query_params.append(f"includeDetails={quote(value, safe='')}") + if cancelled_since is not None: + value = str(cancelled_since) + if isinstance(cancelled_since, bool): + value = value.lower() + query_params.append(f"cancelledSince={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_all_open_orders_for_an_individual( + self, + id_or_record_number: str, + page_number: int, + *, + include_line_items: Optional[bool] = None, + from_date: Optional[str] = None, + to_date: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get All Open Orders for an Individual + + Get All Open Orders for an Individual + + Swagger operation ID: `Get-All-Open-Orders-for-an-Individual`. + + Args: + id_or_record_number: Individual ID or Record Number. + page_number: Page Number. + include_line_items: Include Line Items. + from_date: From Date. + to_date: To Date. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Orders" + f"/Open" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if include_line_items is not None: + value = str(include_line_items) + if isinstance(include_line_items, bool): + value = value.lower() + query_params.append(f"includeLineItems={quote(value, safe='')}") + if from_date is not None: + value = str(from_date) + if isinstance(from_date, bool): + value = value.lower() + query_params.append(f"fromDate={quote(value, safe='')}") + if to_date is not None: + value = str(to_date) + if isinstance(to_date, bool): + value = value.lower() + query_params.append(f"toDate={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_completed_user_tasks_by_user_id_or_email( + self, + user_id_or_email: str, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Completed User Tasks by User ID or Email + + List Completed User Tasks by User ID or Email + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `List-Completed-User-Tasks-by-User-ID-or-Email`. + + Args: + user_id_or_email: A valid User ID or Email. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/tasks" + f"/Users" + f"/{quote(str(user_id_or_email), safe='')}" + f"/Completed" + f"/{quote(str(page_number), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_pending_user_tasks_by_user_id_or_email( + self, + user_id_or_email: str, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Pending User Tasks by User ID or Email + + List Pending User Tasks by User ID or Email + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `List-Pending-User-Tasks-by-User-ID-or-Email`. + + Args: + user_id_or_email: A valid User ID or Email. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/tasks" + f"/Users" + f"/{quote(str(user_id_or_email), safe='')}" + f"/Pending" + f"/{quote(str(page_number), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def add_note_to_sales_opportunity( + self, + input: BaseNoteData | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Note to Sales Opportunity + + Add Note to Sales Opportunity + + Swagger operation ID: `Add-Note-to-Sales-Opportunity`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Sales opportunity ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Sales/Opportunities/{quote(str(id), safe='')}/Notes" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_activity_to_sales_opportunity( + self, + input: ActivityData | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Activity to Sales Opportunity + + Add Activity to Sales Opportunity + + Swagger operation ID: `Add-Activity-to-Sales-Opportunity`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Opportunity ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Sales/Opportunities/{quote(str(id), safe='')}/Activities" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def update_task_by_task_number( + self, + input: TaskSaveData | Mapping[str, Any], + task_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Task by Task Number + + Update Task by Task Number + + Swagger operation ID: `Update-Task-by-Task-Number`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + task_number: A valid Task Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/tasks/{quote(str(task_number), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_all_countries( + self, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List All Countries + + List All Countries + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `List-All-Countries`. + + Args: + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Countries/All/{quote(str(page_number), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_all_states_by_country( + self, + country_id: str, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get All States by Country + + Get All States by Country + + Swagger operation ID: `Get-All-States-by-Country`. + + Args: + country_id: Country ID. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Countries" + f"/{quote(str(country_id), safe='')}" + f"/States" + f"/All" + f"/{quote(str(page_number), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_all_exhibits( + self, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List All Exhibits + + List All Exhibits + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `List-All-Exhibits`. + + Args: + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Exhibits/{quote(str(page_number), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def delete_a_category_for_an_organization( + self, + record_number: str, + category_code: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a Category for an Organization + + Delete a Category for an Organization + + Swagger operation ID: `Delete-a-Category-for-an-Organization`. + + Args: + record_number: Record Number. + category_code: Category Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/{quote(str(record_number), safe='')}" + f"/Categories" + f"/{quote(str(category_code), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_customer_request( + self, + input: RequestSaveData | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Customer Request + + Add Customer Request + + Swagger operation ID: `Add-Customer-Request`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/v1/Requests" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def update_customer_request( + self, + input: RequestUpdateData | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Customer Request + + Update Customer Request + + Swagger operation ID: `Update-Customer-Request`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/v1/Requests" + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_categories_for_an_organization( + self, + input: AddCategoriesForAnOrganizationInput, + record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Categories for an Organization + + Add Categories for an Organization + + Swagger operation ID: `Add-Categories-for-an-Organization`. + + Args: + input: The request body. + record_number: Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/{quote(str(record_number), safe='')}" + f"/Categories" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_of_customer_relationships( + self, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List of Customer Relationships + + List of Customer Relationships + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `List-of-Customer-Relationships`. + + Args: + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Customers" + f"/RelationshipTypes" + f"/{quote(str(page_number), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_all_open_customer_request( + self, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List All Open Customer Request + + List All Open Customer Request + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `List-All-Open-Customer-Request`. + + Args: + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Requests/Open/{quote(str(page_number), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_organization_inactive_memberships( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Organization Inactive Memberships + + Get Organization Inactive Memberships + + Swagger operation ID: `Get-Organization-Inactive-Memberships`. + + Args: + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/{quote(str(id), safe='')}" + f"/Memberships" + f"/Inactive" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_record_from_custom_data_table( + self, + table_name: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete Record From Custom Data Table + + Delete Record From Custom Data Table + + Swagger operation ID: `Delete-Record-From-Custom-Data-Table`. + + Args: + table_name: Custom table name. + id: ID of the record to be deleted. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/CustomData" + f"/{quote(str(table_name), safe='')}" + f"/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def update_user_task_progress_or_mark_as_completed( + self, + input: UserTaskData | Mapping[str, Any], + user_id_or_email: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update User Task Progress or Mark as Completed + + Update User Task Progress or Mark as Completed + + Swagger operation ID: `Update-User-Task-Progress-or-Mark-as-Completed`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + user_id_or_email: A valid User Id or Email. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/tasks/Users/{quote(str(user_id_or_email), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def find_members_or_individuals_by_first_name( + self, + first_name: str, + page_number: int, + *, + include_email: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Find Members (Individuals) by First Name + + Find Members (Individuals) by First Name + + Swagger operation ID: `Find-Members-or-Individuals-by-First-Name`. + + Args: + first_name: First Name. + page_number: Page Number. + include_email: Include Email Data. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/Members" + f"/FindByFirstName" + f"/{quote(str(first_name), safe='')}" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if include_email is not None: + value = str(include_email) + if isinstance(include_email, bool): + value = value.lower() + query_params.append(f"includeEmail={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def find_members_or_individuals_by_last_name( + self, + last_name: str, + page_number: int, + *, + include_email: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Find Members (Individuals) by Last Name + + Find Members (Individuals) by Last Name + + Swagger operation ID: `Find-Members-or-Individuals-by-Last-Name`. + + Args: + last_name: Last Name. + page_number: Page Number. + include_email: Include Email Data. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/Members" + f"/FindByLastName" + f"/{quote(str(last_name), safe='')}" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if include_email is not None: + value = str(include_email) + if isinstance(include_email, bool): + value = value.lower() + query_params.append(f"includeEmail={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def assign_task_to_a_user( + self, + input: UserTaskData | Mapping[str, Any], + user_id_or_email: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Create a new task or Assign Task to a User + + Create a new task or Assign Task to a User + + Swagger operation ID: `Assign-Task-to-a-User`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + user_id_or_email: A valid User Id or Email. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/tasks/Users/{quote(str(user_id_or_email), safe='')}/Task" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def delete_a_category_for_an_individual( + self, + record_number: str, + category_code: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a Category for an Individual + + Delete a Category for an Individual + + Swagger operation ID: `Delete-a-Category-for-an-Individual`. + + Args: + record_number: Record Number. + category_code: Category Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(record_number), safe='')}" + f"/Categories" + f"/{quote(str(category_code), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_notification_to_individual( + self, + input: NotificationData | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Notification to Individual + + Add Notification to Individual + + Swagger operation ID: `Add-Notification-to-Individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Individual ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Individuals/{quote(str(id), safe='')}/Notifications" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_categories_for_an_individual( + self, + input: AddCategoriesForAnIndividualInput, + record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Categories for an Individual + + Add Categories for an Individual + + Swagger operation ID: `Add-Categories-for-an-Individual`. + + Args: + input: The request body. + record_number: Individual Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(record_number), safe='')}" + f"/Categories" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_a_new_task( + self, + input: TaskSaveData | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add a New Task + + Add a New Task + + Swagger operation ID: `Add-a-New-Task`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/v1/tasks" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_of_all_organization_members( + self, + page_number: int, + *, + zip_code: Optional[str] = None, + radius: Optional[float] = None, + state_abbreviation: Optional[str] = None, + congressional_district: Optional[float] = None, + membership_type_code: Optional[str] = None, + membership_type_category: Optional[str] = None, + city: Optional[str] = None, + name: Optional[str] = None, + tag: Optional[str] = None, + latitude: Optional[float] = None, + longitude: Optional[float] = None, + domain: Optional[str] = None, + include_membership: Optional[bool] = None, + include_address: Optional[bool] = None, + include_phone: Optional[bool] = None, + include_email: Optional[bool] = None, + include_custom_fields: Optional[bool] = None, + expiring_from: Optional[str] = None, + expiring_to: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List of All Organization Members + + List of All Organization Members + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `List-of-All-Organization-Members`. + + Args: + page_number: Page Number. + zip_code: Zip Code. + radius: Radius in Miles. + state_abbreviation: State Abbreviation. + congressional_district: Congressional District. + membership_type_code: A valid code for a Membership Type. + membership_type_category: A valid Membership Type Category name. + city: City. + name: Name. + tag: Tag. + latitude: Latitude. + longitude: Longitude. + domain: Domain. + include_membership: Include Membership Data. + include_address: Include Address Data. + include_phone: Include Phone Data. + include_email: Include Email Data. + include_custom_fields: Include Custom Field Data. + expiring_from: Expire Date - From. + expiring_to: Expire Date - To. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/Members" + f"/All" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if zip_code is not None: + value = str(zip_code) + if isinstance(zip_code, bool): + value = value.lower() + query_params.append(f"zipCode={quote(value, safe='')}") + if radius is not None: + value = str(radius) + if isinstance(radius, bool): + value = value.lower() + query_params.append(f"Radius={quote(value, safe='')}") + if state_abbreviation is not None: + value = str(state_abbreviation) + if isinstance(state_abbreviation, bool): + value = value.lower() + query_params.append(f"stateAbbreviation={quote(value, safe='')}") + if congressional_district is not None: + value = str(congressional_district) + if isinstance(congressional_district, bool): + value = value.lower() + query_params.append(f"congressionalDistrict={quote(value, safe='')}") + if membership_type_code is not None: + value = str(membership_type_code) + if isinstance(membership_type_code, bool): + value = value.lower() + query_params.append(f"membershipTypeCode={quote(value, safe='')}") + if membership_type_category is not None: + value = str(membership_type_category) + if isinstance(membership_type_category, bool): + value = value.lower() + query_params.append(f"membershipTypeCategory={quote(value, safe='')}") + if city is not None: + value = str(city) + if isinstance(city, bool): + value = value.lower() + query_params.append(f"City={quote(value, safe='')}") + if name is not None: + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"Name={quote(value, safe='')}") + if tag is not None: + value = str(tag) + if isinstance(tag, bool): + value = value.lower() + query_params.append(f"Tag={quote(value, safe='')}") + if latitude is not None: + value = str(latitude) + if isinstance(latitude, bool): + value = value.lower() + query_params.append(f"Latitude={quote(value, safe='')}") + if longitude is not None: + value = str(longitude) + if isinstance(longitude, bool): + value = value.lower() + query_params.append(f"Longitude={quote(value, safe='')}") + if domain is not None: + value = str(domain) + if isinstance(domain, bool): + value = value.lower() + query_params.append(f"Domain={quote(value, safe='')}") + if include_membership is not None: + value = str(include_membership) + if isinstance(include_membership, bool): + value = value.lower() + query_params.append(f"includeMembership={quote(value, safe='')}") + if include_address is not None: + value = str(include_address) + if isinstance(include_address, bool): + value = value.lower() + query_params.append(f"includeAddress={quote(value, safe='')}") + if include_phone is not None: + value = str(include_phone) + if isinstance(include_phone, bool): + value = value.lower() + query_params.append(f"includePhone={quote(value, safe='')}") + if include_email is not None: + value = str(include_email) + if isinstance(include_email, bool): + value = value.lower() + query_params.append(f"includeEmail={quote(value, safe='')}") + if include_custom_fields is not None: + value = str(include_custom_fields) + if isinstance(include_custom_fields, bool): + value = value.lower() + query_params.append(f"includeCustomFields={quote(value, safe='')}") + if expiring_from is not None: + value = str(expiring_from) + if isinstance(expiring_from, bool): + value = value.lower() + query_params.append(f"expiringFrom={quote(value, safe='')}") + if expiring_to is not None: + value = str(expiring_to) + if isinstance(expiring_to, bool): + value = value.lower() + query_params.append(f"expiringTo={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_of_all_individual_members( + self, + page_number: int, + *, + zip_code: Optional[str] = None, + radius: Optional[float] = None, + membership_type_code: Optional[str] = None, + membership_type_category: Optional[str] = None, + tag: Optional[str] = None, + include_membership: Optional[bool] = None, + include_address: Optional[bool] = None, + include_phone: Optional[bool] = None, + include_email: Optional[bool] = None, + include_link: Optional[bool] = None, + include_custom_fields: Optional[bool] = None, + include_categories: Optional[bool] = None, + include_membership_renewal_url: Optional[bool] = None, + expiring_from: Optional[str] = None, + expiring_to: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List of All Individual Members + + List of All Individual Members + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `List-of-All-Individual-Members`. + + Args: + page_number: Page Number. + zip_code: Zip Code. + radius: Radius in Miles. + membership_type_code: A valid code for a Membership Type. + membership_type_category: A valid Membership Type Category name. + tag: Tag. + include_membership: Include Membership Data. + include_address: Include Address Data. + include_phone: Include Phone Data. + include_email: Include Email Data. + include_link: Include Link Data. + include_custom_fields: Include Custom Field Data. + include_categories: Include Categories Data. + include_membership_renewal_url: Include Membership Renewal URLs. + expiring_from: Expire Date - From. + expiring_to: Expire Date - To. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/Members" + f"/All" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if zip_code is not None: + value = str(zip_code) + if isinstance(zip_code, bool): + value = value.lower() + query_params.append(f"zipCode={quote(value, safe='')}") + if radius is not None: + value = str(radius) + if isinstance(radius, bool): + value = value.lower() + query_params.append(f"Radius={quote(value, safe='')}") + if membership_type_code is not None: + value = str(membership_type_code) + if isinstance(membership_type_code, bool): + value = value.lower() + query_params.append(f"membershipTypeCode={quote(value, safe='')}") + if membership_type_category is not None: + value = str(membership_type_category) + if isinstance(membership_type_category, bool): + value = value.lower() + query_params.append(f"membershipTypeCategory={quote(value, safe='')}") + if tag is not None: + value = str(tag) + if isinstance(tag, bool): + value = value.lower() + query_params.append(f"Tag={quote(value, safe='')}") + if include_membership is not None: + value = str(include_membership) + if isinstance(include_membership, bool): + value = value.lower() + query_params.append(f"includeMembership={quote(value, safe='')}") + if include_address is not None: + value = str(include_address) + if isinstance(include_address, bool): + value = value.lower() + query_params.append(f"includeAddress={quote(value, safe='')}") + if include_phone is not None: + value = str(include_phone) + if isinstance(include_phone, bool): + value = value.lower() + query_params.append(f"includePhone={quote(value, safe='')}") + if include_email is not None: + value = str(include_email) + if isinstance(include_email, bool): + value = value.lower() + query_params.append(f"includeEmail={quote(value, safe='')}") + if include_link is not None: + value = str(include_link) + if isinstance(include_link, bool): + value = value.lower() + query_params.append(f"includeLink={quote(value, safe='')}") + if include_custom_fields is not None: + value = str(include_custom_fields) + if isinstance(include_custom_fields, bool): + value = value.lower() + query_params.append(f"includeCustomFields={quote(value, safe='')}") + if include_categories is not None: + value = str(include_categories) + if isinstance(include_categories, bool): + value = value.lower() + query_params.append(f"includeCategories={quote(value, safe='')}") + if include_membership_renewal_url is not None: + value = str(include_membership_renewal_url) + if isinstance(include_membership_renewal_url, bool): + value = value.lower() + query_params.append(f"includeMembershipRenewalUrl={quote(value, safe='')}") + if expiring_from is not None: + value = str(expiring_from) + if isinstance(expiring_from, bool): + value = value.lower() + query_params.append(f"expiringFrom={quote(value, safe='')}") + if expiring_to is not None: + value = str(expiring_to) + if isinstance(expiring_to, bool): + value = value.lower() + query_params.append(f"expiringTo={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_list_of_active_certifications_for_an_organization( + self, + id_or_record_number: str, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get List of Active Certifications for an Organization + + Get List of Active Certifications for an Organization + + Swagger operation ID: + `Get-List-of-Active-Certifications-for-an-Organization`. + + Args: + id_or_record_number: Organization ID or Record Number. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Certifications" + f"/{quote(str(page_number), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_list_of_active_certifications_for_an_individual( + self, + id_or_record_number: str, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get List of Active Certifications for an Individual + + Get List of Active Certifications for an Individual + + Swagger operation ID: + `Get-List-of-Active-Certifications-for-an-Individual`. + + Args: + id_or_record_number: Individual ID or Record Number. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Certifications" + f"/{quote(str(page_number), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_individual_inactive_memberships( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Individual Inactive Memberships + + Get Individual Inactive Memberships + + Swagger operation ID: `Get-Individual-Inactive-Memberships`. + + Args: + id: Individual ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id), safe='')}" + f"/Memberships" + f"/Inactive" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_activity_to_organization( + self, + input: ActivityData | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Activity to Organization + + Add Activity to Organization + + Swagger operation ID: `Add-Activity-to-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Organizations/{quote(str(id), safe='')}/Activities" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def register_an_individual_for_a_free_session( + self, + input: RegisterAnIndividualForAFreeSessionInput, + event_code: str, + customer_id_or_record_number: str, + *, + registration_number: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Register an Individual for a Free Session + + Register an Individual for a Free Session + + Swagger operation ID: `Register-an-Individual-for-a-Free-Session`. + + Args: + input: The request body. + event_code: A Valid Event Code. + customer_id_or_record_number: A Valid Individual ID or Record + Number. + registration_number: A Valid Registration Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Events" + f"/{quote(str(event_code), safe='')}" + f"/Sessions" + f"/Register" + f"/{quote(str(customer_id_or_record_number), safe='')}" + ) + query_params = [] + if registration_number is not None: + value = str(registration_number) + if isinstance(registration_number, bool): + value = value.lower() + query_params.append(f"registrationNumber={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_a_list_of_licenses( + self, + id: str, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a List of Licenses + + Get a List of Licenses + + Swagger operation ID: `Get-a-List-of-Licenses`. + + Args: + id: Individual ID. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id), safe='')}" + f"/Licenses" + f"/{quote(str(page_number), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_all_awards( + self, + page_number: int, + *, + year: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List All Awards + + List All Awards + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `List-All-Awards`. + + Args: + page_number: Page Number. + year: Year. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Awards/{quote(str(page_number), safe='')}" + ) + query_params = [] + if year is not None: + value = str(year) + if isinstance(year, bool): + value = value.lower() + query_params.append(f"Year={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def find_members_or_individuals_by_name( + self, + name: str, + page_number: int, + *, + include_email: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Find Members (Individuals) by Name + + Find Members (Individuals) by Name + + Swagger operation ID: `Find-Members-or-Individuals-by-Name`. + + Args: + name: Individual Name. + page_number: Page Number. + include_email: Include Email Data. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/Members" + f"/FindByName" + f"/{quote(str(name), safe='')}" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if include_email is not None: + value = str(include_email) + if isinstance(include_email, bool): + value = value.lower() + query_params.append(f"includeEmail={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_a_list_of_all_services_of_an_organization( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a List of All Services of an Organization + + Get a List of All Services of an Organization + + Swagger operation ID: `Get-a-List-of-All-Services-of-an-Organization`. + + Args: + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Organizations/{quote(str(id), safe='')}/Services" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_a_service_to_an_organization( + self, + input: ServiceData | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add a Service to an Organization + + Add a Service to an Organization + + Swagger operation ID: `Add-a-Service-to-an-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Organizations/{quote(str(id), safe='')}/Services" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_phone_for_an_individual( + self, + input: PhoneSaveData | Mapping[str, Any], + id_or_record_number: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Phone for an Individual + + Update Phone for an Individual + + Swagger operation ID: `Update-Phone-for-an-Individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Individual ID or Record Number. + id: Phone ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Phones" + f"/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_phone_for_an_organization( + self, + input: PhoneSaveData | Mapping[str, Any], + id_or_record_number: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Phone for an Organization + + Update Phone for an Organization + + Swagger operation ID: `Update-Phone-for-an-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Organization ID or Record Number. + id: Phone ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Phones" + f"/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_an_individual_web_link( + self, + input: DeleteAnIndividualWebLinkInput | Mapping[str, Any], + id_or_record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete an Individual Web Link + + Delete an Individual Web Link + + Swagger operation ID: `Delete-an-Individual-Web-Link`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: A valid Individual ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Links" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_web_link_for_individual( + self, + input: AddWebLinkForIndividualInput | Mapping[str, Any], + id_or_record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Web Link for Individual + + Add Web Link for Individual + + Swagger operation ID: `Add-Web-Link-for-Individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: A valid Individual Id or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Links" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_phone_to_organization( + self, + input: PhoneSaveData | Mapping[str, Any], + id_or_record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Phone to Organization + + Add Phone to Organization + + Swagger operation ID: `Add-Phone-to-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Organization ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Phones" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_nominees_by_committee( + self, + code: str, + page_number: int, + *, + term: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Nominees by Committee + + Get Nominees by Committee + + Swagger operation ID: `Get-Nominees-by-Committee`. + + Args: + code: Committee Code. + page_number: Page Number. + term: Term. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Committees" + f"/{quote(str(code), safe='')}" + f"/Nominations" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if term is not None: + value = str(term) + if isinstance(term, bool): + value = value.lower() + query_params.append(f"Term={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_organizations_active_subscriptions( + self, + id: str, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Organization's Active Subscriptions + + Get Organization's Active Subscriptions + + Swagger operation ID: `Get-Organizations-Active-Subscriptions`. + + Args: + id: Organization ID. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/{quote(str(id), safe='')}" + f"/Subscriptions" + f"/{quote(str(page_number), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_an_organization_web_link( + self, + input: DeleteAnOrganizationWebLinkInput | Mapping[str, Any], + id_or_record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete an Organization Web Link + + Delete an Organization Web Link + + Swagger operation ID: `Delete-an-Organization-Web-Link`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Organization ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Links" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_web_link_for_organization( + self, + input: AddWebLinkForOrganizationInput | Mapping[str, Any], + id_or_record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Web Link for Organization + + Add Web Link for Organization + + Swagger operation ID: `Add-Web-Link-for-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Organization ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Links" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_email_to_organization( + self, + input: EmailData | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Email to Organization + + Add Email to Organization + + Swagger operation ID: `Add-Email-to-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Organizations/{quote(str(id), safe='')}/Emails" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_organizations_relationships( + self, + id: str, + page_number: int, + *, + relationship_name: Optional[str] = None, + includes_details: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Organization's Relationships + + Get Organization's Relationships + + Swagger operation ID: `Get-Organizations-Relationships`. + + Args: + id: Organization ID. + page_number: Page Number. + relationship_name: Name of the Relationship. + includes_details: Includes Details. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/{quote(str(id), safe='')}" + f"/Relationships" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if relationship_name is not None: + value = str(relationship_name) + if isinstance(relationship_name, bool): + value = value.lower() + query_params.append(f"relationshipName.={quote(value, safe='')}") + if includes_details is not None: + value = str(includes_details) + if isinstance(includes_details, bool): + value = value.lower() + query_params.append(f"includesDetails={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_or_update_address_to_organization( + self, + input: AddressSaveData | Mapping[str, Any], + id_or_record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add or Update Address to Organization + + Add or Update Address to Organization + + Swagger operation ID: `Add-or-Update-Address-to-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Organization ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Addresses" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_or_update_a_list_of_custom_fields_per_individual( + self, + input: AddOrUpdateAListOfCustomFieldsPerIndividualInput, + id_or_record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add or Update a List of Custom Fields Per Individual + + Add or Update a List of Custom Fields Per Individual + + Swagger operation ID: + `Add-or-Update-a-List-of-Custom-Fields-Per-Individual`. + + Args: + input: The request body. + id_or_record_number: Individual ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id_or_record_number), safe='')}" + f"/CustomFieldsList" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_upcoming_events( + self, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Upcoming Events + + Get Upcoming Events + + Swagger operation ID: `Get-Upcoming-Events`. + + Args: + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Events/Upcoming/{quote(str(page_number), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_phone_to_individual( + self, + input: PhoneSaveData | Mapping[str, Any], + id_or_record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Phone to Individual + + Add Phone to Individual + + Swagger operation ID: `Add-Phone-to-Individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Individual ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Phones" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_committee_information_for_an_individual( + self, + id: str, + page_number: int, + *, + include_inactive: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Committee Information for an Individual + + Get Committee Information for an Individual + + Swagger operation ID: `Get-Committee-Information-for-an-Individual`. + + Args: + id: Individual ID. + page_number: Page Number. + include_inactive: Include Inactive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id), safe='')}" + f"/Committees" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if include_inactive is not None: + value = str(include_inactive) + if isinstance(include_inactive, bool): + value = value.lower() + query_params.append(f"includeInactive={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_organization_custom_field_values( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Organization Custom Field Values + + Get Organization Custom Field Values + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Get-Organization-Custom-Field-Values`. + + Args: + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Organizations/{quote(str(id), safe='')}/CustomFields" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_organization_active_memberships( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Organization Active Memberships + + Get Organization Active Memberships + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Get-Organization-Active-Memberships`. + + Args: + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/{quote(str(id), safe='')}" + f"/Memberships" + f"/Active" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_all_events( + self, + page_number: int, + *, + code: Optional[str] = None, + name: Optional[str] = None, + tag: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get All Events + + Get All Events + + Swagger operation ID: `Get-All-Events`. + + Args: + page_number: Page Number. + code: Code. + name: Name. + tag: Tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Events/All/{quote(str(page_number), safe='')}" + ) + query_params = [] + if code is not None: + value = str(code) + if isinstance(code, bool): + value = value.lower() + query_params.append(f"Code={quote(value, safe='')}") + if name is not None: + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"Name={quote(value, safe='')}") + if tag is not None: + value = str(tag) + if isinstance(tag, bool): + value = value.lower() + query_params.append(f"Tag={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_individual_active_memberships( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Individual Active Memberships + + Get Individual Active Memberships + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Get-Individual-Active-Memberships`. + + Args: + id: Individual ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Individuals/{quote(str(id), safe='')}/Memberships/Active" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_all_event_registrations_information_for_an_individual( + self, + id_or_record_number: str, + page_number: int, + *, + event_code: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get All Event Registrations Information for an Individual + + Get All Event Registrations Information for an Individual + + Swagger operation ID: + `Get-All-Event-Registrations-Information-for-an-Individual`. + + Args: + id_or_record_number: Individual ID or Record Number. + page_number: Page Number. + event_code: Event Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Registrations" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if event_code is not None: + value = str(event_code) + if isinstance(event_code, bool): + value = value.lower() + query_params.append(f"eventCode={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_individuals_relationships( + self, + id: str, + page_number: int, + *, + relationship_name: Optional[str] = None, + include_details: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Individual's Relationships + + Get Individual's Relationships + + Swagger operation ID: `Get-Individuals-Relationships`. + + Args: + id: Individual ID. + page_number: Page Number. + relationship_name: Name of the Relationship. + include_details: Include Details. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id), safe='')}" + f"/Relationships" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if relationship_name is not None: + value = str(relationship_name) + if isinstance(relationship_name, bool): + value = value.lower() + query_params.append(f"relationshipName={quote(value, safe='')}") + if include_details is not None: + value = str(include_details) + if isinstance(include_details, bool): + value = value.lower() + query_params.append(f"includeDetails={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_an_individual_email( + self, + input: UpdateAnIndividualEmailInput | Mapping[str, Any], + id_or_record_number: str, + current_email_address: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update an Individual Email + + Update an Individual Email + + Swagger operation ID: `Update-an-Individual-Email`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Individual ID or Record Number. + current_email_address: Email Address to Update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Emails" + f"/{quote(str(current_email_address), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + async def save_relationship_for_organization( + self, + input: SaveRelationshipForOrganizationInput | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Save Relationship for Organization + + Save Relationship for Organization + + Swagger operation ID: `Save-Relationship-for-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Organizations/{quote(str(id), safe='')}/Relationships" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_individual( + self, + input: AddIndividualInput | Mapping[str, Any], + *, + create_user: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Individual + + Adds an Individual. + + Swagger operation ID: `Add-Individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + create_user: Choose True if a user account should be created when + the individual is created. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/v1/Individuals" + query_params = [] + if create_user is not None: + value = str(create_user) + if isinstance(create_user, bool): + value = value.lower() + query_params.append(f"createUser={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_email_to_individual( + self, + input: AddEmailToIndividualInput | Mapping[str, Any], + id_or_record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Email to Individual + + Add Email to Individual + + Swagger operation ID: `Add-Email-to-Individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Individual ID Or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Emails" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_or_update_address_to_individual( + self, + input: AddressSaveData | Mapping[str, Any], + id_or_record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add or Update Address to Individual + + Add or Update Address to Individual + + Swagger operation ID: `Add-or-Update-Address-to-Individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Individual ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id_or_record_number), safe='')}" + f"/Addresses" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def find_members_or_individuals_by_first_and_last_name( + self, + first_name: str, + last_name: str, + page_number: int, + *, + include_email: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Find Members (Individuals) by First Name and Last Name + + Find Members (Individuals) by First Name and Last Name + + Swagger operation ID: + `Find-members-or-individuals-by-first-and-last-name`. + + Args: + first_name: First Name. + last_name: Last Name. + page_number: Page Number. + include_email: Include Email Data. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/Members" + f"/FindByName" + f"/{quote(str(first_name), safe='')}" + f"/{quote(str(last_name), safe='')}" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if include_email is not None: + value = str(include_email) + if isinstance(include_email, bool): + value = value.lower() + query_params.append(f"includeEmail={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_committee_members_by_committee_id_or_code( + self, + id_or_code: str, + page_number: int, + *, + term: Optional[int] = None, + position_codes: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get Committee Members by committee ID or code + + Get Committee Members by Committee ID or Code + + Swagger operation ID: `Get-Committee-Members-by-committee-ID-or-code`. + + Args: + id_or_code: Committee ID or Code. + page_number: Page Number. + term: Term. + position_codes: Position Codes. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Committees" + f"/{quote(str(id_or_code), safe='')}" + f"/Members" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + if term is not None: + value = str(term) + if isinstance(term, bool): + value = value.lower() + query_params.append(f"Term={quote(value, safe='')}") + if position_codes is not None: + value = str(position_codes) + if isinstance(position_codes, bool): + value = value.lower() + query_params.append(f"positionCodes={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_activity( + self, + input: AddActivityInput | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Activity + + Add Activity. + + Swagger operation ID: `Add-Activity`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Individual Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Individuals/{quote(str(id), safe='')}/Activities" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def find_individual_id_or_email( + self, + id_or_record_number_or_email: str, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Find Individual by Id or Email or Record Number + + Find Individual by Id or Email. + + Swagger operation ID: `Find-Individual-IDOrEmail`. + + Args: + id_or_record_number_or_email: Id or Record Number or Email. + page_number: pageNumber. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/Profile" + f"/{quote(str(id_or_record_number_or_email), safe='')}" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + query_params.append("IncludeDetails=" + quote("true", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_relationship_to_individual( + self, + input: AddRelationshipToIndividualInput | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Relationship to Individual + + Add Relationship to Individual. + + Swagger operation ID: `Add-relationship-to-individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Individual Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Individuals/{quote(str(id), safe='')}/Relationships" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def individual_add_education_credit( + self, + input: EducationCreditData | Mapping[str, Any], + id_or_record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Education Credits to Individual + + Add a new Education Credit to an Individual. + + Swagger operation ID: `Individual-Add-Education-Credit`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Individual Id or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id_or_record_number), safe='')}" + f"/EducationCredits" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def individual_add_note( + self, + input: NoteData | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Note to Individual + + Add a Note to an Individual. + + Swagger operation ID: `Individual-AddNote`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Individual Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Individuals/{quote(str(id), safe='')}/Notes" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def individuals_lookup_by_name( + self, + page_number: int, + name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Lookup Individuals + + Lookup Individuals by Name + + Swagger operation ID: `Individuals-LookupByName`. + + Args: + page_number: pageNumber. + name: Individual Name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Individuals/Lookup/{quote(str(page_number), safe='')}" + ) + query_params = [] + query_params.append("includeOrgAddresses=" + quote("true", safe='')) + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_to_committee( + self, + input: CommitteeMemberCreateData | Mapping[str, Any], + code: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Individual to Committee + + Add Individual to Committee. + + Swagger operation ID: `Add-To-Committee`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + code: Committee Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Committees/{quote(str(code), safe='')}/Members" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_committee_member( + self, + input: CommitteeMemberUpdateData | Mapping[str, Any], + code: str, + member_record_number: str, + current_position_code: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update Committee Member + + Update Committee Member. + + Swagger operation ID: `Update-Committee-Member`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + code: Committee Code. + member_record_number: Member Record Number. + current_position_code: Current Position Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Committees" + f"/{quote(str(code), safe='')}" + f"/Members" + f"/{quote(str(member_record_number), safe='')}" + f"/{quote(str(current_position_code), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_organization( + self, + input: AddOrganizationInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Organization + + Add Organization. + + Swagger operation ID: `Add-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/v1/Organizations" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_organization( + self, + input: UpdateOrganizationInput | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Organization + + Update Organization. + + Swagger operation ID: `Update-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Organization Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Organizations/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def organization_get_profile( + self, + id_or_recordnumber: str, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Find Organization by Id or Record Number + + Get organization's profile information by ID or Record Number + + Swagger operation ID: `Organization-Get-Profile`. + + Args: + id_or_recordnumber: Organization Id or Record Number. + page_number: pageNumber. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Organizations" + f"/Profile" + f"/{quote(str(id_or_recordnumber), safe='')}" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + query_params.append("includeDescription=" + quote("true", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def organization_add_note( + self, + input: NoteData | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Note to Organization + + Add a Note to an Organization. + + Swagger operation ID: `Organization-AddNote`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Organization Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Organizations/{quote(str(id), safe='')}/Notes" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def organization_lookup_by_name( + self, + page_number: int, + name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Lookup Organizations + + Lookup Organizations by Name or Acronym + + Swagger operation ID: `Organization-LookupByName`. + + Args: + page_number: pageNumber. + name: Name or Acronym. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Organizations/Lookup/{quote(str(page_number), safe='')}" + ) + query_params = [] + query_params.append("includeAddresses=" + quote("true", safe='')) + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_all_committees( + self, + page_number: int, + *, + code: Optional[str] = None, + name: Optional[str] = None, + term: Optional[int] = None, + active_only: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get All Committees + + Get All Committees + + Swagger operation ID: `Get-All-Committees`. + + Args: + page_number: Page Number. + code: Committee Code. + name: Committee Name. + term: Term. + active_only: Active Only. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Committees/{quote(str(page_number), safe='')}" + ) + query_params = [] + if code is not None: + value = str(code) + if isinstance(code, bool): + value = value.lower() + query_params.append(f"Code={quote(value, safe='')}") + if name is not None: + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"Name={quote(value, safe='')}") + if term is not None: + value = str(term) + if isinstance(term, bool): + value = value.lower() + query_params.append(f"Term={quote(value, safe='')}") + if active_only is not None: + value = str(active_only) + if isinstance(active_only, bool): + value = value.lower() + query_params.append(f"activeOnly={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_positions_by_committee( + self, + code: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Positions by Committee + + Get Positions by Committee + + Swagger operation ID: `Get-Positions-by-Committee`. + + Args: + code: Committee Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Committees/{quote(str(code), safe='')}/Positions" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_sub_committees( + self, + code: str, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Sub-Committees + + Get Sub-Committees + + Swagger operation ID: `Get-Sub-Committees`. + + Args: + code: Code. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Committees" + f"/{quote(str(code), safe='')}" + f"/subcommittees" + f"/{quote(str(page_number), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_individuals_active_subscriptions( + self, + id: str, + page_number: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Individual's Active Subscriptions + + Get Individual's Active Subscriptions + + Swagger operation ID: `Get-Individuals-Active-Subscriptions`. + + Args: + id: Individual. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Individuals" + f"/{quote(str(id), safe='')}" + f"/Subscriptions" + f"/All" + f"/{quote(str(page_number), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_all_individuals( + self, + page_number: int, + *, + name: Optional[str] = None, + include_details: Optional[bool] = None, + old_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all Individuals + + List all Individuals + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `List-all-Individuals`. + + Args: + page_number: Page Number. + name: Individual Name. + include_details: Include Details. + old_id: Individual Old ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Individuals/{quote(str(page_number), safe='')}" + ) + query_params = [] + if name is not None: + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"Name={quote(value, safe='')}") + if include_details is not None: + value = str(include_details) + if isinstance(include_details, bool): + value = value.lower() + query_params.append(f"includeDetails={quote(value, safe='')}") + if old_id is not None: + value = str(old_id) + if isinstance(old_id, bool): + value = value.lower() + query_params.append(f"oldID={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def find_customer_phone( + self, + page_number: str, + phone_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Find Customer by Phone Number + + Find Customer by Phone Number. + + Swagger operation ID: `Find-Customer-Phone`. + + Args: + page_number: pageNumber. + phone_number: Phone Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Customers/{quote(str(page_number), safe='')}" + ) + query_params = [] + query_params.append("includeAddress=" + quote("true", safe='')) + query_params.append("includePhone=" + quote("true", safe='')) + query_params.append("includeEmail=" + quote("true", safe='')) + value = str(phone_number) + if isinstance(phone_number, bool): + value = value.lower() + query_params.append(f"phoneNumber={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def mark_registrant_attended( + self, + input: MarkRegistrantAttendedInput, + record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Mark Registrant as Attended + + Mark the Registrant as Attended for the specified Events. + + Swagger operation ID: `Mark-Registrant-Attended`. + + Args: + input: The request body. + record_number: Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Events" + f"/Registrants" + f"/{quote(str(record_number), safe='')}" + f"/Attended" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + async def awards_add_award_nomination( + self, + input: AwardNominationData | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add Award Nomination + + Add a new Award Nomination. + + Swagger operation ID: `Awards-AddAwardNomination`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Award Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Awards/{quote(str(id), safe='')}/Nominations" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def awards_update_award_nomination( + self, + input: UpdateAwardNominationData | Mapping[str, Any], + id: str, + nominee_record_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update Award Nomination + + Update an existing Award Nomination. + + Swagger operation ID: `Awards-UpdateAwardNomination`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Award Id. + nominee_record_number: Nominee Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Awards" + f"/{quote(str(id), safe='')}" + f"/Nominations" + f"/{quote(str(nominee_record_number), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + async def awards_get_individual_award_recipients( + self, + page_number: int, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + List Award Individual Recipients + + List all Individuals that are Award Recipients. + + Swagger operation ID: `Awards-GetIndividualAwardRecipients`. + + Args: + page_number: pageNumber. + id: Award Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Awards" + f"/{quote(str(id), safe='')}" + f"/Recipients" + f"/Individuals" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + query_params.append("includeDetails=" + quote("true", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def awards_get_organization_award_recipients( + self, + page_number: int, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + List Award Organization Recipients + + List all Organizations that are Award Recipients. + + Swagger operation ID: `Awards-GetOrganizationAwardRecipients`. + + Args: + page_number: pageNumber. + id: Award Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/v1" + f"/Awards" + f"/{quote(str(id), safe='')}" + f"/Recipients" + f"/Organizations" + f"/{quote(str(page_number), safe='')}" + ) + query_params = [] + query_params.append("includeDetails=" + quote("true", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/infusionsoft.py b/src/azure/connectors/aio/infusionsoft.py new file mode 100644 index 0000000..ea827a0 --- /dev/null +++ b/src/azure/connectors/aio/infusionsoft.py @@ -0,0 +1,342 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# InfusionsoftClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.infusionsoft import ( + CreateTaskRequest, + ListOrdersResponse, + ListTasksResponse, + OnNewTaskResponse, + TaskResponse, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "InfusionsoftClient", + "CreateTaskRequest", + "ListOrdersResponse", + "ListTasksResponse", + "OnNewTaskResponse", + "TaskResponse", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class InfusionsoftClient(ConnectorClientBase): + """Typed client for infusionsoft connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a InfusionsoftClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "infusionsoft" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_task( + self, + input: CreateTaskRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a task + + Create a new task. + + Swagger operation ID: `CreateTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/crm/rest/v1/tasks/" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_task( + self, + input: CreateTaskRequest | Mapping[str, Any], + id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a task + + Update an existing task. + + Swagger operation ID: `UpdateTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Id of the task. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/crm/rest/v1/tasks/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tasks( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List tasks + + Retrieve a page of tasks ordered by due date. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTasks`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/crm/rest/v1/tasks/search" + ) + query_params = [] + query_params.append("order=" + quote("-due_date", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("tasks", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/insightly.py b/src/azure/connectors/aio/insightly.py new file mode 100644 index 0000000..ca2301a --- /dev/null +++ b/src/azure/connectors/aio/insightly.py @@ -0,0 +1,1365 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# InsightlyClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.insightly import ( + Address, + Contact, + ContactInfo, + ContactRequest, + Event, + Lead, + LeadRequest, + ListContactsResponse, + ListEventsResponse, + ListLeadsResponse, + ListProjectsResponse, + ListTasksResponse, + ListUsersResponse, + ObjectEntity, + Organization, + OrganizationRequest, + Project, + ProjectRequest, + Tag, + TaskObject, + TaskRequest, + User, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "InsightlyClient", + "Address", + "Contact", + "ContactInfo", + "ContactRequest", + "Event", + "Lead", + "LeadRequest", + "ListContactsResponse", + "ListEventsResponse", + "ListLeadsResponse", + "ListProjectsResponse", + "ListTasksResponse", + "ListUsersResponse", + "ObjectEntity", + "Organization", + "OrganizationRequest", + "Project", + "ProjectRequest", + "Tag", + "TaskObject", + "TaskRequest", + "User", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class InsightlyClient(ConnectorClientBase): + """Typed client for insightly connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a InsightlyClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "insightly" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_tasks( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List tasks + + List tasks + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTasks`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Tasks" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("tasks", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_task( + self, + input: TaskRequest | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update task + + Update task + + Swagger operation ID: `UpdateTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique Id of the task to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Tasks" + query_params = [] + value = str(id) + if isinstance(id, bool): + value = value.lower() + query_params.append(f"id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_task( + self, + input: TaskRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add task + + Add task + + Swagger operation ID: `AddTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Tasks" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_projects( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List projects + + List projects + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListProjects`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Projects" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("projects", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_project( + self, + input: ProjectRequest | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update project + + Update project + + Swagger operation ID: `UpdateProject`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique Id of the project to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Projects" + query_params = [] + value = str(id) + if isinstance(id, bool): + value = value.lower() + query_params.append(f"id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_project( + self, + input: ProjectRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add project + + Add project + + Swagger operation ID: `AddProject`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Projects" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_leads( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List leads + + List leads + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListLeads`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Leads" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("leads", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_lead( + self, + input: LeadRequest | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update lead + + Update lead + + Swagger operation ID: `UpdateLead`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique Id of the lead to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Leads" + query_params = [] + value = str(id) + if isinstance(id, bool): + value = value.lower() + query_params.append(f"id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_lead( + self, + input: LeadRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add lead + + Add lead + + Swagger operation ID: `AddLead`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Leads" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_contacts( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List contacts + + List contacts + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListContacts`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Contacts" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("contacts", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_contact( + self, + input: ContactRequest | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update contact + + Update contact + + Swagger operation ID: `UpdateContact`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique Id of the contact to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Contacts" + query_params = [] + value = str(id) + if isinstance(id, bool): + value = value.lower() + query_params.append(f"id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_contact( + self, + input: ContactRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add contact + + Add contact + + Swagger operation ID: `AddContact`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Contacts" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_users( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List users + + List users + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListUsers`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Users" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("users", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def delete_task( + self, + task_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete task + + Delete task + + Swagger operation ID: `DeleteTask`. + + Args: + task_id: Task Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Tasks/{quote(str(task_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def follow_task( + self, + task_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Follow a task + + Follow a task + + Swagger operation ID: `FollowTask`. + + Args: + task_id: Task Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Tasks/{quote(str(task_id), safe='')}/Follow" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_project( + self, + project_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete project + + Delete project + + Swagger operation ID: `DeleteProject`. + + Args: + project_id: Project Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Projects/{quote(str(project_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_lead( + self, + lead_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete lead + + Delete lead + + Swagger operation ID: `DeleteLead`. + + Args: + lead_id: Lead Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Leads/{quote(str(lead_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_contact( + self, + contact_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete contact + + Delete contact + + Swagger operation ID: `DeleteContact`. + + Args: + contact_id: Contact Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Contacts/{quote(str(contact_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_organization( + self, + input: OrganizationRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add organization + + Add organization + + Swagger operation ID: `AddOrganization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Organisations" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/jedoxodatahub.py b/src/azure/connectors/aio/jedoxodatahub.py new file mode 100644 index 0000000..cf45ad6 --- /dev/null +++ b/src/azure/connectors/aio/jedoxodatahub.py @@ -0,0 +1,3193 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# JedoxodatahubClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.jedoxodatahub import ( + Cell, + CellArray, + Cube, + CubeArray, + CubeCellsResponse, + CubesResponse, + Database, + DatabaseArray, + DatabasesResponse, + Dimension, + DimensionArray, + DimensionsResponse, + Element, + ElementArray, + ElementsResponse, + Error, + ExtractRowsResponse, + ExtractsResponse, + GetCubeCellResultSchemaResponse, + GetExtractRowsResultSchemaResponse, + GetTransformRowsResultSchemaResponse, + GetViewCellResultSchemaResponse, + IntegratorComponent, + IntegratorComponentArray, + IntegratorExtractComponentRow, + IntegratorExtractComponentRowArray, + IntegratorProject, + IntegratorProjectArray, + IntegratorProjectGroup, + IntegratorProjectGroupArray, + IntegratorProjectGroupsResponse, + IntegratorProjectsResponse, + IntegratorRunResult, + IntegratorTransformComponentRow, + IntegratorTransformComponentRowArray, + JobsResponse, + LoadsResponse, + TransformRowsResponse, + TransformsResponse, + View, + ViewArray, + ViewCell, + ViewCellArray, + ViewCellsResponse, + ViewsResponse, +) + +__all__ = [ + "JedoxodatahubClient", + "Cell", + "CellArray", + "Cube", + "CubeArray", + "CubeCellsResponse", + "CubesResponse", + "Database", + "DatabaseArray", + "DatabasesResponse", + "Dimension", + "DimensionArray", + "DimensionsResponse", + "Element", + "ElementArray", + "ElementsResponse", + "Error", + "ExtractRowsResponse", + "ExtractsResponse", + "GetCubeCellResultSchemaResponse", + "GetExtractRowsResultSchemaResponse", + "GetTransformRowsResultSchemaResponse", + "GetViewCellResultSchemaResponse", + "IntegratorComponent", + "IntegratorComponentArray", + "IntegratorExtractComponentRow", + "IntegratorExtractComponentRowArray", + "IntegratorProject", + "IntegratorProjectArray", + "IntegratorProjectGroup", + "IntegratorProjectGroupArray", + "IntegratorProjectGroupsResponse", + "IntegratorProjectsResponse", + "IntegratorRunResult", + "IntegratorTransformComponentRow", + "IntegratorTransformComponentRowArray", + "JobsResponse", + "LoadsResponse", + "TransformRowsResponse", + "TransformsResponse", + "View", + "ViewArray", + "ViewCell", + "ViewCellArray", + "ViewCellsResponse", + "ViewsResponse", +] + + +# Type Definitions + +# Client Class + +class JedoxodatahubClient(ConnectorClientBase): + """Typed client for jedoxodatahub connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a JedoxodatahubClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "jedoxodatahub" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_databases( + self, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get databases + + Get a list of databases found in the server. System and config + databases are excluded from the list, but can be requested by providing + the ID. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Databases`. + + Args: + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Databases" + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def database_by_id( + self, + database_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get database by id + + Get the database with the given ID. + + Swagger operation ID: `DatabaseById`. + + Args: + database_id: Numeric ID of the database. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Databases({quote(str(database_id), safe='')})" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_cubes( + self, + database_id: int, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get cubes + + Get a list of cubes in the given database. To prevent issues with the + URL encodings, Attribute cubes will be renamed, e.g. \\#_Years to + ATT_Years. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Cubes`. + + Args: + database_id: Numeric ID of the database. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Databases({quote(str(database_id), safe='')})/Cubes" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def cube_by_id( + self, + database_id: int, + cube_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get cube by ID + + Get the cube with the given ID in the given database. To prevent issues + with the URL encodings, Attribute cubes will be renamed, e.g. \\#_Years + to ATT_Years. + + Swagger operation ID: `CubeById`. + + Args: + database_id: Numeric ID of the database. + cube_id: Numeric ID of the cube. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Databases({quote(str(database_id), safe='')})" + f"/Cubes({quote(str(cube_id), safe='')})" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_cube_cells( + self, + database_id: int, + cube_id: int, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + baseonly: Optional[bool] = None, + userules: Optional[bool] = None, + zerosupression: Optional[bool] = None, + disablepaging: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get cube cells + + Get the cells from a cube. This returns the cells' values and element + names. If the cell has a string value, the value is instead stored in + the stringValue field. Element names are stored in dynamic properties. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `CubeCells`. + + Args: + database_id: Numeric ID of the database. + cube_id: Numeric ID of the cube. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + > Currently the /Cells functions only support basic operations. + Complex formulas might return an invalid result. For complex + filtering, please use Views. + baseonly: If set to true, the result will only contain base + elements. If set to false, it will also contain consolidated + elements. + userules: If set to true, rules will be applied to the resulting + cells. + zerosupression: If set to true, numeric cells with a value of 0 and + empty string cells will be removed from the result. + disablepaging: If set to true, the service will return the entire + result instead of a single page. With this option set to true, + the response might take multiple minutes depending on the + cube's size. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Databases({quote(str(database_id), safe='')})" + f"/Cubes({quote(str(cube_id), safe='')})" + f"/Cells" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if baseonly is not None: + value = str(baseonly) + if isinstance(baseonly, bool): + value = value.lower() + query_params.append(f"baseonly={quote(value, safe='')}") + if userules is not None: + value = str(userules) + if isinstance(userules, bool): + value = value.lower() + query_params.append(f"userules={quote(value, safe='')}") + if zerosupression is not None: + value = str(zerosupression) + if isinstance(zerosupression, bool): + value = value.lower() + query_params.append(f"zerosupression={quote(value, safe='')}") + if disablepaging is not None: + value = str(disablepaging) + if isinstance(disablepaging, bool): + value = value.lower() + query_params.append(f"disablepaging={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_dimensions( + self, + database_id: int, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get dimensions + + Get a list of dimensions in the given database. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Dimensions`. + + Args: + database_id: Numeric ID of the database. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Databases({quote(str(database_id), safe='')})/Dimensions" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def dimension_by_id( + self, + database_id: int, + dimension_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get dimension by ID + + Get the dimension with the given ID in the given database. + + Swagger operation ID: `DimensionById`. + + Args: + database_id: Numeric ID of the database. + dimension_id: Numeric ID of the dimension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Databases({quote(str(database_id), safe='')})" + f"/Dimensions({quote(str(dimension_id), safe='')})" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_elements( + self, + database_id: int, + dimension_id: int, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get elements + + Get a list of elements in the given dimension. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Elements`. + + Args: + database_id: Numeric ID of the database. + dimension_id: Numeric ID of the dimension. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Databases({quote(str(database_id), safe='')})" + f"/Dimensions({quote(str(dimension_id), safe='')})" + f"/Elements" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def element_by_id( + self, + database_id: int, + dimension_id: int, + element_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get element by ID + + Returns the element with the given ID in the given dimension. + + Swagger operation ID: `ElementById`. + + Args: + database_id: Numeric ID of the database. + dimension_id: Numeric ID of the dimension. + element_id: Numeric ID of the element. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Databases({quote(str(database_id), safe='')})" + f"/Dimensions({quote(str(dimension_id), safe='')})" + f"/Elements({quote(str(element_id), safe='')})" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_views( + self, + database_id: int, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get stored views + + Get a list of stored views in the given database. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Views`. + + Args: + database_id: Numeric ID of the database. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Databases({quote(str(database_id), safe='')})/Views" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def view_by_id( + self, + database_id: int, + view_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get stored view by ID + + Get the view with the given ID in the given database. + + Swagger operation ID: `ViewById`. + + Args: + database_id: Numeric ID of the database. + view_id: UUID of the view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Databases({quote(str(database_id), safe='')})" + f"/Views({quote(str(view_id), safe='')})" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_view_cells( + self, + database_id: int, + view_id: str, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + baseonly: Optional[bool] = None, + userules: Optional[bool] = None, + zerosupression: Optional[bool] = None, + disablepaging: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get stored view cells + + Get all cells from a view. This returns the cells' values and element + names. If the cell has a string value, the value is instead stored in + the stringValue field. Element names are stored in dynamic properties. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ViewCells`. + + Args: + database_id: Numeric ID of the database. + view_id: UUID of the view. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + > Currently the /Cells functions only support basic operations. + Complex formulas might return an invalid result. + baseonly: If set to true, the result will only contain base + elements. If set to false, it will also contain consolidated + elements. + userules: If set to true, rules will be applied to the resulting + cells. + zerosupression: If set to true, numeric cells with a value of 0 and + empty string cells will be removed from the result. + disablepaging: If set to true, the service will return the entire + result instead of a single page. With this option set to true, + the response might take multiple minutes depending on the + view's size. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Databases({quote(str(database_id), safe='')})" + f"/Views({quote(str(view_id), safe='')})" + f"/Cells" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if baseonly is not None: + value = str(baseonly) + if isinstance(baseonly, bool): + value = value.lower() + query_params.append(f"baseonly={quote(value, safe='')}") + if userules is not None: + value = str(userules) + if isinstance(userules, bool): + value = value.lower() + query_params.append(f"userules={quote(value, safe='')}") + if zerosupression is not None: + value = str(zerosupression) + if isinstance(zerosupression, bool): + value = value.lower() + query_params.append(f"zerosupression={quote(value, safe='')}") + if disablepaging is not None: + value = str(disablepaging) + if isinstance(disablepaging, bool): + value = value.lower() + query_params.append(f"disablepaging={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_integrator_project_groups( + self, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Integrator project groups + + Get a list of integrator project groups found in the server. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `IntegratorProjectGroups`. + + Args: + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Integrator" + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def integrator_projects_by_id( + self, + group_identifier: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Integrator project group by identifier + + Get the project group with the given ID. + + Swagger operation ID: `IntegratorProjectsById`. + + Args: + group_identifier: The identifier of the Integrator project group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_integrator_projects( + self, + group_identifier: str, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Integrator projects + + Get a list of integrator projects found in the server. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `IntegratorProjects`. + + Args: + group_identifier: The identifier of the Integrator project group. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')/Projects" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def integrator_projects_by_name( + self, + group_identifier: str, + project_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Integrator project by name + + Get the integrator project with the given name. + + Swagger operation ID: `IntegratorProjectsByName`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_extracts( + self, + group_identifier: str, + project_name: str, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get extracts + + Get a list of extracts in the given integrator project. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Extracts`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + f"/Extracts" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def extract_by_name( + self, + group_identifier: str, + project_name: str, + extract_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get extract by Name + + Get the extract with the given name in the given integrator project. + + Swagger operation ID: `ExtractByName`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + extract_name: The name of the extract. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + f"/Extracts('{quote(str(extract_name), safe='')}')" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_extract_rows( + self, + group_identifier: str, + project_name: str, + extract_name: str, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get extract rows + + Stream the rows of the extract with the given name in the given + integrator project. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ExtractRows`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + extract_name: The name of the extract. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + f"/Extracts('{quote(str(extract_name), safe='')}')" + f"/Rows" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_jobs( + self, + group_identifier: str, + project_name: str, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get jobs + + Get a list of jobs in the given integrator project. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Jobs`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + f"/Jobs" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def job_by_name( + self, + group_identifier: str, + project_name: str, + job_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get job by name + + Get the jobs with the given name in the given integrator project. + + Swagger operation ID: `JobByName`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + job_name: The name of the job. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + f"/Jobs('{quote(str(job_name), safe='')}')" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def run_job( + self, + group_identifier: str, + project_name: str, + job_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Run job + + Run the job with the given name in the given integrator project. The + execution will be added to the queue. + + Swagger operation ID: `RunJob`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + job_name: The name of the job. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + f"/Jobs('{quote(str(job_name), safe='')}')" + f"/Run" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def run_job_with_variables( + self, + group_identifier: str, + project_name: str, + job_name: str, + variables: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Run job with variables + + Run the job with the given name in the given integrator project. The + execution will be added to the queue. + + Swagger operation ID: `RunJobWithVariables`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + job_name: The name of the job. + variables: Variable names and values separated by an equal sign. If + a variable is omitted, the default value will be used. Multiple + variables must be separated by commas. Example: + Variables='SourceDB=Demo,TargetDB=Biker'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + f"/Jobs('{quote(str(job_name), safe='')}')" + f"/Run(Variables='" + f"{quote(quote(str(variables), safe=''), safe='')}" + f"')" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_loads( + self, + group_identifier: str, + project_name: str, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get loads + + Get a list of loads in the given integrator project. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Loads`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + f"/Loads" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def load_by_name( + self, + group_identifier: str, + project_name: str, + load_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get load by name + + Get the transform with the given name in the given integrator project. + + Swagger operation ID: `LoadByName`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + load_name: The name of the load. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + f"/Loads('{quote(str(load_name), safe='')}')" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def run_load( + self, + group_identifier: str, + project_name: str, + load_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Run load + + Run the load with the given name in the given integrator project. The + execution will be added to the queue. + + Swagger operation ID: `RunLoad`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + load_name: The name of the load. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + f"/Loads('{quote(str(load_name), safe='')}')" + f"/Run()" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def run_load_with_variables( + self, + group_identifier: str, + project_name: str, + load_name: str, + variables: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Run load with variables + + Run the load with the given name in the given integrator project. The + execution will be added to the queue. + + Swagger operation ID: `RunLoadWithVariables`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + load_name: The name of the load. + variables: Variable names and values separated by an equal sign. If + a variable is omitted, the default value will be used. Multiple + variables must be separated by commas. Example: + Variables='SourceDB=Demo,TargetDB=Biker'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + f"/Loads('{quote(str(load_name), safe='')}')" + f"/Run(Variables='" + f"{quote(quote(str(variables), safe=''), safe='')}" + f"')" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_transforms( + self, + group_identifier: str, + project_name: str, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get transforms + + Get a list of transforms in the given integrator project. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Transforms`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + f"/Transforms" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def transform_by_name( + self, + group_identifier: str, + project_name: str, + transform_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get transform by name + + Get the transform with the given name in the given integrator project. + + Swagger operation ID: `TransformByName`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + transform_name: The name of the transform. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + f"/Transforms('{quote(str(transform_name), safe='')}')" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_transform_rows( + self, + group_identifier: str, + project_name: str, + transform_name: str, + *, + top: Optional[int] = None, + skip: Optional[int] = None, + filter: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get transform Rows + + Stream the rows of the transform with the given name in the given + integrator project. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `TransformRows`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + transform_name: The name of the transform. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Integrator('{quote(str(group_identifier), safe='')}')" + f"/Projects('{quote(str(project_name), safe='')}')" + f"/Transforms('{quote(str(transform_name), safe='')}')" + f"/Rows" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_cube_cell_result_schema( + self, + database_id: int, + cube_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Cube Cell Result Schema + + Service request for getting the schema used for the result of cube + cells. + + Swagger operation ID: `GetCubeCellResultSchema`. + + Args: + database_id: The identifier of the Olap database. + cube_id: The identifier of the Olap cube. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/service" + f"/powerapps" + f"/schema" + f"/databases" + f"/{quote(str(database_id), safe='')}" + f"/cubes" + f"/{quote(str(cube_id), safe='')}" + f"/cells" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_extract_rows_result_schema( + self, + group_identifier: str, + project_name: str, + extract_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Extract Rows Result Schema + + Service request for getting the schema used for the result of extract + rows. + + Swagger operation ID: `GetExtractRowsResultSchema`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the project. + extract_name: The name of the extract. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/service" + f"/powerapps" + f"/schema" + f"/integrator" + f"/{quote(str(group_identifier), safe='')}" + f"/{quote(str(project_name), safe='')}" + f"/extracts" + f"/{quote(str(extract_name), safe='')}" + f"/rows" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_transform_rows_result_schema( + self, + group_identifier: str, + project_name: str, + transform_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Transform Rows Result Schema + + Service request for getting the schema used for the result of transform + rows. + + Swagger operation ID: `GetTransformRowsResultSchema`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the project. + transform_name: The name of the transform. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/service" + f"/powerapps" + f"/schema" + f"/integrator" + f"/{quote(str(group_identifier), safe='')}" + f"/{quote(str(project_name), safe='')}" + f"/transforms" + f"/{quote(str(transform_name), safe='')}" + f"/rows" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_view_cell_result_schema( + self, + database_id: int, + view_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get View Cell Result Schema + + Service request for getting the schema used for the result of view + cells. + + Swagger operation ID: `GetViewCellResultSchema`. + + Args: + database_id: The identifier of the Olap database. + view_id: The identifier of the stored view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/service" + f"/powerapps" + f"/schema" + f"/databases" + f"/{quote(str(database_id), safe='')}" + f"/views" + f"/{quote(str(view_id), safe='')}" + f"/cells" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/jira.py b/src/azure/connectors/aio/jira.py new file mode 100644 index 0000000..579fadd --- /dev/null +++ b/src/azure/connectors/aio/jira.py @@ -0,0 +1,1992 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# JiraClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.jira import ( + Assignee, + CancelTaskResponse, + Comment, + CommentResponse, + CreateIssueInput, + CreateIssueRequest, + CreateIssueResponse, + CreateProjectCategoryInput, + CreateProjectCategoryResponse, + CreateProjectInput, + CreateProjectResponse, + Creator, + EditIssueInput, + EditIssueResponse, + FilterArray, + FullIssue, + GetCurrentUserResponse, + GetTaskResponse, + GetUserResponse, + IssueTypes, + ListFiltersResponse, + ListIssuesResponse, + ListIssuesResponseDatacenter, + ListProjectsResponse, + ListTransitionsResponse, + MCPQueryRequest, + MCPQueryResponse, + PartialIssue, + PriorityList, + Project, + ProjectArray, + Reporter, + Sites, + StatusList, + Transition, + TransitionInput, + TransitionStatus, + UpdateIssueRequest, + UpdateProjectInput, + UpdateProjectResponse, + UpdateTransitionResponse, + User, + UserList, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "JiraClient", + "Assignee", + "CancelTaskResponse", + "Comment", + "CommentResponse", + "CreateIssueInput", + "CreateIssueRequest", + "CreateIssueResponse", + "CreateProjectCategoryInput", + "CreateProjectCategoryResponse", + "CreateProjectInput", + "CreateProjectResponse", + "Creator", + "EditIssueInput", + "EditIssueResponse", + "FilterArray", + "FullIssue", + "GetCurrentUserResponse", + "GetTaskResponse", + "GetUserResponse", + "IssueTypes", + "ListFiltersResponse", + "ListIssuesResponse", + "ListIssuesResponseDatacenter", + "ListProjectsResponse", + "ListTransitionsResponse", + "MCPQueryRequest", + "MCPQueryResponse", + "PartialIssue", + "PriorityList", + "Project", + "ProjectArray", + "Reporter", + "Sites", + "StatusList", + "Transition", + "TransitionInput", + "TransitionStatus", + "UpdateIssueRequest", + "UpdateProjectInput", + "UpdateProjectResponse", + "UpdateTransitionResponse", + "User", + "UserList", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class JiraClient(ConnectorClientBase): + """Typed client for jira connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a JiraClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "jira" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_resources( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get list of Resources + + This operation returns a list of resources accessible to user. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListResources`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/oauth/token/accessible-resources" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_issues( + self, + *, + jql: Optional[str] = None, + fields: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get list of issues + + This operation returns a list of issues using JQL. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListIssues`. + + Args: + jql: The JQL query used to search for issues. If left blank, + returns all issues created in the last 10 years. + fields: Optional comma-separated list of Jira field IDs or keys to + return, for example summary,status,attachment. For custom + fields, use the field ID, such as customfield_10042. Also + supports *all, *navigable, and exclusions such as + *all,-attachment. If omitted, all fields are returned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/2/search" + query_params = [] + query_params.append("expand=" + quote("*", safe='')) + if jql is not None: + value = str(jql) + if isinstance(jql, bool): + value = value.lower() + query_params.append(f"jql={quote(value, safe='')}") + if fields is not None: + value = str(fields) + if isinstance(fields, bool): + value = value.lower() + query_params.append(f"fields={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("issues", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_issues_datacenter( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get list of issues (Datacenter) + + This operation returns a list of issues using JQL. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListIssues_Datacenter`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/datacenter/search" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("issues", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_transitions( + self, + issue_id_or_key: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get list of Transitions + + Returns a list of the transitions possible for this issue by the + current user + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTransitions`. + + Args: + issue_id_or_key: ID or key of the issue to retrieve transitions + for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/3/issue/{quote(str(issue_id_or_key), safe='')}/transitions" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("transitions", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_transition( + self, + input: TransitionInput | Mapping[str, Any], + issue_id_or_key: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Performs an issue transition + + Transitions an issue to a new status. + + Swagger operation ID: `UpdateTransition`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + issue_id_or_key: ID or key of the issue to be transitioned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/3/issue/{quote(str(issue_id_or_key), safe='')}/transitions" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_current_user( + self, + *, + expand: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get current user + + This operation returns details for the current user + + Swagger operation ID: `GetCurrentUser`. + + Args: + expand: Use expand to include additional information about users in + the response. This parameter accepts a comma-separated list. + Expand options include: * `groups` includes all groups and + nested groups to which the user belongs. * `applicationRoles` + includes details of all the applications to which the user has + access. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/3/myself" + query_params = [] + if expand is not None: + value = str(expand) + if isinstance(expand, bool): + value = value.lower() + query_params.append(f"expand={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def mcp_jira_issue_management( + self, + input: MCPQueryRequest | Mapping[str, Any], + *, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Jira MCP Server + + Jira MCP Server + + Swagger operation ID: `mcp_JiraIssueManagement`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + session_id: sessionId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/mcp/JiraIssueManagement" + query_params = [] + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_comment( + self, + input: Comment | Mapping[str, Any], + issue_key: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add comment + + This operation is used to add a comment to an existing Jira issue. + + Swagger operation ID: `AddComment_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + issue_key: Unique Key of the issue to add a comment to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/issue/{quote(str(issue_key), safe='')}/comment" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def cancel_task( + self, + task_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Cancel Task + + Cancels a task. Permissions required: either of: Administer Jira or + Creator of the task. + + Swagger operation ID: `CancelTask_V2`. + + Args: + task_id: The ID of the task. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/task/{quote(str(task_id), safe='')}/cancel" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_issue( + self, + input: CreateIssueInput | Mapping[str, Any], + project_key: str, + issue_type_ids: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a new issue + + This operation is used to create a new issue. + + Swagger operation ID: `CreateIssue_V3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + project_key: Pick a project to create the issue in. + issue_type_ids: Pick an issue type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v3/issue" + query_params = [] + value = str(project_key) + if isinstance(project_key, bool): + value = value.lower() + query_params.append(f"projectKey={quote(value, safe='')}") + value = str(issue_type_ids) + if isinstance(issue_type_ids, bool): + value = value.lower() + query_params.append(f"issueTypeIds={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_project( + self, + input: CreateProjectInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a new project + + This operation is used to create a new Jira project. + + Swagger operation ID: `CreateProject_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/project" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_project_category( + self, + input: CreateProjectCategoryInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Project Category + + Creates a project category. Permissions required: Administer Jira + (global permissions) + + Swagger operation ID: `CreateProjectCategory_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/projectCategory" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_project( + self, + project_id_or_key: str, + *, + enable_undo: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete Project + + Deletes a project. Permissions required: Administer Jira (global + permissions) + + Swagger operation ID: `DeleteProject_V2`. + + Args: + project_id_or_key: The project ID or project key (case sensitive). + enable_undo: Whether this project is placed in the Jira recycle bin + where it will be available for restoration. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/project/{quote(str(project_id_or_key), safe='')}" + ) + query_params = [] + if enable_undo is not None: + value = str(enable_undo) + if isinstance(enable_undo, bool): + value = value.lower() + query_params.append(f"enableUndo={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def edit_issue( + self, + input: EditIssueInput | Mapping[str, Any], + issue_id_or_key: str, + *, + notify_users: Optional[bool] = None, + override_screen_security: Optional[bool] = None, + override_editable_flag: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Edit Issue + + Edits an issue. A transition may be applied and issue properties + updated as part of the edit. The edits to the issue's fields are + defined using update and fields. + + Swagger operation ID: `EditIssue_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + issue_id_or_key: Provide the Issue ID or Key for the issue you wish + to edit. + notify_users: Do you want to notify users? + override_screen_security: Do you want to override the screen + security? + override_editable_flag: Do you want to override the editable flag? + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/3/issue/{quote(str(issue_id_or_key), safe='')}" + ) + query_params = [] + if notify_users is not None: + value = str(notify_users) + if isinstance(notify_users, bool): + value = value.lower() + query_params.append(f"notifyUsers={quote(value, safe='')}") + if override_screen_security is not None: + value = str(override_screen_security) + if isinstance(override_screen_security, bool): + value = value.lower() + query_params.append(f"overrideScreenSecurity={quote(value, safe='')}") + if override_editable_flag is not None: + value = str(override_editable_flag) + if isinstance(override_editable_flag, bool): + value = value.lower() + query_params.append(f"overrideEditableFlag={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_all_project_categories( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get All Project Categories + + Returns all project categories. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAllProjectCategories_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/projectCategory" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_issue( + self, + issue_key: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get issue by key + + This operation is used to retrieve the issue object for a given issue + Key. + + Swagger operation ID: `GetIssue_V2`. + + Args: + issue_key: Unique Key of the issue. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/issue/{quote(str(issue_key), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_task( + self, + task_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Task + + Returns the status of a long-running asynchronous task. When a task has + finished, this operation returns the JSON blob applicable to the task. + + Swagger operation ID: `GetTask_V2`. + + Args: + task_id: The ID of the task. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/task/{quote(str(task_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_user( + self, + account_id: str, + *, + expand: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get User + + Returns a user. Permissions required: Browse users and groups. + + Swagger operation ID: `GetUser_V2`. + + Args: + account_id: The account ID of the user, which uniquely identifies + the user across all Atlassian products. For example, + *5b10ac8d82e05b22cc7d4ef5*. Required. + expand: Use expand to include additional information about users in + the response. This parameter accepts a comma-separated list. + Expand options include: * `groups` includes all groups and + nested groups to which the user belongs. * `applicationRoles` + includes details of all the applications to which the user has + access. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/user" + query_params = [] + value = str(account_id) + if isinstance(account_id, bool): + value = value.lower() + query_params.append(f"accountId={quote(value, safe='')}") + if expand is not None: + value = str(expand) + if isinstance(expand, bool): + value = value.lower() + query_params.append(f"expand={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_filters( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get list of Filters + + This operation returns a list of Filters accessible to user. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListFilters_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/filter/search" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextPage") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("values", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_projects( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get projects + + This operation is used to retrieve a list of projects for your Jira + instance. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListProjects_V3`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/project/search" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextPage") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("values", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_project_users( + self, + project_key: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List users by project + + This operation is used to retrieve a list of all users associated with + a project. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListProjectUsers_V2`. + + Args: + project_key: Unique key of the project. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v2/user/permission/search" + ) + query_params = [] + value = str(project_key) + if isinstance(project_key, bool): + value = value.lower() + query_params.append(f"projectKey={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def remove_project_category( + self, + id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Remove Project Category + + Deletes a project category. Permissions required: Administer Jira + (global permissions) + + Swagger operation ID: `RemoveProjectCategory_V2`. + + Args: + id: ID of the project category to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/projectCategory/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def update_project( + self, + input: UpdateProjectInput | Mapping[str, Any], + project_id_or_key: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Project + + Updates the project details of a project. + + Swagger operation ID: `UpdateProject_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + project_id_or_key: Provide the project ID or Key you want to + update1. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/project/{quote(str(project_id_or_key), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_issue_types( + self, + project_key: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get issue types + + This operation is used to retrieve a list of issue types for a given + project. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListIssueTypes_V2`. + + Args: + project_key: Project. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v2/types/issue/createmeta" + ) + query_params = [] + value = str(project_key) + if isinstance(project_key, bool): + value = value.lower() + query_params.append(f"projectKey={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_issue_types_fields( + self, + project_key: str, + issuetype_ids: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get issue types fields + + This operation is used to retrieve a list of fields for a specific + issue type. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListIssueTypesFields_V2`. + + Args: + project_key: Project. + issuetype_ids: Issue Types. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v3/issue/createmeta" + query_params = [] + value = str(project_key) + if isinstance(project_key, bool): + value = value.lower() + query_params.append(f"projectKey={quote(value, safe='')}") + value = str(issuetype_ids) + if isinstance(issuetype_ids, bool): + value = value.lower() + query_params.append(f"issuetypeIds={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/keyvault.py b/src/azure/connectors/aio/keyvault.py new file mode 100644 index 0000000..d7c332a --- /dev/null +++ b/src/azure/connectors/aio/keyvault.py @@ -0,0 +1,1072 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# KeyvaultClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.keyvault import ( + KeyDecryptInput, + KeyDecryptOutput, + KeyEncryptInput, + KeyEncryptOutput, + KeyMetadata, + KeyMetadataCollection, + Secret, + SecretMetadata, + SecretMetadataCollection, +) + +__all__ = [ + "KeyvaultClient", + "KeyDecryptInput", + "KeyDecryptOutput", + "KeyEncryptInput", + "KeyEncryptOutput", + "KeyMetadata", + "KeyMetadataCollection", + "Secret", + "SecretMetadata", + "SecretMetadataCollection", +] + + +# Type Definitions + +# Client Class + +class KeyvaultClient(ConnectorClientBase): + """Typed client for keyvault connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a KeyvaultClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "keyvault" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_keys( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List keys + + List keys. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListKeys`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/keys" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_key_versions( + self, + key_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List key versions + + List versions of a key. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListKeyVersions`. + + Args: + key_name: Name of the key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/keys/{quote(str(key_name), safe='')}/versions" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_key_metadata( + self, + key_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get key metadata + + Gets metadata of a key. + + Swagger operation ID: `GetKeyMetadata`. + + Args: + key_name: Name of the key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/keys/{quote(str(key_name), safe='')}/metadata" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_key_version_metadata( + self, + key_name: str, + key_version: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get key version metadata + + Gets metadata of a version of a key. + + Swagger operation ID: `GetKeyVersionMetadata`. + + Args: + key_name: Name of the key. + key_version: Version of the key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/keys" + f"/{quote(str(key_name), safe='')}" + f"/versions" + f"/{quote(str(key_version), safe='')}" + f"/metadata" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def encrypt_data( + self, + input: KeyEncryptInput | Mapping[str, Any], + key_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Encrypt data with key + + Encrypt data using the latest version of a key. + + Swagger operation ID: `EncryptData`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + key_name: Name of the key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/keys/{quote(str(key_name), safe='')}/encrypt" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def encrypt_data_with_version( + self, + input: KeyEncryptInput | Mapping[str, Any], + key_name: str, + key_version: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Encrypt data with key version + + Encrypt data using a specific version of a key. + + Swagger operation ID: `EncryptDataWithVersion`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + key_name: Name of the key. + key_version: Version of the key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/keys" + f"/{quote(str(key_name), safe='')}" + f"/versions" + f"/{quote(str(key_version), safe='')}" + f"/encrypt" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def decrypt_data( + self, + input: KeyDecryptInput | Mapping[str, Any], + key_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Decrypt data with key + + Decrypt data using the latest version of a key. Output of this + operation is typically classified as secret and can be visible in the + run history. + + Swagger operation ID: `DecryptData`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + key_name: Name of the key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/keys/{quote(str(key_name), safe='')}/decrypt" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def decrypt_data_with_version( + self, + input: KeyDecryptInput | Mapping[str, Any], + key_name: str, + key_version: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Decrypt data with key version + + Decrypt data using a specific version of a key. Output of this + operation is typically classified as secret and can be visible in the + run history. + + Swagger operation ID: `DecryptDataWithVersion`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + key_name: Name of the key. + key_version: Version of the key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/keys" + f"/{quote(str(key_name), safe='')}" + f"/versions" + f"/{quote(str(key_version), safe='')}" + f"/decrypt" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_secrets( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List secrets + + List secrets. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListSecrets`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/secrets" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_secret_versions( + self, + secret_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List secret versions + + List versions of a secret. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListSecretVersions`. + + Args: + secret_name: Name of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/secrets/{quote(str(secret_name), safe='')}/versions" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_secret_metadata( + self, + secret_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get secret metadata + + Gets metadata of a secret. + + Swagger operation ID: `GetSecretMetadata`. + + Args: + secret_name: Name of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/secrets/{quote(str(secret_name), safe='')}/metadata" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_secret_version_metadata( + self, + secret_name: str, + secret_version: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get secret version metadata + + Gets metadata of a version of a secret. + + Swagger operation ID: `GetSecretVersionMetadata`. + + Args: + secret_name: Name of the secret. + secret_version: Version of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/secrets" + f"/{quote(str(secret_name), safe='')}" + f"/versions" + f"/{quote(str(secret_version), safe='')}" + f"/metadata" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_secret( + self, + secret_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get secret + + Gets a secret. Output of this operation is typically classified as + secret and can be visible in the run history. + + Swagger operation ID: `GetSecret`. + + Args: + secret_name: Name of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/secrets/{quote(str(secret_name), safe='')}/value" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_secret_version( + self, + secret_name: str, + secret_version: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get secret version + + Gets a version of a secret. Output of this operation is typically + classified as secret and can be visible in the run history. + + Swagger operation ID: `GetSecretVersion`. + + Args: + secret_name: Name of the secret. + secret_version: Version of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/secrets" + f"/{quote(str(secret_name), safe='')}" + f"/versions" + f"/{quote(str(secret_version), safe='')}" + f"/value" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/kusto.py b/src/azure/connectors/aio/kusto.py new file mode 100644 index 0000000..7d0b012 --- /dev/null +++ b/src/azure/connectors/aio/kusto.py @@ -0,0 +1,612 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# KustoClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping +from urllib.parse import quote +import json + +from azure.core.polling import AsyncLROPoller +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorPollingMethod, +) + +from azure.connectors.kusto import ( + AsyncCommandResult, + ChartType, + ClusterName, + CommandAndVisualizeSchema, + ControlCommandAndListSchema, + DatabaseName, + MCPQueryRequest, + MCPQueryResponse, + ObjectEntity, + Query, + QueryAndListSchema, + QueryAndVisualizeSchema, + Row, + Table, + VisualizeResults, +) + +__all__ = [ + "KustoClient", + "AsyncCommandResult", + "ChartType", + "ClusterName", + "CommandAndVisualizeSchema", + "ControlCommandAndListSchema", + "DatabaseName", + "MCPQueryRequest", + "MCPQueryResponse", + "ObjectEntity", + "Query", + "QueryAndListSchema", + "QueryAndVisualizeSchema", + "Row", + "Table", + "VisualizeResults", +] + + +# Type Definitions + +# Client Class + +class KustoClient(ConnectorClientBase): + """Typed client for kusto connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a KustoClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "kusto" + + async def begin_list_kusto_results( + self, + input: QueryAndListSchema | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Run KQL query + + Runs the KQL query and returns the result as a set of rows which can be + iterated over in the following connectors e.g TableName | take 10. + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `listKustoResultsPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/ListKustoResults/false" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_list_kusto_show_command_results( + self, + input: ControlCommandAndListSchema | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Run show control command + + Runs the show control command and returns the result as a set of rows + which can be iterated over in the following connectors e.g .show table + TableName policy caching. + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `listKustoShowCommandResultsPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/ListKustoShowCommandResults" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_run_kusto_query_and_visualize_results( + self, + input: QueryAndVisualizeSchema | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Run KQL query and render a chart + + Runs the KQL query and returns result as a chart of your choice e.g + TableName | where Timestamp > ago(1h) | project timestamp, value. + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `runKustoQueryAndVisualizeResultsPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/RunKustoAndVisualizeResults/false" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_run_kusto_command_and_visualize_results( + self, + input: CommandAndVisualizeSchema | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Run control command and render a chart + + Runs the control command and returns the result as a chart of your + choice e.g .clear table TableName data. + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `runKustoCommandAndVisualizeResultsPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/RunKustoAndVisualizeResults/true" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_run_async_control_command_and_wait( + self, + input: ControlCommandAndListSchema | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Run async control command + + Runs control command in async mode and returns its ID, state and status + on completion. Command can run for maximum 1 hour. The 'async' keyword + is mandatory e.g .set-or-append async TargetTable <| SourceTable. + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `runAsyncControlCommandAndWait`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/RunAsyncControlCommandAndWait" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def mcp_kusto_query_management( + self, + input: MCPQueryRequest | Mapping[str, Any], + *, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Kusto Query MCP Server + + This MCP server runs Kusto queries and manages the results. + + Swagger operation ID: `mcp_KustoQueryManagement`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + session_id: sessionId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/mcp/KustoQueryManagement" + ) + query_params = [] + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def list_kusto_results_schema( + self, + input: QueryAndListSchema | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Query schema + + Gets the schema for a query + + Swagger operation ID: `listKustoResultsSchemaPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/ListKustoResultsSchema" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/mailchimp.py b/src/azure/connectors/aio/mailchimp.py new file mode 100644 index 0000000..8d37ea5 --- /dev/null +++ b/src/azure/connectors/aio/mailchimp.py @@ -0,0 +1,844 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# MailchimpClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.mailchimp import ( + ABSplitOpts, + AddUserResponseModel, + CampaignDefaults, + CampaignResponseModel, + Capsule, + Contact, + CreateNewListResponseModel, + DailySend, + DeliveryStatus, + FirstAndLastName, + GetAddMembersBatchResponseModel, + GetAllMembersResponseModel, + GetCampaignsResponse, + GetListsResponseModel, + GetMembersResponseModel, + Highrise, + LastNote, + Link, + Location, + MemberResponseModel, + NewCampaignRequest, + NewListRequest, + NewMemberInListRequest, + NewMembersInListRequest, + ObjectEntity, + RSSOpts, + Recipient, + ReportSummary, + Salesforce, + Schedule, + SegmentOpts, + Settings, + SocialCard, + Stats, + Tracking, + UpdateMemberInListRequest, + VariateSettings, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "MailchimpClient", + "ABSplitOpts", + "AddUserResponseModel", + "CampaignDefaults", + "CampaignResponseModel", + "Capsule", + "Contact", + "CreateNewListResponseModel", + "DailySend", + "DeliveryStatus", + "FirstAndLastName", + "GetAddMembersBatchResponseModel", + "GetAllMembersResponseModel", + "GetCampaignsResponse", + "GetListsResponseModel", + "GetMembersResponseModel", + "Highrise", + "LastNote", + "Link", + "Location", + "MemberResponseModel", + "NewCampaignRequest", + "NewListRequest", + "NewMemberInListRequest", + "NewMembersInListRequest", + "ObjectEntity", + "RSSOpts", + "Recipient", + "ReportSummary", + "Salesforce", + "Schedule", + "SegmentOpts", + "Settings", + "SocialCard", + "Stats", + "Tracking", + "UpdateMemberInListRequest", + "VariateSettings", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class MailchimpClient(ConnectorClientBase): + """Typed client for mailchimp connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a MailchimpClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "mailchimp" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_campaigns( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List campaigns + + This operation retrieves a list of campaigns in an account + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetCampaigns`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/campaigns" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("campaigns", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def sendcampaign( + self, + campaign_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Send Campaign + + Send an existing campaign + + Swagger operation ID: `sendcampaign`. + + Args: + campaign_id: The unique id for the list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/campaigns/{quote(str(campaign_id), safe='')}/actions/send" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_lists( + self, + *, + count: Optional[int] = None, + offset: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get all the lists + + Find all the lists for the current user + + Swagger operation ID: `GetLists`. + + Args: + count: The number of records to return. Default value is 10. + Maximum value is 1000. + offset: The number of records from a collection to skip. Default + value is 0. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/lists" + query_params = [] + if count is not None: + value = str(count) + if isinstance(count, bool): + value = value.lower() + query_params.append(f"count={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def newlist( + self, + input: NewListRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + New List + + Create a new list in your MailChimp account + + Swagger operation ID: `newlist`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/lists" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_members( + self, + input: NewMembersInListRequest | Mapping[str, Any], + list_id: str, + *, + skip_merge_validation: Optional[bool] = None, + skip_duplicate_check: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Subscribe or unsubscribe list members + + Batch subscribe or unsubscribe list members. + + Swagger operation ID: `AddMembers`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + list_id: The unique id for the list. + skip_merge_validation: Allows member data to be accepted without + merge field values. + skip_duplicate_check: Ignores duplicates sent in the request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(list_id), safe='')}" + ) + query_params = [] + if skip_merge_validation is not None: + value = str(skip_merge_validation) + if isinstance(skip_merge_validation, bool): + value = value.lower() + query_params.append(f"skip_merge_validation={quote(value, safe='')}") + if skip_duplicate_check is not None: + value = str(skip_duplicate_check) + if isinstance(skip_duplicate_check, bool): + value = value.lower() + query_params.append(f"skip_duplicate_check={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_list_members( + self, + list_id: str, + *, + count: Optional[int] = None, + offset: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Show list members + + Show all the members of a list + + Swagger operation ID: `GetListMembers`. + + Args: + list_id: The unique id for the list. + count: The number of records to return. Default value is 10. + Maximum value is 1000. + offset: The number of records from a collection to skip. Default + value is 0. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(list_id), safe='')}/members" + ) + query_params = [] + if count is not None: + value = str(count) + if isinstance(count, bool): + value = value.lower() + query_params.append(f"count={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def addmember( + self, + input: NewMemberInListRequest | Mapping[str, Any], + list_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add member to list + + Add or update a list member + + Swagger operation ID: `addmember`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + list_id: The unique id for the list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(list_id), safe='')}/members" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def newcampaign( + self, + input: NewCampaignRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + New Campaign + + Create a new campaign based on a Campaign Type, Recipients list and + Campaign Settings (subject line, title, from_name and reply_to). + + Swagger operation ID: `newcampaignV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/campaigns" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def removemember( + self, + list_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Remove Member from list + + Delete a member from a list. + + Swagger operation ID: `removemember_v2`. + + Args: + list_id: The unique id for the list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists" + f"/replacemailwithhash" + f"/{quote(str(list_id), safe='')}" + f"/members" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def updatemember( + self, + input: UpdateMemberInListRequest | Mapping[str, Any], + list_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update member information + + Update information for a specific list member. + + Swagger operation ID: `updatemember_v2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + list_id: The unique id for the list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists" + f"/replacemailwithhash" + f"/{quote(str(list_id), safe='')}" + f"/members" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/meetingroommap.py b/src/azure/connectors/aio/meetingroommap.py new file mode 100644 index 0000000..067d868 --- /dev/null +++ b/src/azure/connectors/aio/meetingroommap.py @@ -0,0 +1,1484 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# MeetingroommapClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.meetingroommap import ( + AADMeetingRoom, + AADMeetingRoomCollection, + GetCustomLocationListByImageNameQuery, + GetCustomLocationsByCategoriesQuery, + GetCustomLocationsByImageNameResponse, + GetOfficeLocationsByImageResponse, + GetRoomWithPersonsDetailsResponse, + GetRoomsByImageNameResponse, + UserDetailsDTO, +) + +__all__ = [ + "MeetingroommapClient", + "AADMeetingRoom", + "AADMeetingRoomCollection", + "GetCustomLocationListByImageNameQuery", + "GetCustomLocationsByCategoriesQuery", + "GetCustomLocationsByImageNameResponse", + "GetOfficeLocationsByImageResponse", + "GetRoomWithPersonsDetailsResponse", + "GetRoomsByImageNameResponse", + "UserDetailsDTO", +] + + +# Type Definitions + +# Client Class + +class MeetingroommapClient(ConnectorClientBase): + """Typed client for meetingroommap connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a MeetingroommapClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "meetingroommap" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def get_custom_locations( + self, + input: GetCustomLocationsByCategoriesQuery | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get all custom locations + + Get all custom locations + + Swagger operation ID: `GetCustomLocations`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/CustomLocations/GetCustomLocations" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_custom_locations_by_image_name( + self, + input: GetCustomLocationListByImageNameQuery | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get locations by image + + Get all custom locations for a given image + + Swagger operation ID: `GetCustomLocationsByImageName`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/CustomLocations/GetCustomLocationsByImageName" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_categories( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[str]: + """ + GetCategories + + Get custom categories + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetCategories`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[str]: An Azure Core pager over connector results. + Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/api/CustomLocations/categories" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[str]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def location_details( + self, + location_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get location by id + + Get location details including image url by the location id + + Swagger operation ID: `LocationDetails`. + + Args: + location_id: Location identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/CustomLocations/{quote(str(location_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + def list_search_locations( + self, + location_name: str, + *, + category: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Search location by name + + Search custom locations by name + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SearchLocations`. + + Args: + location_name: Search string for location. + category: Optional category filter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/CustomLocations" + f"/findbyname" + f"/{quote(str(location_name), safe='')}" + ) + query_params = [] + if category is not None: + value = str(category) + if isinstance(category, bool): + value = value.lower() + query_params.append(f"Category={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_custom_location_image( + self, + location_id: str, + *, + large: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get image for location + + Get image for specific custom location + + Swagger operation ID: `GetCustomLocationImage`. + + Args: + location_id: Unique identifier for location. + large: Large image returned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/CustomLocations" + f"/createimage" + f"/{quote(str(location_id), safe='')}" + ) + query_params = [] + if large is not None: + value = str(large) + if isinstance(large, bool): + value = value.lower() + query_params.append(f"Large={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + def list_images( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get all images + + Get list of all floorplans/images + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Images`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/MapImage/thumbnails" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_meeting_room_image( + self, + room_name: str, + *, + large: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get image for meeting room + + Get image for a specific meeting room + + Swagger operation ID: `GetMeetingRoomImage`. + + Args: + room_name: The name of the room to get image for. + large: Large image. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/MapImage/create/{quote(str(room_name), safe='')}" + ) + query_params = [] + if large is not None: + value = str(large) + if isinstance(large, bool): + value = value.lower() + query_params.append(f"Large={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def next_meetings( + self, + meeting_count: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get next meetings + + Get the next meetings for the current user + + Swagger operation ID: `NextMeetings`. + + Args: + meeting_count: Count of meetings. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/MapImage" + f"/meetings" + f"/{quote(str(meeting_count), safe='')}" + f"/roomdetails" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_meeting_room_details( + self, + room_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get meetingroom details + + Get meetingroom details + + Swagger operation ID: `GetMeetingRoomDetails`. + + Args: + room_name: The room name to get details for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/MapImage/roomdetails_v2/{quote(str(room_name), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_office_locations( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get all office locations + + Get all office locations + + Swagger operation ID: `GetOfficeLocations`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/officelocations" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + def list_search_coworkers( + self, + person_search: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Search coworker + + Search coworker by name/email + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SearchCoworkers`. + + Args: + person_search: Search string. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/officelocations" + f"/searchCoworkers" + f"/{quote(str(person_search), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_office_locations_by_image( + self, + image_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get office locations on image + + Get all office locations mapped to a specific image + + Swagger operation ID: `GetOfficeLocationsByImage`. + + Args: + image_name: The image identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/officelocations" + f"/bymapimage" + f"/{quote(str(image_name), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_room_with_persons_details( + self, + office_location_name: str, + *, + inlude_user_info: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get office location details + + Get office location details including list of people for that office + location + + Swagger operation ID: `GetRoomWithPersonsDetails`. + + Args: + office_location_name: The office location name. + inlude_user_info: Flag to indicate if user info should be included. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/officelocations" + f"/mapimagewithpersoninfo" + f"/{quote(str(office_location_name), safe='')}" + ) + query_params = [] + if inlude_user_info is not None: + value = str(inlude_user_info) + if isinstance(inlude_user_info, bool): + value = value.lower() + query_params.append(f"InludeUserInfo={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_office_location_image( + self, + office_location_name: str, + *, + large: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get image of office location + + Get image of specific office location + + Swagger operation ID: `GetOfficeLocationImage`. + + Args: + office_location_name: Office location identifier. + large: Image size. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/officelocationimage" + f"/create" + f"/{quote(str(office_location_name), safe='')}" + ) + query_params = [] + if large is not None: + value = str(large) + if isinstance(large, bool): + value = value.lower() + query_params.append(f"Large={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + def list_rooms( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get all rooms + + Get all rooms (defined in Azure AD as meeting rooms) + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetRooms`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/rooms" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("rooms", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_search_meeting_rooms( + self, + name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Search for meeting room + + Get rooms by name search (from Azure AD meeting rooms) + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SearchMeetingRooms`. + + Args: + name: Search string. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/rooms/findbyname/{quote(str(name), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("rooms", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_room_lists( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get meeting rooms lists + + Get meeting rooms lists as defined in Azure AD + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `RoomLists`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/rooms/lists" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("rooms", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_rooms_by_list_address( + self, + meeting_room_list_address: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get meeting rooms by list + + Get all meeting rooms from specific list name + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `RoomsByListAddress`. + + Args: + meeting_room_list_address: Name of list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/rooms/{quote(str(meeting_room_list_address), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("rooms", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_rooms_by_image_name( + self, + image_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get all meeting rooms by image + + Get all meeting rooms mapped to a specific image + + Swagger operation ID: `GetRoomsByImageName`. + + Args: + image_name: The unique image name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/rooms/GetRoomsByImageName/{quote(str(image_name), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/microsoftbookings.py b/src/azure/connectors/aio/microsoftbookings.py new file mode 100644 index 0000000..7aaf53f --- /dev/null +++ b/src/azure/connectors/aio/microsoftbookings.py @@ -0,0 +1,239 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# MicrosoftbookingsClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.microsoftbookings import ( + AppointmentData, + CancelAppointmentInput, + CreateAppointmentInput, + CustomQuestion, + CustomerData, + DeleteWebhookResponse, + ListMailboxResponse, + MailboxEntity, + StaffMemberData, + UpdateAppointmentInput, + WebhookResponse, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "MicrosoftbookingsClient", + "AppointmentData", + "CancelAppointmentInput", + "CreateAppointmentInput", + "CustomQuestion", + "CustomerData", + "DeleteWebhookResponse", + "ListMailboxResponse", + "MailboxEntity", + "StaffMemberData", + "UpdateAppointmentInput", + "WebhookResponse", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class MicrosoftbookingsClient(ConnectorClientBase): + """Typed client for microsoftbookings connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a MicrosoftbookingsClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "microsoftbookings" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_bookings_business_user_as_admin( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Booking Businesses where user is an admin + + Operation used to list all mailboxes for which the accessing user is an + Administrator. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListBookingsBusinessUserAsAdmin`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/BookingsService/api/V1/bookingBusinessesUserAsAdmin" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("mailboxes", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/microsoftforms.py b/src/azure/connectors/aio/microsoftforms.py new file mode 100644 index 0000000..0b30575 --- /dev/null +++ b/src/azure/connectors/aio/microsoftforms.py @@ -0,0 +1,406 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# MicrosoftformsClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.microsoftforms import ( + FormsList, + GetFormDetailsByIdResult, + GetFormResponseByIdResult, + NewResponses, + WebhookPayload, + WebhookRequestBody, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "MicrosoftformsClient", + "FormsList", + "GetFormDetailsByIdResult", + "GetFormResponseByIdResult", + "NewResponses", + "WebhookPayload", + "WebhookRequestBody", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class MicrosoftformsClient(ConnectorClientBase): + """Typed client for microsoftforms connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a MicrosoftformsClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "microsoftforms" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def get_form_response_by_id( + self, + form_id: str, + response_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get response details + + This action retrieves a form response + + Swagger operation ID: `GetFormResponseById`. + + Args: + form_id: Unique identifier of the form. + response_id: Unique identifier of the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/formapi/api/forms('{quote(str(form_id), safe='')}')/responses" + ) + query_params = [] + value = str(response_id) + if isinstance(response_id, bool): + value = value.lower() + query_params.append(f"response_id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_form_details_by_id( + self, + form_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get form details + + This action retrieves the details of a form + + Swagger operation ID: `GetFormDetailsById`. + + Args: + form_id: Unique identifier of the form. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/formapi/api/forms('{quote(str(form_id), safe='')}')" + ) + query_params = [] + query_params.append( + "$select=" + quote( + "title,modifiedDate,createdDate,status,createdBy", + safe='' + ) + ) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_forms( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List forms + + This operation returns a list of forms in your account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListForms`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/formapi/api/forms" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_questions( + self, + form_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get questions + + Get questions definition in a form. + + Swagger operation ID: `GetQuestions`. + + Args: + form_id: Unique id of the form. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/formapi/api/forms('{quote(str(form_id), safe='')}')/questions" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) diff --git a/src/azure/connectors/aio/monday.py b/src/azure/connectors/aio/monday.py new file mode 100644 index 0000000..e0a95e8 --- /dev/null +++ b/src/azure/connectors/aio/monday.py @@ -0,0 +1,2419 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# MondayClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.monday import ( + CreateBoardInput, + CreateBoardResponse, + CreateColumnInput, + CreateColumnResponse, + CreateGroupInput, + CreateGroupResponse, + CreateItemInput, + CreateItemResponse, + CreateNotificationInput, + CreateNotificationResponse, + CreateSubitemInput, + CreateSubitemResponse, + CreateUpdateInput, + CreateUpdateResponse, + CreateWorkspaceInput, + CreateWorkspaceResponse, + DuplicateBoardInput, + DuplicateBoardResponse, + DynamicGetColumnNamesForUpdateWebhook, + DynamicGetColumnNamesForWebhook, + DynamicGetGetItemsSchema, + DynamicGetSubitemColumnNamesForWebhook, + DynamicResponseGetListSchema, + DynamicResponseGetListSchemaGet, + DynamicResponseGetSingleColumnSchema, + FieldBoard, + FieldColumnsToUpdateSingleColumn, + FieldWorkspace, + GetColumnNamesSchemaForColumnChangesWebhookResponse, + GetColumnNamesSchemaForItemNameChangeWebhookResponse, + GetColumnNamesSchemaForSubitemNameChangeWebhookResponse, + GetColumnNamesSchemaForUpdateWebhookResponse, + GetColumnNamesSchemaForWebhookResponse, + GetColumnNamesSchemaResponse, + GetSchemaForGetItemsActionResponse, + GetSingleColumnSchemaResponse, + GetSubitemColumnNamesForGetSubitems, + GetSubitemColumnNamesResponse, + GetSubitemSchemaResponse, + GetTagsResponse, + GetUsersResponse, + GetWorkspacesResponse, + MoveItemToGroupInput, + MoveItemToGroupResponse, + UpdateItemColumnInput, + UpdateItemColumnResponse, + UpdateMultipleItemColumnsInput, + UpdateMultipleItemColumnsResponse, + WebhookAnyColumnChangesInput, + WebhookAnyColumnChangesResponse, + WebhookChangeNameInput, + WebhookChangeNameResponse, + WebhookChangeSubitemNameInput, + WebhookChangeSubitemNameResponse, + WebhookColumnChangesInput, + WebhookColumnChangesResponse, + WebhookCreateItemInput, + WebhookCreateItemResponse, + WebhookCreateSubitemInput, + WebhookCreateSubitemResponse, + WebhookCreateUpdateInput, + WebhookCreateUpdateResponse, + WebhookSubitemColumnChangesInput, + WebhookSubitemColumnChangesResponse, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "MondayClient", + "CreateBoardInput", + "CreateBoardResponse", + "CreateColumnInput", + "CreateColumnResponse", + "CreateGroupInput", + "CreateGroupResponse", + "CreateItemInput", + "CreateItemResponse", + "CreateNotificationInput", + "CreateNotificationResponse", + "CreateSubitemInput", + "CreateSubitemResponse", + "CreateUpdateInput", + "CreateUpdateResponse", + "CreateWorkspaceInput", + "CreateWorkspaceResponse", + "DuplicateBoardInput", + "DuplicateBoardResponse", + "DynamicGetColumnNamesForUpdateWebhook", + "DynamicGetColumnNamesForWebhook", + "DynamicGetGetItemsSchema", + "DynamicGetSubitemColumnNamesForWebhook", + "DynamicResponseGetListSchema", + "DynamicResponseGetListSchemaGet", + "DynamicResponseGetSingleColumnSchema", + "FieldBoard", + "FieldColumnsToUpdateSingleColumn", + "FieldWorkspace", + "GetColumnNamesSchemaForColumnChangesWebhookResponse", + "GetColumnNamesSchemaForItemNameChangeWebhookResponse", + "GetColumnNamesSchemaForSubitemNameChangeWebhookResponse", + "GetColumnNamesSchemaForUpdateWebhookResponse", + "GetColumnNamesSchemaForWebhookResponse", + "GetColumnNamesSchemaResponse", + "GetSchemaForGetItemsActionResponse", + "GetSingleColumnSchemaResponse", + "GetSubitemColumnNamesForGetSubitems", + "GetSubitemColumnNamesResponse", + "GetSubitemSchemaResponse", + "GetTagsResponse", + "GetUsersResponse", + "GetWorkspacesResponse", + "MoveItemToGroupInput", + "MoveItemToGroupResponse", + "UpdateItemColumnInput", + "UpdateItemColumnResponse", + "UpdateMultipleItemColumnsInput", + "UpdateMultipleItemColumnsResponse", + "WebhookAnyColumnChangesInput", + "WebhookAnyColumnChangesResponse", + "WebhookChangeNameInput", + "WebhookChangeNameResponse", + "WebhookChangeSubitemNameInput", + "WebhookChangeSubitemNameResponse", + "WebhookColumnChangesInput", + "WebhookColumnChangesResponse", + "WebhookCreateItemInput", + "WebhookCreateItemResponse", + "WebhookCreateSubitemInput", + "WebhookCreateSubitemResponse", + "WebhookCreateUpdateInput", + "WebhookCreateUpdateResponse", + "WebhookSubitemColumnChangesInput", + "WebhookSubitemColumnChangesResponse", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class MondayClient(ConnectorClientBase): + """Typed client for monday connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a MondayClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "monday" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_item( + self, + input: CreateItemInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create an item + + Creates an item in the selected monday.com board and group. + + Swagger operation ID: `CreateItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/executePowerAutomateAction/CreateItem" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def duplicate_board( + self, + input: DuplicateBoardInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Duplicate a board + + Duplicates a board in monday.com. + + Swagger operation ID: `DuplicateBoard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/executePowerAutomateAction/DuplicateBoard" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_board( + self, + input: CreateBoardInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a board + + Creates a board in monday.com. + + Swagger operation ID: `CreateBoard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/executePowerAutomateAction/CreateBoard" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_column( + self, + input: CreateColumnInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a column + + Creates a column in monday.com for the specified board. + + Swagger operation ID: `CreateColumn`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/executePowerAutomateAction/CreateColumn" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_group( + self, + input: CreateGroupInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a group + + Creates a group in monday.com for the specified board. + + Swagger operation ID: `CreateGroup`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/executePowerAutomateAction/CreateGroup" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_item_column( + self, + input: UpdateItemColumnInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update an item's column value + + Updates a single item's column. If the value is blank, the column value + will be cleared. + + Swagger operation ID: `UpdateItemColumn`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/executePowerAutomateAction/UpdateItemColumn" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_multiple_item_columns( + self, + input: UpdateMultipleItemColumnsInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update multiple item column values + + Updates multiple item columns. Leave the column value blank to keep the + current value. + + Swagger operation ID: `UpdateMultipleItemColumns`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/executePowerAutomateAction/UpdateMultipleItemColumns" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def move_item_to_group( + self, + input: MoveItemToGroupInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Move an item to a group + + Moves an item to another group on the same board. + + Swagger operation ID: `MoveItemToGroup`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/executePowerAutomateAction/MoveItemToGroup" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_notification( + self, + input: CreateNotificationInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a notification + + Creates a notification in monday.com for a user for either a specific + board or item. + + Swagger operation ID: `CreateNotification`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/executePowerAutomateAction/CreateNotification" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_subitem( + self, + input: CreateSubitemInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a subitem + + Creates a subitem in monday.com for the selected board and parent item. + + Swagger operation ID: `CreateSubitem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/executePowerAutomateAction/CreateSubitem" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_subitems( + self, + workspace_id: str, + board_id: str, + item_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get subitems + + Gets subitems in monday.com for a specific item in a board. + + Swagger operation ID: `GetSubitems`. + + Args: + workspace_id: Select a workspace from the drop-down or specify a + workspace ID. + board_id: Select the item's board from the drop-down or specify a + board ID. + item_id: Specify an item ID to retrieve the subitems for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/getData/getSubitems" + query_params = [] + value = str(workspace_id) + if isinstance(workspace_id, bool): + value = value.lower() + query_params.append(f"workspaceId={quote(value, safe='')}") + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"boardId={quote(value, safe='')}") + value = str(item_id) + if isinstance(item_id, bool): + value = value.lower() + query_params.append(f"itemId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_update( + self, + input: CreateUpdateInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create an update + + Creates an update in monday.com for a specific item. + + Swagger operation ID: `CreateUpdate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/executePowerAutomateAction/CreateUpdate" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_item_by_id( + self, + item_id: str, + workspace_id: str, + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get an item by ID + + Gets a monday.com item using the specified item ID and board. + + Swagger operation ID: `GetItemById`. + + Args: + item_id: Specify an item ID to retrieve. + workspace_id: Select the item's workspace from the drop-down or + specify a workspace ID. + board_id: Select the item's board from the drop-down or specify a + board ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/getData/getItemById" + query_params = [] + value = str(item_id) + if isinstance(item_id, bool): + value = value.lower() + query_params.append(f"itemId={quote(value, safe='')}") + value = str(workspace_id) + if isinstance(workspace_id, bool): + value = value.lower() + query_params.append(f"workspaceId={quote(value, safe='')}") + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"boardId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_workspace( + self, + input: CreateWorkspaceInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a workspace + + Creates a monday.com workspace with a user-specified name and + description. + + Swagger operation ID: `CreateWorkspace_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/executePowerAutomateAction/CreateWorkspaceV2" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_items( + self, + workspace_id: str, + board_id: str, + group_id: str, + *, + filter1_column: Optional[str] = None, + filter1_operator: Optional[str] = None, + filter1_value: Optional[str] = None, + filter2_column: Optional[str] = None, + filter2_operator: Optional[str] = None, + filter2_value: Optional[str] = None, + filter3_column: Optional[str] = None, + filter3_operator: Optional[str] = None, + filter3_value: Optional[str] = None, + filter4_column: Optional[str] = None, + filter4_operator: Optional[str] = None, + filter4_value: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get items + + Gets items in monday.com for a specific board and group. Filter items + by column values using the filters found under advanced options. More + info on filtering can be found here: + https://plugingenie.com/docs/filtering-items. + + Swagger operation ID: `GetItems_V2`. + + Args: + workspace_id: Select a workspace from the drop-down or specify a + workspace ID. + board_id: Select a board from the drop-down or specify a board ID. + group_id: Select a group from the drop-down or specify a group ID. + filter1_column: Select a column from the drop-down or specify a + column ID. + filter1_operator: Select an operator from the drop-down. + filter1_value: Specify a value (if applicable). + filter2_column: Select a column from the drop-down or specify a + column ID. + filter2_operator: Select an operator from the drop-down. + filter2_value: Specify a value (if applicable). + filter3_column: Select a column from the drop-down or specify a + column ID. + filter3_operator: Select an operator from the drop-down. + filter3_value: Specify a value (if applicable). + filter4_column: Select a column from the drop-down or specify a + column ID. + filter4_operator: Select an operator from the drop-down. + filter4_value: Specify a value (if applicable). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/getData/getItemsV2" + query_params = [] + value = str(workspace_id) + if isinstance(workspace_id, bool): + value = value.lower() + query_params.append(f"workspaceId={quote(value, safe='')}") + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"boardId={quote(value, safe='')}") + value = str(group_id) + if isinstance(group_id, bool): + value = value.lower() + query_params.append(f"groupId={quote(value, safe='')}") + if filter1_column is not None: + value = str(filter1_column) + if isinstance(filter1_column, bool): + value = value.lower() + query_params.append(f"filter1Column={quote(value, safe='')}") + if filter1_operator is not None: + value = str(filter1_operator) + if isinstance(filter1_operator, bool): + value = value.lower() + query_params.append(f"filter1Operator={quote(value, safe='')}") + if filter1_value is not None: + value = str(filter1_value) + if isinstance(filter1_value, bool): + value = value.lower() + query_params.append(f"filter1Value={quote(value, safe='')}") + if filter2_column is not None: + value = str(filter2_column) + if isinstance(filter2_column, bool): + value = value.lower() + query_params.append(f"filter2Column={quote(value, safe='')}") + if filter2_operator is not None: + value = str(filter2_operator) + if isinstance(filter2_operator, bool): + value = value.lower() + query_params.append(f"filter2Operator={quote(value, safe='')}") + if filter2_value is not None: + value = str(filter2_value) + if isinstance(filter2_value, bool): + value = value.lower() + query_params.append(f"filter2Value={quote(value, safe='')}") + if filter3_column is not None: + value = str(filter3_column) + if isinstance(filter3_column, bool): + value = value.lower() + query_params.append(f"filter3Column={quote(value, safe='')}") + if filter3_operator is not None: + value = str(filter3_operator) + if isinstance(filter3_operator, bool): + value = value.lower() + query_params.append(f"filter3Operator={quote(value, safe='')}") + if filter3_value is not None: + value = str(filter3_value) + if isinstance(filter3_value, bool): + value = value.lower() + query_params.append(f"filter3Value={quote(value, safe='')}") + if filter4_column is not None: + value = str(filter4_column) + if isinstance(filter4_column, bool): + value = value.lower() + query_params.append(f"filter4Column={quote(value, safe='')}") + if filter4_operator is not None: + value = str(filter4_operator) + if isinstance(filter4_operator, bool): + value = value.lower() + query_params.append(f"filter4Operator={quote(value, safe='')}") + if filter4_value is not None: + value = str(filter4_value) + if isinstance(filter4_value, bool): + value = value.lower() + query_params.append(f"filter4Value={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_tags( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get tags + + This operation gets monday.com tags. + + Swagger operation ID: `GetTags_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/getData/getTagsV2" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_users( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get users + + This operation gets the name, email, and ID of users in your monday.com + account. + + Swagger operation ID: `GetUsers_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/getData/getUsersV2" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_workspaces( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get workspaces + + This operation gets the workspaces from monday.com. + + Swagger operation ID: `GetWorkspaces_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/getData/getWorkspacesV2" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_boards( + self, + *, + workspace_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get boards + + This operation gets the boards from monday.com. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetBoards`. + + Args: + workspace_id: Specify the ID of the monday.com workspace. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/getData/getBoards" + query_params = [] + if workspace_id is not None: + value = str(workspace_id) + if isinstance(workspace_id, bool): + value = value.lower() + query_params.append(f"workspaceId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_groups_for_get_items( + self, + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get groups for the Get Items operation + + This operation gets the groups from monday.com, which includes the + option to select all groups. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetGroupsForGetItems`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/getData/getGroupsForGetItems" + ) + query_params = [] + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"boardId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_columns_for_item_filtering( + self, + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get columns for item filtering + + This operation gets the columns from monday.com for item filtering. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetColumnsForItemFiltering`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/getData/getColumnsForItemFiltering" + ) + query_params = [] + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"boardId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_column_filter_operator( + self, + board_id: str, + *, + column_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get column filter operator + + This operation gets the available item filter operator for the selected + monday.com column. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetColumnFilterOperator`. + + Args: + board_id: Specify the ID of a monday.com board. + column_id: Specify the ID of a monday.com column. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/getData/getColumnFilterOperator" + ) + query_params = [] + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"boardId={quote(value, safe='')}") + if column_id is not None: + value = str(column_id) + if isinstance(column_id, bool): + value = value.lower() + query_params.append(f"columnId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_column_names_schema( + self, + *, + board_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get column names for a board ID + + This operation gets the column names for a board ID. + + Swagger operation ID: `GetColumnNamesSchema`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/getSchema/getColumnNames" + ) + query_params = [] + if board_id is not None: + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"boardId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_single_column_schema( + self, + *, + board_id: Optional[str] = None, + column_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Gets single column schema for a board ID + + This operation gets the single column schema for a board ID. + + Swagger operation ID: `GetSingleColumnSchema`. + + Args: + board_id: Specify the ID of a monday.com board. + column_id: Specify the ID of a monday.com column. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/getSchema/getSingleColumnSchema" + ) + query_params = [] + if board_id is not None: + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"boardId={quote(value, safe='')}") + if column_id is not None: + value = str(column_id) + if isinstance(column_id, bool): + value = value.lower() + query_params.append(f"columnId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_column_names_schema_for_webhook( + self, + *, + board_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get column names for a board ID for a webhook + + This operation gets the column names for a board ID for a webhook + (includes itemId). + + Swagger operation ID: `GetColumnNamesSchemaForWebhook`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/getSchema/getColumnNamesForWebhook" + ) + query_params = [] + if board_id is not None: + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"boardId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_schema_for_get_items_action( + self, + *, + board_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get column names for a board ID for a webhook + + This operation gets the schema for the GetItems action. + + Swagger operation ID: `GetSchemaForGetItemsAction`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/getSchema/getSchemaForGetItemsAction" + ) + query_params = [] + if board_id is not None: + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"boardId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_column_names_schema_for_update_webhook( + self, + *, + board_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get column names for a board ID for an update webhook + + This operation gets the column names for a board ID for a webhook + (includes itemId). + + Swagger operation ID: `GetColumnNamesSchemaForUpdateWebhook`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/getSchema/getColumnNamesForUpdateWebhook" + ) + query_params = [] + if board_id is not None: + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"boardId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_subitem_column_names( + self, + parent_board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get subitem column names + + Gets subitem column names in monday.com given a board ID. + + Swagger operation ID: `GetSubitemColumnNames`. + + Args: + parent_board_id: Specify the ID of the monday.com parent board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/getSchema/getSubitemColumnNames" + ) + query_params = [] + value = str(parent_board_id) + if isinstance(parent_board_id, bool): + value = value.lower() + query_params.append(f"parentBoardId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_subitem_schema( + self, + parent_board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get subitem column names + + Gets subitem schema in monday.com given a board ID. + + Swagger operation ID: `GetSubitemSchema`. + + Args: + parent_board_id: Specify the ID of the monday.com parent board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/getSchema/getSubitemSchema" + ) + query_params = [] + value = str(parent_board_id) + if isinstance(parent_board_id, bool): + value = value.lower() + query_params.append(f"parentBoardId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_column_names_schema_for_item_name_change_webhook( + self, + *, + board_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get column names schema for column changes + + This operation gets the column names for a board ID for a webhook when + the item's name changes. + + Swagger operation ID: `GetColumnNamesSchemaForItemNameChangeWebhook`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/getSchema/getColumnNamesForItemNameChangeWebhook" + ) + query_params = [] + if board_id is not None: + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"boardId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_column_names_schema_for_subitem_name_change_webhook( + self, + parent_board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get column names schema for column changes + + This operation gets the column names for a board ID for a webhook when + the subitem's name changes. + + Swagger operation ID: + `GetColumnNamesSchemaForSubitemNameChangeWebhook`. + + Args: + parent_board_id: Specify the ID of the monday.com parent board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/getSchema/getColumnNamesForSubitemNameChangeWebhook" + ) + query_params = [] + value = str(parent_board_id) + if isinstance(parent_board_id, bool): + value = value.lower() + query_params.append(f"parentBoardId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_column_names_schema_for_column_changes_webhook( + self, + *, + board_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get column names schema for column changes + + This operation gets the column names for a board ID for a webhook + (includes itemId). + + Swagger operation ID: `GetColumnNamesSchemaForColumnChangesWebhook`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/getSchema/getColumnNamesForColumnChangesWebhook" + ) + query_params = [] + if board_id is not None: + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"boardId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/mq.py b/src/azure/connectors/aio/mq.py new file mode 100644 index 0000000..9ac8ea2 --- /dev/null +++ b/src/azure/connectors/aio/mq.py @@ -0,0 +1,490 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# MqClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping +import json + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, +) + +from azure.connectors.mq import ( + Item, + ItemsList, + MultipleGetValidOptions, + ObjectEntity, + ProcedureMetadata, + SendResponse, + SendValidDataOptions, + SendValidDataOptionsArray, + SingleGetValidOptions, +) + +__all__ = [ + "MqClient", + "Item", + "ItemsList", + "MultipleGetValidOptions", + "ObjectEntity", + "ProcedureMetadata", + "SendResponse", + "SendValidDataOptions", + "SendValidDataOptionsArray", + "SingleGetValidOptions", +] + + +# Type Definitions + +# Client Class + +class MqClient(ConnectorClientBase): + """Typed client for mq connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a MqClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "mq" + + async def delete( + self, + input: SingleGetValidOptions | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete message + + Deletes one message from the queue, by doing a destructive get. + + Swagger operation ID: `DeleteV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/delete" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_all( + self, + input: MultipleGetValidOptions | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete messages + + Deletes messages from the queue, by doing a destructive get. + + Swagger operation ID: `DeleteAllV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/deleteall" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def read( + self, + input: SingleGetValidOptions | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Browse message + + Browse one message from the queue. + + Swagger operation ID: `ReadV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/read" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def read_all( + self, + input: MultipleGetValidOptions | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Browse messages + + Browse messages in a queue. + + Swagger operation ID: `ReadAllV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/readall" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def receive( + self, + input: SingleGetValidOptions | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Receive message + + Returns one message from the queue, by doing a destructive get. + + Swagger operation ID: `ReceiveV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/receive" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def receive_all( + self, + input: MultipleGetValidOptions | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Receive messages + + Returns messages from the queue, by doing a destructive get. + + Swagger operation ID: `ReceiveAllV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/receiveall" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send( + self, + input: SendValidDataOptions | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send message + + Send a message to a queue. + + Swagger operation ID: `SendV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/send" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/msgraphgroupsanduser.py b/src/azure/connectors/aio/msgraphgroupsanduser.py new file mode 100644 index 0000000..71ec9df --- /dev/null +++ b/src/azure/connectors/aio/msgraphgroupsanduser.py @@ -0,0 +1,716 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# MsgraphgroupsanduserClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.msgraphgroupsanduser import ( + GetGroupPropertiesResponse, + GetMemberGroupsInput, + GetMemberGroupsResponse, + GetMemberLicenseDetailsResponse, + ListDirectGroupMembersResponse, + ListGroupsByDisplayNameSearchResponse, + ListSubscribedSkusResponse, + ListUsersResponse, +) + +__all__ = [ + "MsgraphgroupsanduserClient", + "GetGroupPropertiesResponse", + "GetMemberGroupsInput", + "GetMemberGroupsResponse", + "GetMemberLicenseDetailsResponse", + "ListDirectGroupMembersResponse", + "ListGroupsByDisplayNameSearchResponse", + "ListSubscribedSkusResponse", + "ListUsersResponse", +] + + +# Type Definitions + +# Client Class + +class MsgraphgroupsanduserClient(ConnectorClientBase): + """Typed client for msgraphgroupsanduser connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a MsgraphgroupsanduserClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "msgraphgroupsanduser" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_users( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Users + + Retrieve all users in the organization (Microsoft Entra ID Tenant) + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListUsers`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/users" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_groups_by_display_name_search( + self, + *, + search: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Groups By Display Name Search + + Retrieve groups by searching group's display name + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListGroupsByDisplayNameSearch`. + + Args: + search: Search by keyword in display name of the Microsoft Entra ID + group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/groups" + query_params = [] + query_params.append("$count=" + quote("true", safe='')) + if search is not None: + value = str(search) + if isinstance(search, bool): + value = value.lower() + query_params.append(f"$search={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_subscribed_skus( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Subscribed Skus + + Details of organization's subscribed license plan SKUs + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListSubscribedSkus`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/subscribedSkus" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_direct_group_members( + self, + group_id: str, + *, + filter: Optional[str] = None, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Direct Group Members + + Retrieve direct members of a group with count + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListDirectGroupMembers`. + + Args: + group_id: Object ID of the Microsoft Entra ID group. + filter: Filter By. + select: Select which columns to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/groups/{quote(str(group_id), safe='')}/members" + ) + query_params = [] + query_params.append("$count=" + quote("true", safe='')) + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_member_license_details( + self, + id: str, + *, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Member License Details + + Retrieve group member(user)'s license details + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMemberLicenseDetails`. + + Args: + id: Object ID of the Microsoft Entra ID member(user). + select: Selection of data points(columns). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/users/{quote(str(id), safe='')}/licenseDetails" + ) + query_params = [] + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_group_properties( + self, + group_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Group Properties + + Retrieve properties and relationships of an Microsoft Entra ID group + + Swagger operation ID: `GetGroupProperties`. + + Args: + group_id: Object ID of the Microsoft Entra ID group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/groups/{quote(str(group_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_member_groups( + self, + input: GetMemberGroupsInput | Mapping[str, Any], + member_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[str]: + """ + Get Member Groups + + Group memberships for a user (member) + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMemberGroups`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + member_id: Object ID of the Microsoft Entra ID member(user). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[str]: An Azure Core pager over connector results. + Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/users/{quote(str(member_id), safe='')}/getMemberGroups" + ) + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[str]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/office365.py b/src/azure/connectors/aio/office365.py new file mode 100644 index 0000000..c76117f --- /dev/null +++ b/src/azure/connectors/aio/office365.py @@ -0,0 +1,3698 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# Office365Client.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.office365 import ( + ApprovalEmailResponse, + ApprovalEmailSubscription, + ApprovalMessage, + AssignCategoryBulkInput, + Attendee, + AutomaticRepliesSettingClient, + BatchItemFailureResult, + BatchOperationResult, + BatchResponseClientReceiveMessage, + BatchResponseGraphClientReceiveMessage, + BatchResponseSensitivityLabel, + BlobDataSetsMetadata, + CalendarEventBackend, + CalendarEventClient, + CalendarEventClientReceive, + CalendarEventClientReceiveStringEnums, + CalendarEventClientWithActionType, + CalendarEventHtmlClient, + CalendarEventList, + CalendarEventListClientReceive, + CalendarEventListWithActionType, + CalendarGetTablesResponse, + ClientReceiveFileAttachment, + ClientReceiveMessage, + ClientReceiveMessageStringEnums, + ClientSendAttachment, + ClientSendMessage, + ClientSubscription, + Contact, + ContactResponse, + DataSet, + DataSetsList, + DataSetsMetadata, + DateTimeTimeZone, + DirectForwardMessage, + DraftEmailInput, + EmailAddress, + EmailAddressV2, + EntityListResponseCalendarEventBackend, + EntityListResponseCalendarEventClientReceiveStringEnums, + EntityListResponseContactResponse, + EntityListResponseFilePickerFile, + EntityListResponseGraphCalendarEventClientReceive, + EntityListResponseGraphContactFolder, + EntityListResponseTable, + FilePickerFile, + FindMeetingTimesInput, + FindMeetingTimesResponse, + GeoCoordinates, + GetAttachmentResponse, + GetMailTipsInput, + GetMailTipsResponse, + GetRoomListsResponse, + GetRoomsInRoomListResponse, + GetRoomsResponse, + GraphCalendarEventClient, + GraphCalendarEventClientReceive, + GraphCalendarEventClientWithActionType, + GraphCalendarEventListClientReceive, + GraphCalendarEventListWithActionType, + GraphClientReceiveFileAttachment, + GraphClientReceiveMessage, + GraphContactFolder, + GraphOutlookCategory, + InternetMessageHeader, + ItemBody, + Location, + LocationConstraint, + MCPQueryRequest, + MCPQueryResponse, + MailTipsAutomaticReplies, + MailTipsClientReceive, + MarkAsReadInput, + MeetingTimeSuggestions, + MessageWithOptions, + ObjectEntity, + ObjectWithoutType, + OptionsEmailSubscription, + OutlookReceiveAttachment, + OutlookReceiveMessage, + PaginatedListResponseCalendarEventClientReceiveStringEnums, + PassThroughNativeQuery, + PatternedRecurrence, + PhysicalAddress, + Procedure, + ReceiveMessageMetadata, + Recipient, + RecurrencePattern, + RecurrenceRange, + ReplyEmailInput, + ReplyMessage, + ResponseStatus, + ResponseToEventInvite, + SendEmailInput, + SensitivityLabel, + SensitivityLabelMetadata, + SetAutomaticRepliesSettingInput, + SetAutomaticRepliesSettingResponse, + SharedMailboxClientSendMessage, + SharedMailboxSendEmailInput, + SubscriptionEvent, + SubscriptionPayloadEntityOutlookReceiveMessage, + SubscriptionPayloadEntitySubscriptionEvent, + SubscriptionPayloadOutlookReceiveMessage, + SubscriptionPayloadSubscriptionEvent, + SubscriptionResponse, + Table, + TableCapabilitiesMetadata, + TableFilterRestrictionsMetadata, + TableMetadata, + TableSelectRestrictionsMetadata, + TableSortRestrictionsMetadata, + TabularDataSetsMetadata, + TriggerBatchResponseClientReceiveMessage, + TriggerBatchResponseGraphClientReceiveMessage, + TriggerBatchResponseReceiveMessageMetadata, + UpdateEmailFlag, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "Office365Client", + "ApprovalEmailResponse", + "ApprovalEmailSubscription", + "ApprovalMessage", + "AssignCategoryBulkInput", + "Attendee", + "AutomaticRepliesSettingClient", + "BatchItemFailureResult", + "BatchOperationResult", + "BatchResponseClientReceiveMessage", + "BatchResponseGraphClientReceiveMessage", + "BatchResponseSensitivityLabel", + "BlobDataSetsMetadata", + "CalendarEventBackend", + "CalendarEventClient", + "CalendarEventClientReceive", + "CalendarEventClientReceiveStringEnums", + "CalendarEventClientWithActionType", + "CalendarEventHtmlClient", + "CalendarEventList", + "CalendarEventListClientReceive", + "CalendarEventListWithActionType", + "CalendarGetTablesResponse", + "ClientReceiveFileAttachment", + "ClientReceiveMessage", + "ClientReceiveMessageStringEnums", + "ClientSendAttachment", + "ClientSendMessage", + "ClientSubscription", + "Contact", + "ContactResponse", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "DateTimeTimeZone", + "DirectForwardMessage", + "DraftEmailInput", + "EmailAddress", + "EmailAddressV2", + "EntityListResponseCalendarEventBackend", + "EntityListResponseCalendarEventClientReceiveStringEnums", + "EntityListResponseContactResponse", + "EntityListResponseFilePickerFile", + "EntityListResponseGraphCalendarEventClientReceive", + "EntityListResponseGraphContactFolder", + "EntityListResponseTable", + "FilePickerFile", + "FindMeetingTimesInput", + "FindMeetingTimesResponse", + "GeoCoordinates", + "GetAttachmentResponse", + "GetMailTipsInput", + "GetMailTipsResponse", + "GetRoomListsResponse", + "GetRoomsInRoomListResponse", + "GetRoomsResponse", + "GraphCalendarEventClient", + "GraphCalendarEventClientReceive", + "GraphCalendarEventClientWithActionType", + "GraphCalendarEventListClientReceive", + "GraphCalendarEventListWithActionType", + "GraphClientReceiveFileAttachment", + "GraphClientReceiveMessage", + "GraphContactFolder", + "GraphOutlookCategory", + "InternetMessageHeader", + "ItemBody", + "Location", + "LocationConstraint", + "MCPQueryRequest", + "MCPQueryResponse", + "MailTipsAutomaticReplies", + "MailTipsClientReceive", + "MarkAsReadInput", + "MeetingTimeSuggestions", + "MessageWithOptions", + "ObjectEntity", + "ObjectWithoutType", + "OptionsEmailSubscription", + "OutlookReceiveAttachment", + "OutlookReceiveMessage", + "PaginatedListResponseCalendarEventClientReceiveStringEnums", + "PassThroughNativeQuery", + "PatternedRecurrence", + "PhysicalAddress", + "Procedure", + "ReceiveMessageMetadata", + "Recipient", + "RecurrencePattern", + "RecurrenceRange", + "ReplyEmailInput", + "ReplyMessage", + "ResponseStatus", + "ResponseToEventInvite", + "SendEmailInput", + "SensitivityLabel", + "SensitivityLabelMetadata", + "SetAutomaticRepliesSettingInput", + "SetAutomaticRepliesSettingResponse", + "SharedMailboxClientSendMessage", + "SharedMailboxSendEmailInput", + "SubscriptionEvent", + "SubscriptionPayloadEntityOutlookReceiveMessage", + "SubscriptionPayloadEntitySubscriptionEvent", + "SubscriptionPayloadOutlookReceiveMessage", + "SubscriptionPayloadSubscriptionEvent", + "SubscriptionResponse", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TabularDataSetsMetadata", + "TriggerBatchResponseClientReceiveMessage", + "TriggerBatchResponseGraphClientReceiveMessage", + "TriggerBatchResponseReceiveMessageMetadata", + "UpdateEmailFlag", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class Office365Client(ConnectorClientBase): + """Typed client for office365 connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a Office365Client. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "office365" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_outlook_category_names( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Outlook category names + + This operation gets Outlook category display names. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetOutlookCategoryNames`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Categories" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def draft_email( + self, + input: DraftEmailInput | Mapping[str, Any], + *, + message_id: Optional[str] = None, + draft_type: Optional[str] = None, + comment: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Draft an email message + + This operation drafts an email message. + + Swagger operation ID: `DraftEmail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Message Id. + draft_type: Draft Type. + comment: Draft Comment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Draft" + query_params = [] + if message_id is not None: + value = str(message_id) + if isinstance(message_id, bool): + value = value.lower() + query_params.append(f"messageId={quote(value, safe='')}") + if draft_type is not None: + value = str(draft_type) + if isinstance(draft_type, bool): + value = value.lower() + query_params.append(f"draftType={quote(value, safe='')}") + if comment is not None: + value = str(comment) + if isinstance(comment, bool): + value = value.lower() + query_params.append(f"comment={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_draft_email( + self, + input: DraftEmailInput | Mapping[str, Any], + message_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Updates an email Draft message + + This operation updates an an email Draft message. + + Swagger operation ID: `UpdateDraftEmail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Message Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Draft" + query_params = [] + value = str(message_id) + if isinstance(message_id, bool): + value = value.lower() + query_params.append(f"messageId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + async def send_draft_email( + self, + message_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Send a Draft message + + This operation sends a Draft message. + + Swagger operation ID: `SendDraftEmail`. + + Args: + message_id: Message Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Draft/Send/{quote(str(message_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def assign_category( + self, + message_id: str, + category: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Assigns an Outlook category + + This operation assigns an Outlook category to an email. + + Swagger operation ID: `AssignCategory`. + + Args: + message_id: Message Id. + category: Category. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/Mail/Category" + query_params = [] + value = str(message_id) + if isinstance(message_id, bool): + value = value.lower() + query_params.append(f"messageId={quote(value, safe='')}") + value = str(category) + if isinstance(category, bool): + value = value.lower() + query_params.append(f"category={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def assign_category_bulk( + self, + input: AssignCategoryBulkInput, + category_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Assign a category to multiple emails + + This operation assigns an Outlook category to multiple emails. + + Swagger operation ID: `AssignCategoryBulk`. + + Args: + input: The request body. + category_name: Category Name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Mail/Category/Bulk/{quote(str(category_name), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_mail_with_options( + self, + input: OptionsEmailSubscription | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send email with options + + This operation sends an email with multiple options and waits for the + recipient to respond back with one of the options. Please refer to the + following link regarding the support of actionable messages in + different mail clients: + https://docs.microsoft.com/outlook/actionable-messages/#outlook-version-requirements-for-actionable-messages. + + Swagger operation ID: `SendMailWithOptions`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/mailwithoptions/$subscriptions" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_approval_mail( + self, + input: ApprovalEmailSubscription | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send approval email + + This operation sends an approval email and waits for a response from + the recipient. Please refer to the following link regarding the support + of actionable messages in different mail clients: + https://docs.microsoft.com/outlook/actionable-messages/#outlook-version-requirements-for-actionable-messages. + + Swagger operation ID: `SendApprovalMail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/approvalmail/$subscriptions" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_my_contact_photo( + self, + input: bytes, + folder: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update my contact's photo + + Updates the photo of the specified contact of the current user. The + size of the photo must be less than 4 MB. + + Swagger operation ID: `UpdateMyContactPhoto`. + + Args: + input: The binary request body. + folder: Select a contacts folder. + id: Unique identifier of a contact to update photo. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/me" + f"/contactFolders" + f"/{quote(quote(str(folder), safe=''), safe='')}" + f"/contacts" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/photo" + f"/$value" + ) + + response = await self.http_client.send( + "PUT", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + async def http_request( + self, + input: bytes, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send an HTTP request + + Construct a Microsoft Graph REST API request to invoke. These segments + are supported: 1st segement: /me, /users/ 2nd segment: + messages, mailFolders, events, calendar, calendars, outlook, + inferenceClassification. Learn more: + https://docs.microsoft.com/en-us/graph/use-the-api. + + Swagger operation ID: `HttpRequest`. + + Args: + input: The binary request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/codeless/httprequest" + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def mcp_emails_management( + self, + input: MCPQueryRequest | Mapping[str, Any], + *, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Email Management MCP Server (deprecated) + + This MCP server manages email messages from your Office 365 account + + Swagger operation ID: `mcp_EmailsManagement`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + session_id: sessionId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/mcp/EmailsManagement" + query_params = [] + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def mcp_meeting_management( + self, + input: MCPQueryRequest | Mapping[str, Any], + *, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Meeting Management MCP Server (deprecated) + + This MCP server manages events, calendars and meetings + + Swagger operation ID: `mcp_MeetingManagement`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + session_id: sessionId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/mcp/MeetingManagement" + query_params = [] + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def mcp_contacts_management( + self, + input: MCPQueryRequest | Mapping[str, Any], + *, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Contact Management MCP Server + + This MCP server manages contacts + + Swagger operation ID: `mcp_ContactsManagement`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + session_id: sessionId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/mcp/ContactsManagement" + query_params = [] + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def calendar_delete_item( + self, + calendar: str, + event: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete event + + This operation deletes an event in a calendar. + + Swagger operation ID: `CalendarDeleteItem_V2`. + + Args: + calendar: Select a calendar. + event: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/me" + f"/calendars" + f"/{quote(quote(str(calendar), safe=''), safe='')}" + f"/events" + f"/{quote(quote(str(event), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def calendar_get_item( + self, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get event + + This operation gets a specific event from a calendar using Graph API. + + Swagger operation ID: `V3CalendarGetItem`. + + Args: + table: Select a calendar. + id: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/calendars" + f"/v3" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_calendar_get_items( + self, + table: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get events + + This operation gets events from a calendar using Graph API. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `V4CalendarGetItems`. + + Args: + table: Select a calendar. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/calendars" + f"/v4" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_calendar_get_tables( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get calendars + + This operation lists available calendars. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `CalendarGetTables_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/codeless/v1.0/me/calendars" + ) + query_params = [] + query_params.append("skip=" + quote("0", safe='')) + query_params.append("top=" + quote("256", safe='')) + query_params.append("orderBy=" + quote("name", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def calendar_patch_item( + self, + input: GraphCalendarEventClient | Mapping[str, Any], + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update event + + This operation updates an event in a calendar using Graph API. + + Swagger operation ID: `V4CalendarPatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Select a calendar. + id: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/calendars" + f"/v4" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def calendar_post_item( + self, + input: GraphCalendarEventClient | Mapping[str, Any], + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create event + + This operation creates a new event in a calendar. + + Swagger operation ID: `V4CalendarPostItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Select a calendar. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/calendars" + f"/v4" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def contact_delete_item( + self, + folder: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete contact + + This operation deletes a contact from a contacts folder. + + Swagger operation ID: `ContactDeleteItem_V2`. + + Args: + folder: Select a contacts folder. + id: Unique identifier of contact to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/me" + f"/contactFolders" + f"/{quote(quote(str(folder), safe=''), safe='')}" + f"/contacts" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def contact_get_item( + self, + folder: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get contact + + This operation gets a specific contact from a contacts folder. + + Swagger operation ID: `ContactGetItem_V2`. + + Args: + folder: Select a contacts folder. + id: Unique identifier of a contact to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/me" + f"/contactFolders" + f"/{quote(quote(str(folder), safe=''), safe='')}" + f"/contacts" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_contact_get_items( + self, + folder: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get contacts + + This operation gets contacts from a contacts folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ContactGetItems_V2`. + + Args: + folder: Unique identifier of the contacts folder to retrieve. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/me" + f"/contactFolders" + f"/{quote(quote(str(folder), safe=''), safe='')}" + f"/contacts" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_contact_get_tables( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get contact folders + + This operation lists available contacts folders using Graph API + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ContactGetTablesV2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v2/datasets/contacts/tables" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def contact_patch_item( + self, + input: Contact | Mapping[str, Any], + folder: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update contact + + This operation updates a contact in a contacts folder. + + Swagger operation ID: `ContactPatchItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + folder: Select a contacts folder. + id: Unique identifier of contact to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/me" + f"/contactFolders" + f"/{quote(quote(str(folder), safe=''), safe='')}" + f"/contacts" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def contact_post_item( + self, + input: Contact | Mapping[str, Any], + folder: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create contact + + This operation creates a new contact in a contacts folder. + + Swagger operation ID: `ContactPostItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + folder: Select a contacts folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/me" + f"/contactFolders" + f"/{quote(quote(str(folder), safe=''), safe='')}" + f"/contacts" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_email( + self, + message_id: str, + *, + mailbox_address: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete email + + This operation deletes an email by id. + + Swagger operation ID: `DeleteEmail_V2`. + + Args: + message_id: Id of the email to delete. + mailbox_address: Address of the shared mailbox to delete mail from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless/v1.0/me/messages/{quote(str(message_id), safe='')}" + ) + query_params = [] + if mailbox_address is not None: + value = str(mailbox_address) + if isinstance(mailbox_address, bool): + value = value.lower() + query_params.append(f"mailboxAddress={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def export_email( + self, + message_id: str, + *, + mailbox_address: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Export email + + Export the content of the email in the EML file format. + + Swagger operation ID: `ExportEmail_V2`. + + Args: + message_id: Id of the email to export. + mailbox_address: Address of the shared mailbox to export from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/beta" + f"/me" + f"/messages" + f"/{quote(str(message_id), safe='')}" + f"/$value" + ) + query_params = [] + if mailbox_address is not None: + value = str(mailbox_address) + if isinstance(mailbox_address, bool): + value = value.lower() + query_params.append(f"mailboxAddress={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def find_meeting_times( + self, + input: FindMeetingTimesInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Find meeting times + + Find meeting time suggestions based on organizer, attendee + availability, and time or location constraints + + Swagger operation ID: `FindMeetingTimes_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/codeless/beta/me/findMeetingTimes" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def flag( + self, + input: UpdateEmailFlag | Mapping[str, Any], + message_id: str, + *, + mailbox_address: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Flag email + + This operation updates an email flag. + + Swagger operation ID: `Flag_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Id of the email to be flagged. + mailbox_address: Address of the shared mailbox to update mail. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/me" + f"/messages" + f"/{quote(str(message_id), safe='')}" + f"/flag" + ) + query_params = [] + if mailbox_address is not None: + value = str(mailbox_address) + if isinstance(mailbox_address, bool): + value = value.lower() + query_params.append(f"mailboxAddress={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + async def forward_email( + self, + input: DirectForwardMessage | Mapping[str, Any], + message_id: str, + *, + mailbox_address: Optional[str] = None, + extract_sensitivity_label: Optional[bool] = None, + fetch_sensitivity_label_metadata: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Forward an email + + Forward an email. + + Swagger operation ID: `ForwardEmail_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Id of the message to forward. (You can use 'Message Id' + from trigger or 'Get Emails' action output). + mailbox_address: Address of the shared mailbox to forward mail + from. + extract_sensitivity_label: Select if you want to extract + Sensitivity label ( false, true). + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/me" + f"/messages" + f"/{quote(str(message_id), safe='')}" + f"/forward" + ) + query_params = [] + if mailbox_address is not None: + value = str(mailbox_address) + if isinstance(mailbox_address, bool): + value = value.lower() + query_params.append(f"mailboxAddress={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if fetch_sensitivity_label_metadata is not None: + value = str(fetch_sensitivity_label_metadata) + if isinstance(fetch_sensitivity_label_metadata, bool): + value = value.lower() + query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_attachment( + self, + message_id: str, + attachment_id: str, + *, + mailbox_address: Optional[str] = None, + extract_sensitivity_label: Optional[bool] = None, + fetch_sensitivity_label_metadata: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Attachment + + This operation gets an email attachment by id. + + Swagger operation ID: `GetAttachment_V2`. + + Args: + message_id: Id of the email. + attachment_id: Id of the attachment to download. + mailbox_address: Address of the shared mailbox to retrieve + attachment from. + extract_sensitivity_label: Select if you want to extract + Sensitivity label ( false, true). + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/me" + f"/messages" + f"/{quote(str(message_id), safe='')}" + f"/attachments" + f"/{quote(str(attachment_id), safe='')}" + ) + query_params = [] + if mailbox_address is not None: + value = str(mailbox_address) + if isinstance(mailbox_address, bool): + value = value.lower() + query_params.append(f"mailboxAddress={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if fetch_sensitivity_label_metadata is not None: + value = str(fetch_sensitivity_label_metadata) + if isinstance(fetch_sensitivity_label_metadata, bool): + value = value.lower() + query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_email( + self, + message_id: str, + *, + mailbox_address: Optional[str] = None, + include_attachments: Optional[bool] = None, + internet_message_id: Optional[str] = None, + extract_sensitivity_label: Optional[bool] = None, + fetch_sensitivity_label_metadata: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get email + + This operation gets an email by id. + + Swagger operation ID: `GetEmailV2`. + + Args: + message_id: Id of the email. + mailbox_address: Address of the shared mailbox to retrieve mail + from. + include_attachments: If set to true, attachments content will also + be retrieved along with the email. + internet_message_id: Internet Message Id. + extract_sensitivity_label: Select if you want to extract + Sensitivity label ( false, true). + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/Mail/{quote(str(message_id), safe='')}" + ) + query_params = [] + if mailbox_address is not None: + value = str(mailbox_address) + if isinstance(mailbox_address, bool): + value = value.lower() + query_params.append(f"mailboxAddress={quote(value, safe='')}") + if include_attachments is not None: + value = str(include_attachments) + if isinstance(include_attachments, bool): + value = value.lower() + query_params.append(f"includeAttachments={quote(value, safe='')}") + if internet_message_id is not None: + value = str(internet_message_id) + if isinstance(internet_message_id, bool): + value = value.lower() + query_params.append(f"internetMessageId={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if fetch_sensitivity_label_metadata is not None: + value = str(fetch_sensitivity_label_metadata) + if isinstance(fetch_sensitivity_label_metadata, bool): + value = value.lower() + query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_emails( + self, + *, + folder_path: Optional[str] = None, + to: Optional[str] = None, + cc: Optional[str] = None, + to_or_cc: Optional[str] = None, + from_: Optional[str] = None, + importance: Optional[str] = None, + fetch_only_with_attachment: Optional[bool] = None, + subject_filter: Optional[str] = None, + fetch_only_unread: Optional[bool] = None, + mailbox_address: Optional[str] = None, + include_attachments: Optional[bool] = None, + search_query: Optional[str] = None, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get emails + + This operation gets emails from a folder via graph apis. Please note + that filtering related to these fields: To, Cc, To Or Cc, From, + Importance, Fetch Only With Attachments, Subject Filter, is performed + using first 250 items in a given mail folder. To avoid that limitation + you can use 'Search Query' field. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetEmailsV3`. + + Args: + folder_path: Mail folder to retrieve emails from (default: + 'Inbox'). + to: Recipient email addresses separated by semicolons (If any + match, the trigger will run). + cc: CC recipient email addresses separated by semicolons (If any + match, the trigger will run). + to_or_cc: To or CC recipient email addresses separated by + semicolons (If any match, the trigger will run). + from_: Sender email addresses separated by semicolons (If any + match, the trigger will run). + importance: Importance of the email (Any, High, Normal, Low). + fetch_only_with_attachment: If set to true, only emails with an + attachment will be retrieved. Emails without any attachments + will be skipped. If set to false, all emails will be retrieved. + subject_filter: String to look for in the subject line. + fetch_only_unread: Retrieve only unread emails?. + mailbox_address: Address of the shared mailbox to retrieve mails + from. + include_attachments: If set to true, attachments content will also + be retrieved along with the email. + search_query: Search query to filter emails. How to use '$search' + parameter please refer to: + https://docs.microsoft.com/graph/query-parameters#search-parameter. + top: Number of emails to retrieve (default: 10, max: 1000). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v3/Mail" + query_params = [] + query_params.append("fetchOnlyFlagged=" + quote("false", safe='')) + if folder_path is not None: + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + if to is not None: + value = str(to) + if isinstance(to, bool): + value = value.lower() + query_params.append(f"to={quote(value, safe='')}") + if cc is not None: + value = str(cc) + if isinstance(cc, bool): + value = value.lower() + query_params.append(f"cc={quote(value, safe='')}") + if to_or_cc is not None: + value = str(to_or_cc) + if isinstance(to_or_cc, bool): + value = value.lower() + query_params.append(f"toOrCc={quote(value, safe='')}") + if from_ is not None: + value = str(from_) + if isinstance(from_, bool): + value = value.lower() + query_params.append(f"from={quote(value, safe='')}") + if importance is not None: + value = str(importance) + if isinstance(importance, bool): + value = value.lower() + query_params.append(f"importance={quote(value, safe='')}") + if fetch_only_with_attachment is not None: + value = str(fetch_only_with_attachment) + if isinstance(fetch_only_with_attachment, bool): + value = value.lower() + query_params.append(f"fetchOnlyWithAttachment={quote(value, safe='')}") + if subject_filter is not None: + value = str(subject_filter) + if isinstance(subject_filter, bool): + value = value.lower() + query_params.append(f"subjectFilter={quote(value, safe='')}") + if fetch_only_unread is not None: + value = str(fetch_only_unread) + if isinstance(fetch_only_unread, bool): + value = value.lower() + query_params.append(f"fetchOnlyUnread={quote(value, safe='')}") + if mailbox_address is not None: + value = str(mailbox_address) + if isinstance(mailbox_address, bool): + value = value.lower() + query_params.append(f"mailboxAddress={quote(value, safe='')}") + if include_attachments is not None: + value = str(include_attachments) + if isinstance(include_attachments, bool): + value = value.lower() + query_params.append(f"includeAttachments={quote(value, safe='')}") + if search_query is not None: + value = str(search_query) + if isinstance(search_query, bool): + value = value.lower() + query_params.append(f"searchQuery={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_events_calendar_view( + self, + calendar_id: str, + start_date_time_utc: str, + end_date_time_utc: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + search: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get calendar view of events + + This operation gets all events (including instances of recurrences) in + a calendar using Graph API. Recurrence property is null in this case. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetEventsCalendarViewV3`. + + Args: + calendar_id: Select a calendar. + start_date_time_utc: Start time in UTC (example: + '2017-01-01T08:00:00'). + end_date_time_utc: End time in UTC (example: + '2017-02-01T08:00:00'). + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + search: Search text for matching event body and subject. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/calendars/v3/tables/items/calendarview" + ) + query_params = [] + value = str(calendar_id) + if isinstance(calendar_id, bool): + value = value.lower() + query_params.append(f"calendarId={quote(value, safe='')}") + value = str(start_date_time_utc) + if isinstance(start_date_time_utc, bool): + value = value.lower() + query_params.append(f"startDateTimeUtc={quote(value, safe='')}") + value = str(end_date_time_utc) + if isinstance(end_date_time_utc, bool): + value = value.lower() + query_params.append(f"endDateTimeUtc={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if search is not None: + value = str(search) + if isinstance(search, bool): + value = value.lower() + query_params.append(f"search={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_mail_tips( + self, + input: GetMailTipsInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get mail tips for a mailbox + + Get mail tips for a mailbox such as automatic replies / OOF message or + if the mailbox is full. This is not available in GccHigh and Mooncake. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMailTips_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/codeless/v1.0/me/getMailTips" + ) + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_room_lists( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get room lists + + Get all the room lists defined in the user's tenant + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetRoomLists_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/codeless/beta/me/findRoomLists" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_rooms( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get rooms + + Get all the meeting rooms defined in the user's tenant + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetRooms_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/codeless/beta/me/findRooms" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_get_rooms_in_room( + self, + room_list: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get rooms in room list + + Get the meeting rooms in a specific room list + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetRoomsInRoomList_V2`. + + Args: + room_list: Room list to find rooms in. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/beta" + f"/me" + f"/findRooms(RoomList='{quote(str(room_list), safe='')}')" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def mark_as_read( + self, + input: MarkAsReadInput | Mapping[str, Any], + message_id: str, + *, + mailbox_address: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Mark as read or unread + + This operation marks an email as read/unread. + + Swagger operation ID: `MarkAsRead_V3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Id of the email to be marked. + mailbox_address: Address of the shared mailbox to update mail. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v3" + f"/v1.0" + f"/me" + f"/messages" + f"/{quote(str(message_id), safe='')}" + f"/markAsRead" + ) + query_params = [] + if mailbox_address is not None: + value = str(mailbox_address) + if isinstance(mailbox_address, bool): + value = value.lower() + query_params.append(f"mailboxAddress={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + async def move( + self, + message_id: str, + folder_path: str, + *, + mailbox_address: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Move email + + This operation moves an email to the specified folder within the same + mailbox. + + Swagger operation ID: `MoveV2`. + + Args: + message_id: Id of the email to be moved. + folder_path: Mail folder to move the email to. + mailbox_address: Address of the shared mailbox to move mail from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/Mail/Move/{quote(str(message_id), safe='')}" + ) + query_params = [] + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + if mailbox_address is not None: + value = str(mailbox_address) + if isinstance(mailbox_address, bool): + value = value.lower() + query_params.append(f"mailboxAddress={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def reply_to( + self, + input: ReplyEmailInput | Mapping[str, Any], + message_id: str, + *, + mailbox_address: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Reply to email + + This operation replies to an email. + + Swagger operation ID: `ReplyToV3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Id of the email to reply to. + mailbox_address: Address of the shared mailbox to reply from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v3/Mail/ReplyTo/{quote(str(message_id), safe='')}" + ) + query_params = [] + if mailbox_address is not None: + value = str(mailbox_address) + if isinstance(mailbox_address, bool): + value = value.lower() + query_params.append(f"mailboxAddress={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def respond_to_event( + self, + input: ResponseToEventInvite | Mapping[str, Any], + event_id: str, + response: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Respond to an event invite + + Respond to an event invite. + + Swagger operation ID: `RespondToEvent_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + event_id: Id of the event to respond to. + response: Response for the event invite. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/v1.0" + f"/me" + f"/events" + f"/{quote(str(event_id), safe='')}" + f"/{quote(str(response), safe='')}" + ) + + http_response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= http_response.status < 300): + raise ConnectorException( + "POST", + request_url, + http_response.status, + http_response.text, + response=http_response, + ) + + async def send_email( + self, + input: SendEmailInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Send an email + + This operation sends an email message. + + Swagger operation ID: `SendEmailV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/Mail" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def set_automatic_replies_setting( + self, + input: SetAutomaticRepliesSettingInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Set up automatic replies + + Set the automatic replies setting for your mailbox. + + Swagger operation ID: `SetAutomaticRepliesSetting_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/codeless/v1.0/me/mailboxSettings" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def shared_mailbox_send_email( + self, + input: SharedMailboxSendEmailInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Send an email from a shared mailbox + + This operation sends an email from a shared mailbox. Your account + should have permission to access the mailbox for this operation to + succeed. + + Swagger operation ID: `SharedMailboxSendEmailV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/SharedMailbox/Mail" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) diff --git a/src/azure/connectors/aio/office365groups.py b/src/azure/connectors/aio/office365groups.py new file mode 100644 index 0000000..45bfdb8 --- /dev/null +++ b/src/azure/connectors/aio/office365groups.py @@ -0,0 +1,1067 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# Office365groupsClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.office365groups import ( + CreateCalendarEventResponse, + ListGroupMembersResponse, + ListGroupsResponse, + ListOwnedGroupsResponse, + ObjectWithoutType, + OnGroupMemberAddedOrRemovedResponse, + OnNewEventResponse, + SensitivityLabelMetadata, + UpdateCalendarEventHTMLRequest, + UpdateCalendarEventRequest, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "Office365groupsClient", + "CreateCalendarEventResponse", + "ListGroupMembersResponse", + "ListGroupsResponse", + "ListOwnedGroupsResponse", + "ObjectWithoutType", + "OnGroupMemberAddedOrRemovedResponse", + "OnNewEventResponse", + "SensitivityLabelMetadata", + "UpdateCalendarEventHTMLRequest", + "UpdateCalendarEventRequest", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class Office365groupsClient(ConnectorClientBase): + """Typed client for office365groups connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a Office365groupsClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "office365groups" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_group_members( + self, + group_id: str, + *, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List group members + + This operation returns a list of all members in the given group and + their details such as name, title, email, etc. You can query up to 1000 + items using Top parameter. In case you need to retrieve more than 1000 + values please turn on Settings->Pagination feature and provide + Threshold limit. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListGroupMembers`. + + Args: + group_id: Pick a group from the drop down or enter group id. + top: Number of group members to retrieve (from 1 to 999, default is + 100). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/groups/{quote(str(group_id), safe='')}/members" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def add_member_to_group( + self, + group_id: str, + user_upn: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add member to group + + This operation is used to add a member to an O365 group, using a UPN. + + Swagger operation ID: `AddMemberToGroup`. + + Args: + group_id: Pick a group from the drop down or enter group id. + user_upn: The user principal name (UPN) of the user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/groups/{quote(str(group_id), safe='')}/members/$ref" + ) + query_params = [] + value = str(user_upn) + if isinstance(user_upn, bool): + value = value.lower() + query_params.append(f"userUpn={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_groups( + self, + *, + extract_sensitivity_label: Optional[bool] = None, + fetch_sensitivity_label_metadata: Optional[bool] = None, + filter: Optional[str] = None, + top: Optional[int] = None, + skiptoken: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List groups + + This operation returns a list of all groups in the organization. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListGroups`. + + Args: + extract_sensitivity_label: A boolean whether to extract sensitivity + label Id for associated artefact. + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + filter: Enter an OData style filter expression to limit which rows + are listed. + top: Sets the page size of results. + skiptoken: Token that references the next page of results and is + returned in the @odata.nextLink property in the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/groups" + query_params = [] + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if fetch_sensitivity_label_metadata is not None: + value = str(fetch_sensitivity_label_metadata) + if isinstance(fetch_sensitivity_label_metadata, bool): + value = value.lower() + query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skiptoken is not None: + value = str(skiptoken) + if isinstance(skiptoken, bool): + value = value.lower() + query_params.append(f"$skiptoken={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_calendar_event( + self, + input: UpdateCalendarEventHTMLRequest | Mapping[str, Any], + group_id: str, + event: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a group event + + This operation is used to update a new event in a group calendar. + + Swagger operation ID: `UpdateCalendarEvent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Pick a group from the drop down or enter group id. + event: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/groups" + f"/{quote(str(group_id), safe='')}" + f"/events" + f"/{quote(quote(str(event), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def remove_member_from_group( + self, + group_id: str, + user_upn: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Remove member from group + + This operation is used to remove a member from an O365 group, using a + UPN. + + Swagger operation ID: `RemoveMemberFromGroup`. + + Args: + group_id: Pick a group from the drop down or enter group id. + user_upn: The user principal name (UPN) of the user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/groups" + f"/{quote(str(group_id), safe='')}" + f"/members" + f"/memberId" + f"/$ref" + ) + query_params = [] + value = str(user_upn) + if isinstance(user_upn, bool): + value = value.lower() + query_params.append(f"userUpn={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_deleted_groups( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List deleted groups + + Lists deleted groups that can be restored. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListDeletedGroups`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/directory/deletedItems/microsoft.graph.group" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def restore_deleted_group( + self, + group_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Restore a deleted group + + Restore a recently deleted group + + Swagger operation ID: `RestoreDeletedGroup`. + + Args: + group_id: Pick a group from the drop down or enter group id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/directory" + f"/deletedItems" + f"/{quote(str(group_id), safe='')}" + f"/restore" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_deleted_groups_by_owner( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List deleted groups by owner + + List deleted groups that can be restored by owner + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListDeletedGroupsByOwner`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/directory/deletedItems/getUserOwnedObjects" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def calendar_delete_item( + self, + group_id: str, + event: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete event + + This operation deletes an event in a calendar. + + Swagger operation ID: `CalendarDeleteItem_V2`. + + Args: + group_id: Pick a group from the drop down or enter group id. + event: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/groups" + f"/{quote(str(group_id), safe='')}" + f"/events" + f"/{quote(quote(str(event), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def create_calendar_event( + self, + input: UpdateCalendarEventHTMLRequest | Mapping[str, Any], + group_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a group event + + This operation is used to create a new event in a group calendar. + + Swagger operation ID: `CreateCalendarEventV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Pick a group from the drop down or enter group id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/v1.0/groups/{quote(str(group_id), safe='')}/events" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def http_request( + self, + input: bytes, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send an HTTP request + + Construct a Microsoft Graph REST API request to invoke. There is one + segment that is supported: /groups. Learn more: + https://docs.microsoft.com/en-us/graph/use-the-api. + + Swagger operation ID: `HttpRequestV2`. + + Args: + input: The binary request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/httprequest" + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_owned_groups( + self, + *, + extract_sensitivity_label: Optional[bool] = None, + fetch_sensitivity_label_metadata: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List groups that I own and belong to + + This operation returns a list of all groups that you own and belong to. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListOwnedGroups_V3`. + + Args: + extract_sensitivity_label: A boolean whether to extract sensitivity + label Id for associated artefact. + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/v1.0/me/memberOf/$/microsoft.graph.group" + ) + query_params = [] + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if fetch_sensitivity_label_metadata is not None: + value = str(fetch_sensitivity_label_metadata) + if isinstance(fetch_sensitivity_label_metadata, bool): + value = value.lower() + query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/office365groupsmail.py b/src/azure/connectors/aio/office365groupsmail.py new file mode 100644 index 0000000..59fa7b4 --- /dev/null +++ b/src/azure/connectors/aio/office365groupsmail.py @@ -0,0 +1,1416 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# Office365groupsmailClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.office365groupsmail import ( + Attachment, + ClientSendAttachment, + Conversation, + ConversationThread, + ConversationThreadTriggerResponse, + ConversationTriggerResponse, + CreateConversationBody, + CreateConversationResponse, + EmailAddress, + ForwardPostBody, + GetAttachmentsResponse, + GetUsersGraphAction, + ItemBody, + ListConversationThreadsResponse, + ListConversationsResponse, + ListGroupThreadsResponse, + ListGroupsResponse, + ListThreadPostsResponse, + NewConversationThreadResponse, + NewPostBody, + ObjectWithoutType, + OnNewEmailInGroupResponse, + Post, + PostTriggerResponse, + ReplyConversationThreadBody, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "Office365groupsmailClient", + "Attachment", + "ClientSendAttachment", + "Conversation", + "ConversationThread", + "ConversationThreadTriggerResponse", + "ConversationTriggerResponse", + "CreateConversationBody", + "CreateConversationResponse", + "EmailAddress", + "ForwardPostBody", + "GetAttachmentsResponse", + "GetUsersGraphAction", + "ItemBody", + "ListConversationThreadsResponse", + "ListConversationsResponse", + "ListGroupThreadsResponse", + "ListGroupsResponse", + "ListThreadPostsResponse", + "NewConversationThreadResponse", + "NewPostBody", + "ObjectWithoutType", + "OnNewEmailInGroupResponse", + "Post", + "PostTriggerResponse", + "ReplyConversationThreadBody", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class Office365groupsmailClient(ConnectorClientBase): + """Typed client for office365groupsmail connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a Office365groupsmailClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "office365groupsmail" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_conversations( + self, + group_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List the conversations of a group + + Get all the conversations in this group. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListConversations`. + + Args: + group_id: Pick a group from the drop down or enter group id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/groups/{quote(str(group_id), safe='')}/conversations" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_conversation( + self, + input: CreateConversationBody | Mapping[str, Any], + group_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a new conversation in a group + + Create a new conversation in this group. + + Swagger operation ID: `CreateConversation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Pick a group from the drop down or enter group id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/groups/{quote(str(group_id), safe='')}/conversations" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_group_conversation( + self, + group_id: str, + conversation_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a group conversation + + Retrieves the properties of a particular conversation. + + Swagger operation ID: `GetGroupConversation`. + + Args: + group_id: Pick a group from the drop down or enter group id. + conversation_id: Enter the conversation ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/groups" + f"/{quote(str(group_id), safe='')}" + f"/conversations" + f"/{quote(str(conversation_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_conversation_threads( + self, + group_id: str, + conversation_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List the conversation threads of a conversation + + Get all the threads in a group conversation. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListConversationThreads`. + + Args: + group_id: Pick a group from the drop down or enter group id. + conversation_id: Enter the conversation ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/groups" + f"/{quote(str(group_id), safe='')}" + f"/conversations" + f"/{quote(str(conversation_id), safe='')}" + f"/threads" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_conversation_thread( + self, + input: CreateConversationBody | Mapping[str, Any], + group_id: str, + conversation_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a conversation thread + + Create a new thread in the specified conversation. + + Swagger operation ID: `CreateConversationThread`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Pick a group from the drop down or enter group id. + conversation_id: Enter the conversation ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/groups" + f"/{quote(str(group_id), safe='')}" + f"/conversations" + f"/{quote(str(conversation_id), safe='')}" + f"/threads" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_group_threads( + self, + group_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List the threads of a group + + Get all the threads of a group. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListGroupThreads`. + + Args: + group_id: Pick a group from the drop down or enter group id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/groups/{quote(str(group_id), safe='')}/threads" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_group_thread( + self, + input: CreateConversationBody | Mapping[str, Any], + group_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Start a new group conversation by creating a thread + + Start a new group conversation by first creating a thread. + + Swagger operation ID: `CreateGroupThread`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Pick a group from the drop down or enter group id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/groups/{quote(str(group_id), safe='')}/threads" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_conversation_thread( + self, + group_id: str, + thread_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a conversation thread + + Get a specific thread that belongs to a group. + + Swagger operation ID: `GetConversationThread`. + + Args: + group_id: Pick a group from the drop down or enter group id. + thread_id: Enter the conversation thread ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/groups" + f"/{quote(str(group_id), safe='')}" + f"/threads" + f"/{quote(str(thread_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_conversation_thread( + self, + group_id: str, + thread_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a conversation thread + + Deletes the specified conversation thread. + + Swagger operation ID: `DeleteConversationThread`. + + Args: + group_id: Pick a group from the drop down or enter group id. + thread_id: Enter the conversation thread ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/groups" + f"/{quote(str(group_id), safe='')}" + f"/threads" + f"/{quote(str(thread_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_thread_posts( + self, + group_id: str, + thread_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List the posts of a conversation thread + + Get all the posts of the specified conversation thread. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListThreadPosts`. + + Args: + group_id: Pick a group from the drop down or enter group id. + thread_id: Enter the conversation thread ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/groups" + f"/{quote(str(group_id), safe='')}" + f"/threads" + f"/{quote(str(thread_id), safe='')}" + f"/posts" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_thread( + self, + group_id: str, + thread_id: str, + post_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a thread post + + Retrieves a post in a specified thread. + + Swagger operation ID: `GetThreadPost`. + + Args: + group_id: Pick a group from the drop down or enter group id. + thread_id: Enter the conversation thread ID. + post_id: Enter the post ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/groups" + f"/{quote(str(group_id), safe='')}" + f"/threads" + f"/{quote(str(thread_id), safe='')}" + f"/posts" + f"/{quote(str(post_id), safe='')}" + ) + query_params = [] + query_params.append("$expand=" + quote("attachments", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_attachments( + self, + group_id: str, + thread_id: str, + post_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List the attachments of a post + + Retrieve a list of attachments that belong to a post. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAttachments`. + + Args: + group_id: Pick a group from the drop down or enter group id. + thread_id: Enter the conversation thread ID. + post_id: Enter the post ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/groups" + f"/{quote(str(group_id), safe='')}" + f"/threads" + f"/{quote(str(thread_id), safe='')}" + f"/posts" + f"/{quote(str(post_id), safe='')}" + f"/attachments" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def reply_to_a_thread( + self, + input: ReplyConversationThreadBody | Mapping[str, Any], + group_id: str, + thread_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Reply to a conversation thread + + Reply to a thread in a group conversation and add a new post to it. + + Swagger operation ID: `ReplyToAThread`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Pick a group from the drop down or enter group id. + thread_id: Enter the conversation thread ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/groups" + f"/{quote(str(group_id), safe='')}" + f"/threads" + f"/{quote(str(thread_id), safe='')}" + f"/reply" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def reply( + self, + input: ReplyConversationThreadBody | Mapping[str, Any], + group_id: str, + thread_id: str, + post_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Reply to a post + + Reply to a post and add a new post to the specified thread in a group + conversation. + + Swagger operation ID: `ReplyPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Pick a group from the drop down or enter group id. + thread_id: Enter the conversation thread ID. + post_id: Enter the post ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/groups" + f"/{quote(str(group_id), safe='')}" + f"/threads" + f"/{quote(str(thread_id), safe='')}" + f"/posts" + f"/{quote(str(post_id), safe='')}" + f"/reply" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def http_request( + self, + input: bytes, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send an HTTP request + + Construct a Microsoft Graph REST API request to invoke. Learn more: + https://docs.microsoft.com/en-us/graph/use-the-api + + Swagger operation ID: `HttpRequest`. + + Args: + input: The binary request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/httprequest" + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def forward( + self, + input: ForwardPostBody | Mapping[str, Any], + group_mail: str, + conversation_id: str, + thread_id: str, + post_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Forward a post + + Forward a post to a recipient. + + Swagger operation ID: `ForwardPost_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_mail: Pick a group from the drop down or enter the group mail + address. + conversation_id: Enter the conversation ID. + thread_id: Enter the conversation thread ID. + post_id: Enter the post ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/beta" + f"/groups" + f"/{quote(str(group_mail), safe='')}" + f"/conversations" + f"/{quote(str(conversation_id), safe='')}" + f"/threads" + f"/{quote(str(thread_id), safe='')}" + f"/posts" + f"/{quote(str(post_id), safe='')}" + f"/forward" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_groups( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List user groups + + Retrieves all Office 365 Groups the user is part of. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListGroups`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/me/memberOf/$/microsoft.graph.group" + ) + query_params = [] + query_params.append("$filter=" + quote("groupTypes/any(c:c eq 'Unified')", safe='')) + query_params.append("$select=" + quote("id,displayName", safe='')) + query_params.append("$top=" + quote("999", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/office365users.py b/src/azure/connectors/aio/office365users.py new file mode 100644 index 0000000..9d5a444 --- /dev/null +++ b/src/azure/connectors/aio/office365users.py @@ -0,0 +1,1152 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# Office365usersClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.office365users import ( + ClientPhotoMetadata, + DirectReportsResponse, + EntityListResponseIReadOnlyListUser, + GraphTrending, + GraphUser, + GraphUserUpdateable, + LinklessEntityListResponseListPerson, + MyTrendingDocumentsResponse, + ObjectEntity, + ObjectWithoutType, + Person, + Phone, + ResourceVisualization, + ScoredEmailAddress, + SensitivityLabelMetadata, + TrendingDocumentsResponse, + User, +) + +__all__ = [ + "Office365usersClient", + "ClientPhotoMetadata", + "DirectReportsResponse", + "EntityListResponseIReadOnlyListUser", + "GraphTrending", + "GraphUser", + "GraphUserUpdateable", + "LinklessEntityListResponseListPerson", + "MyTrendingDocumentsResponse", + "ObjectEntity", + "ObjectWithoutType", + "Person", + "Phone", + "ResourceVisualization", + "ScoredEmailAddress", + "SensitivityLabelMetadata", + "TrendingDocumentsResponse", + "User", +] + + +# Type Definitions + +# Client Class + +class Office365usersClient(ConnectorClientBase): + """Typed client for office365users connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a Office365usersClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "office365users" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def update_my_profile( + self, + input: GraphUserUpdateable | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update my profile + + Updates the profile of the current user + + Swagger operation ID: `UpdateMyProfile`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/codeless/v1.0/me" + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + async def update_my_photo( + self, + input: bytes, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update my profile photo + + Updates the profile photo of the current user. The size of the photo + must be less than 4 MB. + + Swagger operation ID: `UpdateMyPhoto`. + + Args: + input: The binary request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/codeless/v1.0/me/photo/$value" + ) + + response = await self.http_client.send( + "PUT", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + def list_my_trending_documents( + self, + *, + filter: Optional[str] = None, + extract_sensitivity_label: Optional[bool] = None, + fetch_sensitivity_label_metadata: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get my trending documents + + Retrieves the trending documents for the signed in user + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `MyTrendingDocuments`. + + Args: + filter: An OData filter to filter the resources selected. Filter + selected resources on ResourceVisualization/Type or + ResourceVisualization/containerType. + extract_sensitivity_label: Select if you want to extract + Sensitivity label ( false, true). + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless/beta/me/insights/trending" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if fetch_sensitivity_label_metadata is not None: + value = str(fetch_sensitivity_label_metadata) + if isinstance(fetch_sensitivity_label_metadata, bool): + value = value.lower() + query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_relevant_people( + self, + user_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get relevant people + + Get relevant people. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `RelevantPeople`. + + Args: + user_id: User principal name or id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/users/{quote(str(user_id), safe='')}/relevantpeople" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def user_photo_metadata( + self, + user_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get user photo metadata + + Get user photo metadata. + + Swagger operation ID: `UserPhotoMetadata`. + + Args: + user_id: User principal name or id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/users/photo" + query_params = [] + value = str(user_id) + if isinstance(user_id, bool): + value = value.lower() + query_params.append(f"userId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_trending_documents( + self, + id: str, + *, + filter: Optional[str] = None, + extract_sensitivity_label: Optional[bool] = None, + fetch_sensitivity_label_metadata: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get trending documents + + Retrieves the trending documents for a user + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `TrendingDocuments`. + + Args: + id: User principal name or id. + filter: An OData filter to filter the resources selected. Filter + selected resources on ResourceVisualization/Type or + ResourceVisualization/containerType. + extract_sensitivity_label: Select if you want to extract + Sensitivity label ( false, true). + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless/beta/users/{quote(str(id), safe='')}/insights/trending" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if fetch_sensitivity_label_metadata is not None: + value = str(fetch_sensitivity_label_metadata) + if isinstance(fetch_sensitivity_label_metadata, bool): + value = value.lower() + query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def http_request( + self, + input: bytes, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send an HTTP request + + Construct a Microsoft Graph REST API request to invoke. These segments + are supported: 1st segement: /me, /users/ 2nd segment: + messages, mailFolders, events, calendar, calendars, outlook, + inferenceClassification. Learn more: + https://docs.microsoft.com/en-us/graph/use-the-api. + + Swagger operation ID: `HttpRequest`. + + Args: + input: The binary request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/codeless/httprequest" + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_direct_reports( + self, + id: str, + *, + select: Optional[str] = None, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get direct reports + + Retrieves the user profiles of the specified user's direct reports. + Learn more about available fields to select: + https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/user#properties + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `DirectReports_V2`. + + Args: + id: User principal name or id. + select: Comma separated list of fields to select. Example: surname, + department, jobTitle. + top: Limit on the number of results to return. By default returns + all entries. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless/v1.0/users/{quote(str(id), safe='')}/directReports" + ) + query_params = [] + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def manager( + self, + id: str, + *, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get manager + + Retrieves the profile of the specified user's manager. Learn more about + available fields to select: + https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/user#properties + + Swagger operation ID: `Manager_V2`. + + Args: + id: User principal name or id. + select: Comma separated list of fields to select. Example: surname, + department, jobTitle. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless/v1.0/users/{quote(str(id), safe='')}/manager" + ) + query_params = [] + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def my_profile( + self, + *, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get my profile + + Retrieves the profile of the current user. Learn more about available + fields to select: + https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/user#properties + + Swagger operation ID: `MyProfile_V2`. + + Args: + select: Comma separated list of fields to select. Example: surname, + department, jobTitle. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/codeless/v1.0/me" + query_params = [] + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_search_user( + self, + *, + search_term: Optional[str] = None, + top: Optional[int] = None, + is_search_term_required: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Search for users + + Retrieves the user profiles that match the search term. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SearchUserV2`. + + Args: + search_term: Search string (applies to: display name, given name, + surname, mail, mail nickname and user principal name). + top: Limit on the number of results to return. Minimum value is 1. + Default value is 1000. + is_search_term_required: If set to 'Yes' then no user profiles will + be returned when the search term is empty. If set to 'No' then + no filtering will be applied when the search term is empty. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/users" + query_params = [] + if search_term is not None: + value = str(search_term) + if isinstance(search_term, bool): + value = value.lower() + query_params.append(f"searchTerm={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"top={quote(value, safe='')}") + if is_search_term_required is not None: + value = str(is_search_term_required) + if isinstance(is_search_term_required, bool): + value = value.lower() + query_params.append(f"isSearchTermRequired={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def user_photo( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get user photo + + Retrieves the photo of the specified user if they have one + + Swagger operation ID: `UserPhoto_V2`. + + Args: + id: User principal name or id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless/v1.0/users/{quote(str(id), safe='')}/photo/$value" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def user_profile( + self, + id: str, + *, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get user profile + + Retrieves the profile of a specific user. Learn more about available + fields to select: + https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/user#properties + + Swagger operation ID: `UserProfile_V2`. + + Args: + id: User principal name or id. + select: Comma separated list of fields to select. Example: surname, + department, jobTitle. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless/v1.0/users/{quote(str(id), safe='')}" + ) + query_params = [] + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/onedrive.py b/src/azure/connectors/aio/onedrive.py new file mode 100644 index 0000000..fa1535a --- /dev/null +++ b/src/azure/connectors/aio/onedrive.py @@ -0,0 +1,2009 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# OnedriveClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.onedrive import ( + BlobDataSetsMetadata, + BlobMetadata, + BlobMetadataPage, + DataSetsMetadata, + SharingLink, + TabularDataSetsMetadata, + Tags, + Thumbnail, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "OnedriveClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "BlobMetadataPage", + "DataSetsMetadata", + "SharingLink", + "TabularDataSetsMetadata", + "Tags", + "Thumbnail", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class OnedriveClient(ConnectorClientBase): + """Typed client for onedrive connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a OnedriveClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "onedrive" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def get_file_metadata( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file metadata + + This operation gets the metadata for a file. + + Swagger operation ID: `GetFileMetadata`. + + Args: + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_file( + self, + input: bytes, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update file + + This operation updates a file. + + Swagger operation ID: `UpdateFile`. + + Args: + input: The binary request body. + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PUT", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_file( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete file + + This operation deletes a file. + + Swagger operation ID: `DeleteFile`. + + Args: + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_file_metadata_by_path( + self, + path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file metadata using path + + This operation gets the metadata of a file using the path. + + Swagger operation ID: `GetFileMetadataByPath`. + + Args: + path: The unique path of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/GetFileByPath" + ) + query_params = [] + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_file_content_by_path( + self, + path: str, + *, + infer_content_type: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file content using path + + This operation gets the content of a file using the path. + + Swagger operation ID: `GetFileContentByPath`. + + Args: + path: The unique path of the file. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/GetFileContentByPath" + ) + query_params = [] + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def get_file_content( + self, + id: str, + *, + infer_content_type: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file content + + This operation gets the content of a file. + + Swagger operation ID: `GetFileContent`. + + Args: + id: The unique identifier of the file. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/content" + ) + query_params = [] + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def create_file( + self, + input: bytes, + folder_path: str, + name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create file + + This operation creates a file. + + Swagger operation ID: `CreateFile`. + + Args: + input: The binary request body. + folder_path: The unique path of the folder. + name: The name of the file. Certain characters are disallowed by + OneDrive and will be replaced by underscores. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/datasets/default/files" + query_params = [] + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def copy_file( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Upload file from URL + + This operation uploads a file from a URL to OneDrive. + + Swagger operation ID: `CopyFile`. + + Args: + source: The url to the source file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/copyFile" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def copy_drive_file( + self, + id: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Copy file + + This operation copies a file within OneDrive. + + Swagger operation ID: `CopyDriveFile`. + + Args: + id: The unique identifier of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/copy" + ) + query_params = [] + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def copy_drive_file_by_path( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Copy file using path + + This operation copies a file within OneDrive by path. + + Swagger operation ID: `CopyDriveFileByPath`. + + Args: + source: The unique path of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/CopyFileByPath" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def move_file( + self, + id: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Move or rename a file + + This operation moves or renames a file. + + Swagger operation ID: `MoveFile`. + + Args: + id: The unique identifier of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/move" + ) + query_params = [] + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def move_file_by_path( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Move or rename a file using path + + This operation moves or renames a file using the path. + + Swagger operation ID: `MoveFileByPath`. + + Args: + source: The unique path of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/MoveFileByPath" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def convert_file( + self, + id: str, + *, + type_: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Convert file + + This operation converts a file to another format. The list of supported + conversions can be found at https://aka.ms/onedriveconversions + + Swagger operation ID: `ConvertFile`. + + Args: + id: The unique identifier of the file. + type_: The target file type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/convert" + ) + query_params = [] + if type_ is not None: + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def convert_file_by_path( + self, + path: str, + *, + type_: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Convert file using path + + This operation converts a file to another format using the path. The + list of supported conversions can be found at + https://aka.ms/onedriveconversions + + Swagger operation ID: `ConvertFileByPath`. + + Args: + path: The unique path of the file. + type_: The target file type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/ConvertFileByPath" + ) + query_params = [] + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if type_ is not None: + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + def list_file_tags( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[str]: + """ + Get file tags + + This operation gets the tags of a file. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetFileTags`. + + Args: + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[str]: An Azure Core pager over connector results. + Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/tags" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[str]: + for item in page.get("Tags", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def add_file_tag( + self, + id: str, + tag: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add file tag + + This operation adds a tag to a file. + + Swagger operation ID: `AddFileTag`. + + Args: + id: The unique identifier of the file. + tag: The name of the tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/tags" + ) + query_params = [] + value = str(tag) + if isinstance(tag, bool): + value = value.lower() + query_params.append(f"tag={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def remove_file_tag( + self, + id: str, + tag: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Remove file tag + + This operation removes a tag from a file. + + Swagger operation ID: `RemoveFileTag`. + + Args: + id: The unique identifier of the file. + tag: The name of the tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/tags" + ) + query_params = [] + value = str(tag) + if isinstance(tag, bool): + value = value.lower() + query_params.append(f"tag={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_file_thumbnail( + self, + id: str, + size: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file thumbnail + + This operation gets the thumbnail of a file. The thumbnail will only be + valid for 6 hours. + + Swagger operation ID: `GetFileThumbnail`. + + Args: + id: The unique identifier of the file. + size: The size of the thumbnail to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/thumbnail" + ) + query_params = [] + value = str(size) + if isinstance(size, bool): + value = value.lower() + query_params.append(f"size={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_root_folder( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List files in root folder + + This operation gets the list of files and subfolders in the root + folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListRootFolder`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/folders" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_find_files( + self, + id: str, + query: str, + find_mode: str, + *, + max_file_count: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Find files in folder + + This operation finds files within a folder using search or name pattern + match. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `FindFiles`. + + Args: + id: The unique identifier of the folder. + query: The search query to use. + find_mode: The search method to use. \"Search\" mode searches your + OneDrive using the search query (similar a normal search + engine). When \"Regular Expression Pattern Match\" mode is + selected, the search query will be treated as a regex pattern, + and it will return files with names that match the query. + max_file_count: Maximum number of files to return (1-100). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/folders" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/search" + ) + query_params = [] + value = str(query) + if isinstance(query, bool): + value = value.lower() + query_params.append(f"query={quote(value, safe='')}") + value = str(find_mode) + if isinstance(find_mode, bool): + value = value.lower() + query_params.append(f"findMode={quote(value, safe='')}") + if max_file_count is not None: + value = str(max_file_count) + if isinstance(max_file_count, bool): + value = value.lower() + query_params.append(f"maxFileCount={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_find_files_by_path( + self, + query: str, + path: str, + find_mode: str, + *, + max_file_count: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Find files in folder by path + + This operation finds files within a folder by path using search or name + pattern match. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `FindFilesByPath`. + + Args: + query: The search query to use. + path: The unique path of the folder. + find_mode: The search method to use. \"Search\" mode searches your + OneDrive using the search query (similar a normal search + engine). When \"Regular Expression Pattern Match\" mode is + selected, the search query will be treated as a regex pattern, + and it will return files with names that match the query. + max_file_count: Maximum number of files to return (1-100). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/findFile" + ) + query_params = [] + value = str(query) + if isinstance(query, bool): + value = value.lower() + query_params.append(f"query={quote(value, safe='')}") + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + value = str(find_mode) + if isinstance(find_mode, bool): + value = value.lower() + query_params.append(f"findMode={quote(value, safe='')}") + if max_file_count is not None: + value = str(max_file_count) + if isinstance(max_file_count, bool): + value = value.lower() + query_params.append(f"maxFileCount={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_share_link( + self, + id: str, + type_: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create share link + + This operation creates a share link for a file. + + Swagger operation ID: `CreateShareLinkV2`. + + Args: + id: The unique identifier of the file. + type_: The type of link. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/shareV2" + ) + query_params = [] + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_share_link_by_path( + self, + path: str, + type_: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create share link by path + + This operation creates a share link for a file using the path. + + Swagger operation ID: `CreateShareLinkByPathV2`. + + Args: + path: The unique path of the file. + type_: The type of link. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/CreateShareLinkByPathV2" + ) + query_params = [] + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def extract_folder( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Extract archive to folder + + This operation extracts an archive file into a folder (example: .zip). + Maximum archive size is 50 MB and 100 files inside. + + Swagger operation ID: `ExtractFolderV2`. + + Args: + source: The path to the archive file. + destination: The path to extract the archive contents. + overwrite: Overwrites the destination files if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/extractFolderV2" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_folder( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List files in folder + + This operation gets the list of files and subfolders in a folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListFolderV2`. + + Args: + id: The unique identifier of the folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/foldersV2" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + query_params = [] + query_params.append("skipToken=" + quote("", safe='')) + query_params.append("top=" + quote("20", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/onedriveforbusiness.py b/src/azure/connectors/aio/onedriveforbusiness.py new file mode 100644 index 0000000..64081ea --- /dev/null +++ b/src/azure/connectors/aio/onedriveforbusiness.py @@ -0,0 +1,1808 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# OnedriveforbusinessClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.onedriveforbusiness import ( + BlobDataSetsMetadata, + BlobMetadata, + BlobMetadataPage, + DataSetsMetadata, + ForASelectedFileResponse, + SharingLink, + TabularDataSetsMetadata, + Tags, + Thumbnail, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "OnedriveforbusinessClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "BlobMetadataPage", + "DataSetsMetadata", + "ForASelectedFileResponse", + "SharingLink", + "TabularDataSetsMetadata", + "Tags", + "Thumbnail", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class OnedriveforbusinessClient(ConnectorClientBase): + """Typed client for onedriveforbusiness connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a OnedriveforbusinessClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "onedriveforbusiness" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def get_file_metadata( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file metadata + + This operation gets the metadata for a file. + + Swagger operation ID: `GetFileMetadata`. + + Args: + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_file( + self, + input: bytes, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update file + + This operation updates a file. + + Swagger operation ID: `UpdateFile`. + + Args: + input: The binary request body. + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PUT", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_file( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete file + + This operation deletes a file. + + Swagger operation ID: `DeleteFile`. + + Args: + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_file_metadata_by_path( + self, + path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file metadata using path + + This operation gets the metadata of a file using the path. + + Swagger operation ID: `GetFileMetadataByPath`. + + Args: + path: The unique path of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/GetFileByPath" + ) + query_params = [] + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_file_content_by_path( + self, + path: str, + *, + infer_content_type: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file content using path + + This operation gets the content of a file using the path. + + Swagger operation ID: `GetFileContentByPath`. + + Args: + path: The unique path of the file. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/GetFileContentByPath" + ) + query_params = [] + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def get_file_content( + self, + id: str, + *, + infer_content_type: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file content + + This operation gets the content of a file. + + Swagger operation ID: `GetFileContent`. + + Args: + id: The unique identifier of the file. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/content" + ) + query_params = [] + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def create_file( + self, + input: bytes, + folder_path: str, + name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create file + + This operation creates a file. + + Swagger operation ID: `CreateFile`. + + Args: + input: The binary request body. + folder_path: The unique path of the folder. + name: The name of the file. Certain characters are disallowed by + OneDrive and will be replaced by underscores. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/datasets/default/files" + query_params = [] + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def copy_file( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Upload file from URL + + This operation uploads a file from a URL to OneDrive. + + Swagger operation ID: `CopyFile`. + + Args: + source: The url to the source file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/copyFile" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def copy_drive_file( + self, + id: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Copy file + + This operation copies a file within OneDrive. + + Swagger operation ID: `CopyDriveFile`. + + Args: + id: The unique identifier of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/copy" + ) + query_params = [] + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def copy_drive_file_by_path( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Copy file using path + + This operation copies a file within OneDrive by path. + + Swagger operation ID: `CopyDriveFileByPath`. + + Args: + source: The unique path of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/CopyFileByPath" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def move_file( + self, + id: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Move or rename a file + + This operation moves or renames a file. + + Swagger operation ID: `MoveFile`. + + Args: + id: The unique identifier of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/move" + ) + query_params = [] + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def move_file_by_path( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Move or rename a file using path + + This operation moves or renames a file using the path. + + Swagger operation ID: `MoveFileByPath`. + + Args: + source: The unique path of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/MoveFileByPath" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def convert_file( + self, + id: str, + *, + type_: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Convert file + + This operation converts a file to another format. The list of supported + conversions can be found at https://aka.ms/onedriveconversions + + Swagger operation ID: `ConvertFile`. + + Args: + id: The unique identifier of the file. + type_: The target file type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/convert" + ) + query_params = [] + if type_ is not None: + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def convert_file_by_path( + self, + path: str, + *, + type_: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Convert file using path + + This operation converts a file to another format using the path. The + list of supported conversions can be found at + https://aka.ms/onedriveconversions + + Swagger operation ID: `ConvertFileByPath`. + + Args: + path: The unique path of the file. + type_: The target file type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/ConvertFileByPath" + ) + query_params = [] + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if type_ is not None: + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def get_file_thumbnail( + self, + id: str, + size: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file thumbnail + + This operation gets the thumbnail of a file. The thumbnail will only be + valid for 6 hours. + + Swagger operation ID: `GetFileThumbnail`. + + Args: + id: The unique identifier of the file. + size: The size of the thumbnail to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/thumbnail" + ) + query_params = [] + value = str(size) + if isinstance(size, bool): + value = value.lower() + query_params.append(f"size={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_root_folder( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List files in root folder + + This operation gets the list of files and subfolders in the root + folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListRootFolder`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/folders" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_find_files( + self, + id: str, + query: str, + find_mode: str, + *, + max_file_count: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Find files in folder + + This operation finds files within a folder using search or name pattern + match. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `FindFiles`. + + Args: + id: The unique identifier of the folder. + query: The search query to use. + find_mode: The search method to use. \"Search\" mode searches your + OneDrive using the search query (similar a normal search + engine). When \"Regular Expression Pattern Match\" mode is + selected, the search query will be treated as a regex pattern, + and it will return files with names that match the query. + max_file_count: Maximum number of files to return (1-100). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/folders" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/search" + ) + query_params = [] + value = str(query) + if isinstance(query, bool): + value = value.lower() + query_params.append(f"query={quote(value, safe='')}") + value = str(find_mode) + if isinstance(find_mode, bool): + value = value.lower() + query_params.append(f"findMode={quote(value, safe='')}") + if max_file_count is not None: + value = str(max_file_count) + if isinstance(max_file_count, bool): + value = value.lower() + query_params.append(f"maxFileCount={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_find_files_by_path( + self, + query: str, + path: str, + find_mode: str, + *, + max_file_count: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Find files in folder by path + + This operation finds files within a folder by path using search or name + pattern match. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `FindFilesByPath`. + + Args: + query: The search query to use. + path: The unique path of the folder. + find_mode: The search method to use. \"Search\" mode searches your + OneDrive using the search query (similar a normal search + engine). When \"Regular Expression Pattern Match\" mode is + selected, the search query will be treated as a regex pattern, + and it will return files with names that match the query. + max_file_count: Maximum number of files to return (1-100). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/findFile" + ) + query_params = [] + value = str(query) + if isinstance(query, bool): + value = value.lower() + query_params.append(f"query={quote(value, safe='')}") + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + value = str(find_mode) + if isinstance(find_mode, bool): + value = value.lower() + query_params.append(f"findMode={quote(value, safe='')}") + if max_file_count is not None: + value = str(max_file_count) + if isinstance(max_file_count, bool): + value = value.lower() + query_params.append(f"maxFileCount={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_share_link( + self, + id: str, + type_: str, + *, + scope: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create share link + + This operation creates a share link for a file. + + Swagger operation ID: `CreateShareLinkV2`. + + Args: + id: The unique identifier of the file. + type_: The type of link. + scope: The scope of the link. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/shareV2" + ) + query_params = [] + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if scope is not None: + value = str(scope) + if isinstance(scope, bool): + value = value.lower() + query_params.append(f"scope={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_share_link_by_path( + self, + path: str, + type_: str, + *, + scope: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create share link by path + + This operation creates a share link for a file using the path. + + Swagger operation ID: `CreateShareLinkByPathV2`. + + Args: + path: The unique path of the file. + type_: The type of link. + scope: The scope of the link. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/CreateShareLinkByPathV2" + ) + query_params = [] + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if scope is not None: + value = str(scope) + if isinstance(scope, bool): + value = value.lower() + query_params.append(f"scope={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def extract_folder( + self, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Extract archive to folder + + This operation extracts an archive file into a folder (example: .zip). + Maximum archive size is 50 MB and 100 files inside. + + Swagger operation ID: `ExtractFolderV2`. + + Args: + source: The path to the archive file. + destination: The path to extract the archive contents. + overwrite: Overwrites the destination files if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/extractFolderV2" + ) + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_folder( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List files in folder + + This operation gets the list of files and subfolders in a folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListFolderV2`. + + Args: + id: The unique identifier of the folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/foldersV2" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + query_params = [] + query_params.append("skipToken=" + quote("", safe='')) + query_params.append("top=" + quote("20", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/onenote.py b/src/azure/connectors/aio/onenote.py new file mode 100644 index 0000000..146ecff --- /dev/null +++ b/src/azure/connectors/aio/onenote.py @@ -0,0 +1,842 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# OnenoteClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.onenote import ( + CreatePageInQuickNotesInput, + CreatePageInSectionInput, + CreateSectionInNotebookResponse, + CreateSectionRequest, + GetPageResponse, + GetPagesInSectionResponse, + GetSectionsInNotebookResponse, + Link, + NewPageResponse, + NewSectionGroupResponse, + NewSectionResponse, + Notebook, + OneNoteClientUrl, + OneNoteWebUrl, + Page, + ParentNotebook, + SectionGroupResponse, + SectionListItem, + SectionResponse, + UpdatePageContentRequest, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "OnenoteClient", + "CreatePageInQuickNotesInput", + "CreatePageInSectionInput", + "CreateSectionInNotebookResponse", + "CreateSectionRequest", + "GetPageResponse", + "GetPagesInSectionResponse", + "GetSectionsInNotebookResponse", + "Link", + "NewPageResponse", + "NewSectionGroupResponse", + "NewSectionResponse", + "Notebook", + "OneNoteClientUrl", + "OneNoteWebUrl", + "Page", + "ParentNotebook", + "SectionGroupResponse", + "SectionListItem", + "SectionResponse", + "UpdatePageContentRequest", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class OnenoteClient(ConnectorClientBase): + """Typed client for onenote connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a OnenoteClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "onenote" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_section_in_notebook( + self, + input: CreateSectionRequest | Mapping[str, Any], + notebook_key: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create section in a notebook + + Create section in a notebook. + + Swagger operation ID: `CreateSectionInNotebook`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + notebook_key: A key identifying the notebook. Note this is specific + to the API and cannot be hand-typed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/notebooks/Dynamic/sections" + ) + query_params = [] + value = str(notebook_key) + if isinstance(notebook_key, bool): + value = value.lower() + query_params.append(f"notebookKey={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_page_in_section( + self, + input: CreatePageInSectionInput, + notebook_key: str, + section_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create page in a section + + Create new page in a specified section. + + Swagger operation ID: `CreatePageInSection`. + + Args: + input: The request body. + notebook_key: A key identifying the notebook. Note this is specific + to the API and cannot be hand-typed. + section_id: API URL of the section pages. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/sections/Dynamic/pages" + query_params = [] + value = str(notebook_key) + if isinstance(notebook_key, bool): + value = value.lower() + query_params.append(f"notebookKey={quote(value, safe='')}") + value = str(section_id) + if isinstance(section_id, bool): + value = value.lower() + query_params.append(f"sectionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_pages_in_section( + self, + notebook_key: str, + section_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get pages for a specific section + + Get pages for a specific section. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetPagesInSection`. + + Args: + notebook_key: A key identifying the notebook. Note this is specific + to the API and cannot be hand-typed. + section_id: API URL of the section pages. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/sections/Dynamic/pages" + query_params = [] + value = str(notebook_key) + if isinstance(notebook_key, bool): + value = value.lower() + query_params.append(f"notebookKey={quote(value, safe='')}") + value = str(section_id) + if isinstance(section_id, bool): + value = value.lower() + query_params.append(f"sectionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_page_in_quick_notes( + self, + input: CreatePageInQuickNotesInput, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a page in Quick Notes + + Create a new page in the Quick Notes section. + + Swagger operation ID: `CreatePageInQuickNotes`. + + Args: + input: The request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/pages" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_page( + self, + notebook_key: str, + section_id: str, + page_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a page + + Delete a page. + + Swagger operation ID: `DeletePage`. + + Args: + notebook_key: A key identifying the notebook. Note this is specific + to the API and cannot be hand-typed. + section_id: API URL of the section pages. + page_id: Unique id of the page. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/pages" + query_params = [] + value = str(notebook_key) + if isinstance(notebook_key, bool): + value = value.lower() + query_params.append(f"notebookKey={quote(value, safe='')}") + value = str(section_id) + if isinstance(section_id, bool): + value = value.lower() + query_params.append(f"sectionId={quote(value, safe='')}") + value = str(page_id) + if isinstance(page_id, bool): + value = value.lower() + query_params.append(f"pageId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_page_content( + self, + notebook_key: str, + section_id: str, + page_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get page content + + Get HTML page content. + + Swagger operation ID: `GetPageContent`. + + Args: + notebook_key: A key identifying the notebook. Note this is specific + to the API and cannot be hand-typed. + section_id: API URL of the section pages. + page_id: Unique id of the page. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/pages/Dynamic/content" + query_params = [] + query_params.append("preAuthenticated=" + quote("true", safe='')) + value = str(notebook_key) + if isinstance(notebook_key, bool): + value = value.lower() + query_params.append(f"notebookKey={quote(value, safe='')}") + value = str(section_id) + if isinstance(section_id, bool): + value = value.lower() + query_params.append(f"sectionId={quote(value, safe='')}") + value = str(page_id) + if isinstance(page_id, bool): + value = value.lower() + query_params.append(f"pageId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_page_content( + self, + input: UpdatePageContentRequest, + notebook_key: str, + section_id: str, + page_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update page content + + Update HTML page content. + + Swagger operation ID: `UpdatePageContent`. + + Args: + input: The request body. + notebook_key: A key identifying the notebook. Note this is specific + to the API and cannot be hand-typed. + section_id: API URL of the section pages. + page_id: Unique id of the page. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/pages/Dynamic/content" + query_params = [] + value = str(notebook_key) + if isinstance(notebook_key, bool): + value = value.lower() + query_params.append(f"notebookKey={quote(value, safe='')}") + value = str(section_id) + if isinstance(section_id, bool): + value = value.lower() + query_params.append(f"sectionId={quote(value, safe='')}") + value = str(page_id) + if isinstance(page_id, bool): + value = value.lower() + query_params.append(f"pageId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_notebooks( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get recent notebooks + + Get recent notebooks. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetNotebooks`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/notebooks" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_sections_in_notebook( + self, + notebook_key: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get sections in notebook + + Get sections in a specific notebook. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetSectionsInNotebook`. + + Args: + notebook_key: A key identifying the notebook. Note this is specific + to the API and cannot be hand-typed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/notebooks/notebookKey/sections" + ) + query_params = [] + value = str(notebook_key) + if isinstance(notebook_key, bool): + value = value.lower() + query_params.append(f"notebookKey={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/orderful.py b/src/azure/connectors/aio/orderful.py new file mode 100644 index 0000000..857306b --- /dev/null +++ b/src/azure/connectors/aio/orderful.py @@ -0,0 +1,259 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# OrderfulClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping +from urllib.parse import quote +import json + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, +) + +from azure.connectors.orderful import ( + CommunicationChannelCreationResponse, + CommunicationChannelEventResponse, + CommunicationChannelInput, + CommunicationChannelRequestBody, + CreateTransactionInput, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "OrderfulClient", + "CommunicationChannelCreationResponse", + "CommunicationChannelEventResponse", + "CommunicationChannelInput", + "CommunicationChannelRequestBody", + "CreateTransactionInput", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class OrderfulClient(ConnectorClientBase): + """Typed client for orderful connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a OrderfulClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "orderful" + + async def list_transactions( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + List Transactions + + Fetches a list of transactions as specified by the filter/sort + parameters supplied. + + Swagger operation ID: `ListTransactions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/transactions" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_transaction( + self, + input: CreateTransactionInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Create Transaction + + Create Transaction. + + Swagger operation ID: `CreateTransaction`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/transactions" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_transaction_by_id( + self, + transaction_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get Transaction by ID + + Get transaction by ID. + + Swagger operation ID: `GetTransactionById`. + + Args: + transaction_id: The transaction Id used to retrieve transaction.. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/transactions/{quote(str(transaction_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) diff --git a/src/azure/connectors/aio/outlook.py b/src/azure/connectors/aio/outlook.py new file mode 100644 index 0000000..37c5a46 --- /dev/null +++ b/src/azure/connectors/aio/outlook.py @@ -0,0 +1,2176 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# OutlookClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.outlook import ( + ApprovalEmailResponse, + ApprovalEmailSubscription, + ApprovalMessage, + Attendee, + BatchResponseClientReceiveMessage, + BlobDataSetsMetadata, + CalendarEventBackend, + CalendarEventClient, + CalendarEventClientReceive, + CalendarEventClientReceiveStringEnums, + CalendarEventClientWithActionType, + CalendarEventHtmlClient, + CalendarEventList, + CalendarEventListClientReceive, + CalendarEventListWithActionType, + ClientReceiveFileAttachment, + ClientReceiveMessage, + ClientReceiveMessageStringEnums, + ClientSendAttachment, + ClientSendHtmlMessage, + ClientSendMessage, + ClientSubscription, + Contact, + ContactResponse, + DataSet, + DataSetsList, + DataSetsMetadata, + DirectForwardMessage, + EmailAddress, + EntityListResponseCalendarEventBackend, + EntityListResponseCalendarEventClientReceiveStringEnums, + EntityListResponseContactResponse, + EntityListResponseFilePickerFile, + EntityListResponseTable, + FilePickerFile, + GeoCoordinates, + InternetMessageHeader, + ItemBody, + Location, + MessageWithOptions, + ObjectEntity, + OptionsEmailSubscription, + OutlookReceiveAttachment, + OutlookReceiveMessage, + PaginatedListResponseCalendarEventClientReceiveStringEnums, + PassThroughNativeQuery, + PatternedRecurrence, + PhysicalAddress, + Procedure, + Recipient, + RecurrencePattern, + RecurrenceRange, + ReplyHtmlMessage, + ReplyMessage, + ResponseStatus, + ResponseToEventInvite, + SubscriptionEvent, + SubscriptionPayloadEntityOutlookReceiveMessage, + SubscriptionPayloadEntitySubscriptionEvent, + SubscriptionPayloadOutlookReceiveMessage, + SubscriptionPayloadSubscriptionEvent, + SubscriptionResponse, + Table, + TableCapabilitiesMetadata, + TableFilterRestrictionsMetadata, + TableMetadata, + TableSelectRestrictionsMetadata, + TableSortRestrictionsMetadata, + TabularDataSetsMetadata, + TriggerBatchResponseClientReceiveMessage, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "OutlookClient", + "ApprovalEmailResponse", + "ApprovalEmailSubscription", + "ApprovalMessage", + "Attendee", + "BatchResponseClientReceiveMessage", + "BlobDataSetsMetadata", + "CalendarEventBackend", + "CalendarEventClient", + "CalendarEventClientReceive", + "CalendarEventClientReceiveStringEnums", + "CalendarEventClientWithActionType", + "CalendarEventHtmlClient", + "CalendarEventList", + "CalendarEventListClientReceive", + "CalendarEventListWithActionType", + "ClientReceiveFileAttachment", + "ClientReceiveMessage", + "ClientReceiveMessageStringEnums", + "ClientSendAttachment", + "ClientSendHtmlMessage", + "ClientSendMessage", + "ClientSubscription", + "Contact", + "ContactResponse", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "DirectForwardMessage", + "EmailAddress", + "EntityListResponseCalendarEventBackend", + "EntityListResponseCalendarEventClientReceiveStringEnums", + "EntityListResponseContactResponse", + "EntityListResponseFilePickerFile", + "EntityListResponseTable", + "FilePickerFile", + "GeoCoordinates", + "InternetMessageHeader", + "ItemBody", + "Location", + "MessageWithOptions", + "ObjectEntity", + "OptionsEmailSubscription", + "OutlookReceiveAttachment", + "OutlookReceiveMessage", + "PaginatedListResponseCalendarEventClientReceiveStringEnums", + "PassThroughNativeQuery", + "PatternedRecurrence", + "PhysicalAddress", + "Procedure", + "Recipient", + "RecurrencePattern", + "RecurrenceRange", + "ReplyHtmlMessage", + "ReplyMessage", + "ResponseStatus", + "ResponseToEventInvite", + "SubscriptionEvent", + "SubscriptionPayloadEntityOutlookReceiveMessage", + "SubscriptionPayloadEntitySubscriptionEvent", + "SubscriptionPayloadOutlookReceiveMessage", + "SubscriptionPayloadSubscriptionEvent", + "SubscriptionResponse", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TabularDataSetsMetadata", + "TriggerBatchResponseClientReceiveMessage", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class OutlookClient(ConnectorClientBase): + """Typed client for outlook connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a OutlookClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "outlook" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def get_email( + self, + message_id: str, + *, + include_attachments: Optional[bool] = None, + internet_message_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get email + + This operation gets an email by id. + + Swagger operation ID: `GetEmail`. + + Args: + message_id: Id of the email. + include_attachments: If set to true, attachments content will also + be retrieved along with the email. + internet_message_id: Internet Message Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Mail/{quote(str(message_id), safe='')}" + ) + query_params = [] + if include_attachments is not None: + value = str(include_attachments) + if isinstance(include_attachments, bool): + value = value.lower() + query_params.append(f"includeAttachments={quote(value, safe='')}") + if internet_message_id is not None: + value = str(internet_message_id) + if isinstance(internet_message_id, bool): + value = value.lower() + query_params.append(f"internetMessageId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_email( + self, + message_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete email + + This operation deletes an email by id. + + Swagger operation ID: `DeleteEmail`. + + Args: + message_id: Id of the email to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Mail/{quote(str(message_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def move( + self, + message_id: str, + folder_path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Move email + + This operation moves an email to the specified folder. + + Swagger operation ID: `Move`. + + Args: + message_id: Id of the email to be moved. + folder_path: Mail folder to move the email to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Mail/Move/{quote(str(message_id), safe='')}" + ) + query_params = [] + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def flag( + self, + message_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Flag email + + This operation flags an email. + + Swagger operation ID: `Flag`. + + Args: + message_id: Id of the email to be flagged. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Mail/Flag/{quote(str(message_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def mark_as_read( + self, + message_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Mark as read + + This operation marks an email as having been read. + + Swagger operation ID: `MarkAsRead`. + + Args: + message_id: Id of the email to be marked as read. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Mail/MarkAsRead/{quote(str(message_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_attachment( + self, + message_id: str, + attachment_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get attachment + + This operation gets an email attachment by id. + + Swagger operation ID: `GetAttachment`. + + Args: + message_id: Id of the email. + attachment_id: Id of the attachment to download. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/Mail" + f"/{quote(str(message_id), safe='')}" + f"/Attachments" + f"/{quote(str(attachment_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def send_mail_with_options( + self, + input: OptionsEmailSubscription | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send email with options + + This operation sends an email with multiple options and waits for the + recipient to respond back with one of the options. Please refer to the + following link regarding the support of actionable messages in + different mail clients: + https://docs.microsoft.com/outlook/actionable-messages/#outlook-version-requirements-for-actionable-messages. + + Swagger operation ID: `SendMailWithOptions`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/mailwithoptions/$subscriptions" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_approval_mail( + self, + input: ApprovalEmailSubscription | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send approval email + + This operation sends an approval email and waits for a response from + the recipient. Please refer to the following link regarding the support + of actionable messages in different mail clients: + https://docs.microsoft.com/outlook/actionable-messages/#outlook-version-requirements-for-actionable-messages. + + Swagger operation ID: `SendApprovalMail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/approvalmail/$subscriptions" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_calendar_get_tables( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get calendars + + This operation lists available calendars. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `CalendarGetTables`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/calendars/tables" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def calendar_delete_item( + self, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete event + + This operation deletes an event in a calendar. + + Swagger operation ID: `CalendarDeleteItem`. + + Args: + table: Select a calendar. + id: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/calendars" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_contact_get_tables( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get contact folders + + This operation lists available contacts folders. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ContactGetTables`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/contacts/tables" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_contact_get_items( + self, + table: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get contacts + + This operation gets contacts from a contacts folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ContactGetItems`. + + Args: + table: Unique identifier of the contacts folder to retrieve. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/contacts" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def contact_post_item( + self, + input: Contact | Mapping[str, Any], + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create contact + + This operation creates a new contact in a contacts folder. + + Swagger operation ID: `ContactPostItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Select a contacts folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/contacts" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def contact_get_item( + self, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get contact + + This operation gets a specific contact from a contacts folder. + + Swagger operation ID: `ContactGetItem`. + + Args: + table: Select a contacts folder. + id: Unique identifier of a contact to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/contacts" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def contact_delete_item( + self, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete contact + + This operation deletes a contact from a contacts folder. + + Swagger operation ID: `ContactDeleteItem`. + + Args: + table: Select a contacts folder. + id: Unique identifier of contact to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/contacts" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def contact_patch_item( + self, + input: Contact | Mapping[str, Any], + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update contact + + This operation updates a contact in a contacts folder. + + Swagger operation ID: `ContactPatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Select a contacts folder. + id: Unique identifier of contact to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/contacts" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def respond_to_event( + self, + input: ResponseToEventInvite | Mapping[str, Any], + event_id: str, + response: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Respond to an event invite + + Respond to an event invite. + + Swagger operation ID: `RespondToEvent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + event_id: Id of the event to respond to. + response: Response for the event invite. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/api" + f"/v2.0" + f"/me" + f"/events" + f"/{quote(str(event_id), safe='')}" + f"/{quote(str(response), safe='')}" + ) + + http_response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= http_response.status < 300): + raise ConnectorException( + "POST", + request_url, + http_response.status, + http_response.text, + response=http_response, + ) + + async def forward_email( + self, + input: DirectForwardMessage | Mapping[str, Any], + message_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Forward an email + + Forward an email. + + Swagger operation ID: `ForwardEmail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Id of the message to forward. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless" + f"/api" + f"/v2.0" + f"/me" + f"/messages" + f"/{quote(str(message_id), safe='')}" + f"/forward" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def calendar_get_item( + self, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get event + + This operation gets a specific event from a calendar. + + Swagger operation ID: `V2CalendarGetItem`. + + Args: + table: Select a calendar. + id: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/calendars" + f"/v2" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_calendar_get_items( + self, + table: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get events + + This operation gets events from a calendar. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `V3CalendarGetItems`. + + Args: + table: Select a calendar. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/calendars" + f"/v3" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def calendar_patch_item( + self, + input: CalendarEventHtmlClient | Mapping[str, Any], + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update event + + This operation updates an event in a calendar. + + Swagger operation ID: `V3CalendarPatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Select a calendar. + id: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/calendars" + f"/v3" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def calendar_post_item( + self, + input: CalendarEventHtmlClient | Mapping[str, Any], + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create event + + This operation creates a new event in a calendar. + + Swagger operation ID: `V3CalendarPostItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Select a calendar. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/calendars" + f"/v3" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_emails( + self, + *, + folder_path: Optional[str] = None, + to: Optional[str] = None, + cc: Optional[str] = None, + to_or_cc: Optional[str] = None, + from_: Optional[str] = None, + importance: Optional[str] = None, + fetch_only_with_attachment: Optional[bool] = None, + subject_filter: Optional[str] = None, + fetch_only_unread: Optional[bool] = None, + include_attachments: Optional[bool] = None, + search_query: Optional[str] = None, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get emails + + This operation gets emails from a folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetEmailsV2`. + + Args: + folder_path: Mail folder to retrieve emails from (default: + 'Inbox'). + to: Recipient email addresses separated by semicolons (If any + match, the trigger will run). + cc: CC recipient email addresses separated by semicolons (If any + match, the trigger will run). + to_or_cc: To or CC recipient email addresses separated by + semicolons (If any match, the trigger will run). + from_: Sender email addresses separated by semicolons (If any + match, the trigger will run). + importance: Importance of the email (Any, High, Normal, Low). + fetch_only_with_attachment: If set to true, only emails with an + attachment will be retrieved. Emails without any attachments + will be skipped. If set to false, all emails will be retrieved. + subject_filter: String to look for in the subject line. + fetch_only_unread: Retrieve only unread emails?. + include_attachments: If set to true, attachments content will also + be retrieved along with the email. + search_query: Search query to filter emails. How to use '$search' + parameter please refer to: + https://docs.microsoft.com/previous-versions/office/office-365-api/api/version-2.0/complex-types-for-mail-contacts-calendar#search-requests. + top: Number of emails to retrieve (default: 10). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/Mail" + query_params = [] + query_params.append("fetchOnlyFlagged=" + quote("false", safe='')) + if folder_path is not None: + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + if to is not None: + value = str(to) + if isinstance(to, bool): + value = value.lower() + query_params.append(f"to={quote(value, safe='')}") + if cc is not None: + value = str(cc) + if isinstance(cc, bool): + value = value.lower() + query_params.append(f"cc={quote(value, safe='')}") + if to_or_cc is not None: + value = str(to_or_cc) + if isinstance(to_or_cc, bool): + value = value.lower() + query_params.append(f"toOrCc={quote(value, safe='')}") + if from_ is not None: + value = str(from_) + if isinstance(from_, bool): + value = value.lower() + query_params.append(f"from={quote(value, safe='')}") + if importance is not None: + value = str(importance) + if isinstance(importance, bool): + value = value.lower() + query_params.append(f"importance={quote(value, safe='')}") + if fetch_only_with_attachment is not None: + value = str(fetch_only_with_attachment) + if isinstance(fetch_only_with_attachment, bool): + value = value.lower() + query_params.append(f"fetchOnlyWithAttachment={quote(value, safe='')}") + if subject_filter is not None: + value = str(subject_filter) + if isinstance(subject_filter, bool): + value = value.lower() + query_params.append(f"subjectFilter={quote(value, safe='')}") + if fetch_only_unread is not None: + value = str(fetch_only_unread) + if isinstance(fetch_only_unread, bool): + value = value.lower() + query_params.append(f"fetchOnlyUnread={quote(value, safe='')}") + if include_attachments is not None: + value = str(include_attachments) + if isinstance(include_attachments, bool): + value = value.lower() + query_params.append(f"includeAttachments={quote(value, safe='')}") + if search_query is not None: + value = str(search_query) + if isinstance(search_query, bool): + value = value.lower() + query_params.append(f"searchQuery={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_events_calendar_view( + self, + calendar_id: str, + start_date_time_offset: str, + end_date_time_offset: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + search: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get calendar view of events + + This operation gets all events (including instances of recurrences) in + a calendar. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetEventsCalendarViewV2`. + + Args: + calendar_id: Select a calendar. + start_date_time_offset: Start time (example: + '2017-01-01T08:00:00-07:00'). + end_date_time_offset: End time (example: + '2017-02-01T08:00:00-07:00'). + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + search: Search text for matching event body and subject. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/calendars/v2/tables/items/calendarview" + ) + query_params = [] + value = str(calendar_id) + if isinstance(calendar_id, bool): + value = value.lower() + query_params.append(f"calendarId={quote(value, safe='')}") + value = str(start_date_time_offset) + if isinstance(start_date_time_offset, bool): + value = value.lower() + query_params.append(f"startDateTimeOffset={quote(value, safe='')}") + value = str(end_date_time_offset) + if isinstance(end_date_time_offset, bool): + value = value.lower() + query_params.append(f"endDateTimeOffset={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if search is not None: + value = str(search) + if isinstance(search, bool): + value = value.lower() + query_params.append(f"search={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def reply_to( + self, + input: ReplyHtmlMessage | Mapping[str, Any], + message_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Reply to email + + This operation replies to an email. + + Swagger operation ID: `ReplyToV3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Id of the email to reply to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v3/Mail/ReplyTo/{quote(str(message_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def send_email( + self, + input: ClientSendHtmlMessage | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Send an email + + This operation sends an email message. + + Swagger operation ID: `SendEmailV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/Mail" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) diff --git a/src/azure/connectors/aio/pdfco.py b/src/azure/connectors/aio/pdfco.py new file mode 100644 index 0000000..d84bc4e --- /dev/null +++ b/src/azure/connectors/aio/pdfco.py @@ -0,0 +1,3349 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# PdfcoClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping +import json + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, +) + +from azure.connectors.pdfco import ( + BarcodeGeneratorInput, + BarcodeGeneratorResponse, + BarcodeReaderInput, + BarcodeReaderResponse, + DocumentParserInput, + DocumentParserResponse, + EmailAttachmentExtractionInput, + EmailAttachmentExtractionResponse, + EmailDecodeInput, + EmailDecodeResponse, + EmailSendInput, + EmailSendResponse, + HtmlToPdfInput, + HtmlToPdfResponse, + JobCheckInput, + JobCheckResponse, + MergePdfInput, + MergePdfResponse, + MergePdfSimplifiedInput, + MergePdfSimplifiedResponse, + PDFAddSecurityInput, + PDFAddSecurityResponse, + PDFAttachmentExtractionInput, + PDFAttachmentExtractionResponse, + PDFAutoRotatePagesInput, + PDFAutoRotatePagesResponse, + PDFClassifierInput, + PDFClassifierResponse, + PDFCompressInput, + PDFCompressResponse, + PDFDeletePagesInput, + PDFDeletePagesResponse, + PDFFindTableInput, + PDFFindTableResponse, + PDFFormsInfoReaderInput, + PDFFormsInfoReaderResponse, + PDFFromCSVInput, + PDFFromCSVResponse, + PDFFromDocInput, + PDFFromDocResponse, + PDFFromEmailInput, + PDFFromEmailResponse, + PDFFromImagesInput, + PDFFromImagesResponse, + PDFFromXLSXLSXInput, + PDFFromXLSXLSXResponse, + PDFInfoReaderInput, + PDFInfoReaderResponse, + PDFRotatePagesInput, + PDFRotatePagesResponse, + PDFSearchTextInput, + PDFSearchTextResponse, + PDFSearchableInput, + PDFSearchableResponse, + PDFSecurityRemoveInput, + PDFSecurityRemoveResponse, + PDFToCSVInput, + PDFToCSVResponse, + PDFToJPGInput, + PDFToJPGResponse, + PDFToJSONInput, + PDFToJSONMetaInput, + PDFToJSONMetaResponse, + PDFToJSONResponse, + PDFToPNGInput, + PDFToPNGResponse, + PDFToTIFFInput, + PDFToTIFFResponse, + PDFToTextInput, + PDFToTextResponse, + PDFToTextSimpleInput, + PDFToTextSimpleResponse, + PDFToWEBPInput, + PDFToWEBPResponse, + PDFToXLSInput, + PDFToXLSResponse, + PDFToXLSXInput, + PDFToXLSXResponse, + PDFToXMLInput, + PDFToXMLResponse, + PDFUnSearchableInput, + PDFUnSearchableResponse, + PdfFillerInput, + PdfFillerResponse, + SearchAndDeleteTextInput, + SearchAndDeleteTextResponse, + SearchAndReplaceInput, + SearchAndReplaceResponse, + SearchAndReplaceWithImageInput, + SearchAndReplaceWithImageResponse, + SplitPdf2Input, + SplitPdf2Response, + SplitPdfInput, + SplitPdfResponse, + UrlToPdfInput, + UrlToPdfResponse, + XLStoCSVInput, + XLStoCSVResponse, + XLStoHTMLInput, + XLStoHTMLResponse, + XLStoJSONInput, + XLStoJSONResponse, + XLStoTXTInput, + XLStoTXTResponse, + XLStoXMLInput, + XLStoXMLResponse, +) + +__all__ = [ + "PdfcoClient", + "BarcodeGeneratorInput", + "BarcodeGeneratorResponse", + "BarcodeReaderInput", + "BarcodeReaderResponse", + "DocumentParserInput", + "DocumentParserResponse", + "EmailAttachmentExtractionInput", + "EmailAttachmentExtractionResponse", + "EmailDecodeInput", + "EmailDecodeResponse", + "EmailSendInput", + "EmailSendResponse", + "HtmlToPdfInput", + "HtmlToPdfResponse", + "JobCheckInput", + "JobCheckResponse", + "MergePdfInput", + "MergePdfResponse", + "MergePdfSimplifiedInput", + "MergePdfSimplifiedResponse", + "PDFAddSecurityInput", + "PDFAddSecurityResponse", + "PDFAttachmentExtractionInput", + "PDFAttachmentExtractionResponse", + "PDFAutoRotatePagesInput", + "PDFAutoRotatePagesResponse", + "PDFClassifierInput", + "PDFClassifierResponse", + "PDFCompressInput", + "PDFCompressResponse", + "PDFDeletePagesInput", + "PDFDeletePagesResponse", + "PDFFindTableInput", + "PDFFindTableResponse", + "PDFFormsInfoReaderInput", + "PDFFormsInfoReaderResponse", + "PDFFromCSVInput", + "PDFFromCSVResponse", + "PDFFromDocInput", + "PDFFromDocResponse", + "PDFFromEmailInput", + "PDFFromEmailResponse", + "PDFFromImagesInput", + "PDFFromImagesResponse", + "PDFFromXLSXLSXInput", + "PDFFromXLSXLSXResponse", + "PDFInfoReaderInput", + "PDFInfoReaderResponse", + "PDFRotatePagesInput", + "PDFRotatePagesResponse", + "PDFSearchTextInput", + "PDFSearchTextResponse", + "PDFSearchableInput", + "PDFSearchableResponse", + "PDFSecurityRemoveInput", + "PDFSecurityRemoveResponse", + "PDFToCSVInput", + "PDFToCSVResponse", + "PDFToJPGInput", + "PDFToJPGResponse", + "PDFToJSONInput", + "PDFToJSONMetaInput", + "PDFToJSONMetaResponse", + "PDFToJSONResponse", + "PDFToPNGInput", + "PDFToPNGResponse", + "PDFToTIFFInput", + "PDFToTIFFResponse", + "PDFToTextInput", + "PDFToTextResponse", + "PDFToTextSimpleInput", + "PDFToTextSimpleResponse", + "PDFToWEBPInput", + "PDFToWEBPResponse", + "PDFToXLSInput", + "PDFToXLSResponse", + "PDFToXLSXInput", + "PDFToXLSXResponse", + "PDFToXMLInput", + "PDFToXMLResponse", + "PDFUnSearchableInput", + "PDFUnSearchableResponse", + "PdfFillerInput", + "PdfFillerResponse", + "SearchAndDeleteTextInput", + "SearchAndDeleteTextResponse", + "SearchAndReplaceInput", + "SearchAndReplaceResponse", + "SearchAndReplaceWithImageInput", + "SearchAndReplaceWithImageResponse", + "SplitPdf2Input", + "SplitPdf2Response", + "SplitPdfInput", + "SplitPdfResponse", + "UrlToPdfInput", + "UrlToPdfResponse", + "XLStoCSVInput", + "XLStoCSVResponse", + "XLStoHTMLInput", + "XLStoHTMLResponse", + "XLStoJSONInput", + "XLStoJSONResponse", + "XLStoTXTInput", + "XLStoTXTResponse", + "XLStoXMLInput", + "XLStoXMLResponse", +] + + +# Type Definitions + +# Client Class + +class PdfcoClient(ConnectorClientBase): + """Typed client for pdfco connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a PdfcoClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "pdfco" + + async def html_to_pdf( + self, + input: HtmlToPdfInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + HTML to PDF + + Convert HTML code snippet into full featured PDF. Please see api + documentation at https://developer.pdf.co/api/pdf-to-html/index.html + for comprehensive guidelines. + + Swagger operation ID: `HtmlToPdf`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1/pdf/convert/from/html" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def url_to_pdf( + self, + input: UrlToPdfInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + URL to PDF + + Create PDF from URL. Please see api documentation at + https://developer.pdf.co/api/pdf-from-url/index.html for comprehensive + guidelines. + + Swagger operation ID: `UrlToPdf`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/convert/from/url" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_filler( + self, + input: PdfFillerInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Text, Images, Form Fields to PDF + + Add text, images, signatures to pdf. Fill PDF form fields and create + new pdf from templates. Please see api documentation at + https://developer.pdf.co/api/pdf-add/index.html for comprehensive + guidelines. + + Swagger operation ID: `PdfFiller`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/edit/add" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def merge_pdf_simplified( + self, + input: MergePdfSimplifiedInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Merge PDF + + Merge PDF from two or more PDF files into a new one. Please see api + documentation at https://developer.pdf.co/api/pdf-merge/index.html for + comprehensive guidelines. + + Swagger operation ID: `MergePdfSimplified`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/merge" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def merge_pdf( + self, + input: MergePdfInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Merge PDF (Advanced) + + Merge PDF from two or more pdf, doc, xls, images, even zip with + documents and images into a new PDF. Supports zip, doc, docx, xls, + xlsx, rtf, txt, png, jpg. Please see api documentation at + https://developer.pdf.co/api/pdf-merge/index.html#post-tag-pdf-merge2 + for comprehensive guidelines. + + Swagger operation ID: `MergePdf`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/merge2" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def split_pdf( + self, + input: SplitPdfInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Split PDF + + Splits pages from PDF document into multiple new PDF files using page + numbers and page ranges. Please see api documentation at + https://developer.pdf.co/api/pdf-split/index.html for comprehensive + guidelines. + + Swagger operation ID: `SplitPdf`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/split" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def split_pdf2( + self, + input: SplitPdf2Input | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Split PDF (Advanced) + + Split PDF into multiple PDF files by text search (support regular + expressions) or barcode. Please see api documentation at + https://developer.pdf.co/api/pdf-split/index.html#post-tag-pdf-split2 + for comprehensive guidelines. + + Swagger operation ID: `SplitPdf2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/split2" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_search_text( + self, + input: PDFSearchTextInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF Search Text + + Search text in PDF and get coordinates. Supports regular expressions. + Please see api documentation at + https://developer.pdf.co/api/pdf-find/index.html for comprehensive + guidelines. + + Swagger operation ID: `PDFSearchText`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/find" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def document_parser( + self, + input: DocumentParserInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Document Parser + + Document Parser can automatically parse PDF, JPG, and PNG documents to + extract fields, tables, values, and barcodes from invoices, statements, + orders, and other PDF and scanned documents. Please see api + documentation at + https://developer.pdf.co/api/document-parser/index.html for + comprehensive guidelines. + + Swagger operation ID: `DocumentParser`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/documentparser" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def job_check( + self, + input: JobCheckInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Background Jobs Check + + Checks status of background job that was previously created with PDF.co + API. Please see api documentation at + https://developer.pdf.co/api/background-job-check/index.html for + comprehensive guidelines. + + Swagger operation ID: `JobCheck`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/job/check" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def barcode_generator( + self, + input: BarcodeGeneratorInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Barcode Generator + + Generate high quality barcode images. Supports QR Code, Datamatrix, + Code 39, Code 128, PDF417 and many other barcode types. Please see api + documentation at + https://developer.pdf.co/api/barcode-generator/index.html for + comprehensive guidelines. + + Swagger operation ID: `BarcodeGenerator`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/barcode/generate" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def barcode_reader( + self, + input: BarcodeReaderInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Barcode Reader + + Read barcodes from images and PDF. Can read all popular barcode types + from QR Code and Code 128, EAN to Datamatrix, PDF417, GS1 and many + other barcodes. Please see api documentation at + https://developer.pdf.co/api/barcode-reader/index.html for + comprehensive guidelines. + + Swagger operation ID: `BarcodeReader`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1/barcode/read/from/url" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_info_reader( + self, + input: PDFInfoReaderInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF Info Reader + + Get detailed information about the PDF document, it's properties and + security permissions. Please see api documentation at + https://developer.pdf.co/api/pdf-info-reader/index.html for + comprehensive guidelines. + + Swagger operation ID: `PDFInfoReader`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/info" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_forms_info_reader( + self, + input: PDFFormsInfoReaderInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF Forms Info Reader + + Get information about fillable fields inside PDF form file. Please see + api documentation at + https://developer.pdf.co/api/pdf-forms-info-reader/index.html for + comprehensive guidelines. + + Swagger operation ID: `PDFFormsInfoReader`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/info/fields" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_find_table( + self, + input: PDFFindTableInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF Find Table + + AI powered document analysis can scan your document for tables and + return the array of tables on pages with coordinates and information + about columns detected in these tables. Please see api documentation at + https://developer.pdf.co/api/pdf-find/index.html#post-tag-pdf-find-table + for comprehensive guidelines. + + Swagger operation ID: `PDFFindTable`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/find/table" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def search_and_replace( + self, + input: SearchAndReplaceInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF Search and Replace Text + + Modify a PDF file by searching for specific text and replacing it with + new text. Please see api documentation at + https://developer.pdf.co/api/pdf-search-and-replace-text/index.html#post-tag-pdf-edit-replace-text + for comprehensive guidelines. + + Swagger operation ID: `SearchAndReplace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1/pdf/edit/replace-text" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def search_and_replace_with_image( + self, + input: SearchAndReplaceWithImageInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF Search and Replace Text with Image + + Replace specific text in a PDF document with an image. Please see api + documentation at + https://developer.pdf.co/api/pdf-search-and-replace-text/index.html#post-tag-pdf-edit-replace-text-with-image + for comprehensive guidelines. + + Swagger operation ID: `SearchAndReplaceWithImage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1/pdf/edit/replace-text-with-image" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def search_and_delete_text( + self, + input: SearchAndDeleteTextInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF Search and Delete Text from PDF + + Search text in PDF and remove found text from PDF. Please see api + documentation at + https://developer.pdf.co/api/pdf-search-and-delete-text/index.html for + comprehensive guidelines. + + Swagger operation ID: `SearchAndDeleteText`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/edit/delete-text" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_searchable( + self, + input: PDFSearchableInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Make Scanned PDF to Text Searchable + + Turn PDF and scanned JPG, PNG images into text-searchable PDF. Please + see api documentation at + https://developer.pdf.co/api/pdf-make-text-searchable-or-unsearchable/index.html#post-tag-pdf-makesearchable + for comprehensive guidelines. + + Swagger operation ID: `PDFSearchable`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/makesearchable" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_unsearchable( + self, + input: PDFUnSearchableInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF to Scanned PDF + + Convert PDF to Scanned PDF. Result PDF is same as if you printed and + then scanned your PDF. Please see api documentation at + https://developer.pdf.co/api/pdf-make-text-searchable-or-unsearchable/index.html#post-tag-pdf-makeunsearchable + for comprehensive guidelines. + + Swagger operation ID: `PDFUnSearchable`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/makeunsearchable" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_to_csv( + self, + input: PDFToCSVInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF To CSV + + Convert PDF and scanned images into CSV representation with layout, + columns, rows, and tables. Please see api documentation at + https://developer.pdf.co/api/pdf-to-csv/index.html for comprehensive + guidelines. + + Swagger operation ID: `PDFToCSV`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/csv" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_to_json( + self, + input: PDFToJSONInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF To JSON + + Convert PDF and scanned images into JSON representation with text, + fonts, images, vectors, and formatting preserved. Please see api + documentation at https://developer.pdf.co/api/pdf-to-json/index.html + for comprehensive guidelines. + + Swagger operation ID: `PDFToJSON`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/json2" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_to_json_meta( + self, + input: PDFToJSONMetaInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF To JSON (AI Powered) + + Convert PDF and scanned images into JSON representation with text, + fonts, images, vectors, and formatting preserved. Please see api + documentation at + https://developer.pdf.co/api/pdf-to-json/index.html#post-tag-pdf-convert-to-json-meta + for comprehensive guidelines. + + Swagger operation ID: `PDFToJSONMeta`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1/pdf/convert/to/json-meta" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_to_text( + self, + input: PDFToTextInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF To Text (with layout and ocr) + + Convert PDF and scanned images to Text with layout preserved. Please + see api documentation at + https://developer.pdf.co/api/pdf-to-text/index.html for comprehensive + guidelines. + + Swagger operation ID: `PDFToText`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/text" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_to_text_simple( + self, + input: PDFToTextSimpleInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF To Text (without layout and ocr) + + Convert PDF to plain text without layout preserved and OCR support. + Please see api documentation at + https://developer.pdf.co/api/pdf-to-text/index.html#post-tag-pdf-convert-to-text-simple + for comprehensive guidelines. + + Swagger operation ID: `PDFToTextSimple`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1/pdf/convert/to/text-simple" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_to_xls( + self, + input: PDFToXLSInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF To XLS + + Convert PDF and scanned images to spreadsheet with layout and fonts + preserved. Please see api documentation at + https://developer.pdf.co/api/pdf-to-excel/index.html#post-tag-pdf-convert-to-xls + for comprehensive guidelines. + + Swagger operation ID: `PDFToXLS`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/xls" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_to_xlsx( + self, + input: PDFToXLSXInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF To XLSX + + Convert PDF and scanned images to spreadsheet with layout and fonts + preserved. Please see api documentation at + https://developer.pdf.co/api/pdf-to-excel/index.html#post-tag-pdf-convert-to-xlsx + for comprehensive guidelines. + + Swagger operation ID: `PDFToXLSX`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/xlsx" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_to_xml( + self, + input: PDFToXMLInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF To XML + + Convert PDF to XML with information about text value, tables, fonts, + images, objects positions. Please see api documentation at + https://developer.pdf.co/api/pdf-to-xml/index.html for comprehensive + guidelines. + + Swagger operation ID: `PDFToXML`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/xml" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_to_jpg( + self, + input: PDFToJPGInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF to JPG + + PDF to JPG conversion. High-quality rendering. Also works great for + thumbnail generation and previews. Please see api documentation at + https://developer.pdf.co/api/pdf-to-image/index.html#post-tag-pdf-convert-to-jpg + for comprehensive guidelines. + + Swagger operation ID: `PDFToJPG`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/jpg" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_to_png( + self, + input: PDFToPNGInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF to PNG + + PDF to PNG conversion. High-quality rendering. Also works great for + thumbnail generation and previews. Please see api documentation at + https://developer.pdf.co/api/pdf-to-image/index.html#post-tag-pdf-convert-to-png + for comprehensive guidelines. + + Swagger operation ID: `PDFToPNG`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/png" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_to_webp( + self, + input: PDFToWEBPInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF to WEBP + + PDF to WEBP conversion. High-quality rendering. Also works great for + thumbnail generation and previews. Please see api documentation at + https://developer.pdf.co/api/pdf-to-image/index.html#post-tag-pdf-convert-to-webp + for comprehensive guidelines. + + Swagger operation ID: `PDFToWEBP`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/webp" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_to_tiff( + self, + input: PDFToTIFFInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF to TIFF + + PDF to high quality TIFF images conversion. High quality rendering. + Also works great for thumbnail generation and previews. Please see api + documentation at + https://developer.pdf.co/api/pdf-to-image/index.html#post-tag-pdf-convert-to-tiff + for comprehensive guidelines. + + Swagger operation ID: `PDFToTIFF`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/tiff" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_from_csv( + self, + input: PDFFromCSVInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF from CSV + + Convert CSV document to PDF. Works also with XLS or XLSX input. Please + see api documentation at + https://developer.pdf.co/api/pdf-from-document/index.html#post-tag-pdf-convert-from-csv + for comprehensive guidelines. + + Swagger operation ID: `PDFFromCSV`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/convert/from/csv" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_from_doc( + self, + input: PDFFromDocInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF from Document (Doc, DocX, RTF, TXT, XPS) + + Convert DOC, DOCX, RTF, TXT, XPS files into PDF. Please see api + documentation at + https://developer.pdf.co/api/pdf-from-document/index.html#post-tag-pdf-convert-from-doc + for comprehensive guidelines. + + Swagger operation ID: `PDFFromDoc`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/convert/from/doc" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_from_images( + self, + input: PDFFromImagesInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF from Image + + Create a PDF file from one or more JPG, PNG, TIFF images. Please see + api documentation at + https://developer.pdf.co/api/pdf-from-image/index.html for + comprehensive guidelines. + + Swagger operation ID: `PDFFromImages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1/pdf/convert/from/image" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_from_email( + self, + input: PDFFromEmailInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF from Email + + Convert email files (MSG or EML) code into PDF. Extracts attachments + (if any) from input email and embeds into PDF as pdf attachments. + Please see api documentation at + https://developer.pdf.co/api/pdf-from-email/index.html for + comprehensive guidelines. + + Swagger operation ID: `PDFFromEmail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1/pdf/convert/from/email" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_add_security( + self, + input: PDFAddSecurityInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF Add Security + + Add password and security limitations to existing PDF. Please see api + documentation at + https://developer.pdf.co/api/password-and-security/index.html#post-tag-pdf-security-add + for comprehensive guidelines. + + Swagger operation ID: `PDFAddSecurity`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/security/add" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_security_remove( + self, + input: PDFSecurityRemoveInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF Remove Security + + Remove password and security from existing PDF files. Please see api + documentation at + https://developer.pdf.co/api/password-and-security/index.html#post-tag-pdf-security-remove + for comprehensive guidelines. + + Swagger operation ID: `PDFSecurityRemove`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/security/remove" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_from_xls_xlsx( + self, + input: PDFFromXLSXLSXInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF From Spreadsheet + + Create PDF from XLS, XLSX spreadsheet. Please see api documentation at + https://developer.pdf.co/api/convert-excel/index.html#post-tag-xls-convert-to-pdf + for comprehensive guidelines. + + Swagger operation ID: `PDFFromXLSXLSX`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/xls/convert/to/pdf" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def xls_to_csv( + self, + input: XLStoCSVInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Spreadsheet to CSV + + Convert XLS/XLSX into CSV comma separated values file. Please see api + documentation at + https://developer.pdf.co/api/convert-excel/index.html#post-tag-xls-convert-to-csv + for comprehensive guidelines. + + Swagger operation ID: `XLStoCSV`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/xls/convert/to/csv" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def xls_to_json( + self, + input: XLStoJSONInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Spreadsheet to JSON + + Convert XLS/XLSX into JSON file. Please see api documentation at + https://developer.pdf.co/api/convert-excel/index.html#post-tag-xls-convert-to-json + for comprehensive guidelines. + + Swagger operation ID: `XLStoJSON`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/xls/convert/to/json" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def xls_to_html( + self, + input: XLStoHTMLInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Spreadsheet to HTML + + Convert XLS/XLSX into HTML file. Please see api documentation at + https://developer.pdf.co/api/convert-excel/index.html#post-tag-xls-convert-to-html + for comprehensive guidelines. + + Swagger operation ID: `XLStoHTML`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/xls/convert/to/html" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def xls_to_txt( + self, + input: XLStoTXTInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Spreadsheet to TXT + + Convert XLS/XLSX or CSV into Text file. Please see api documentation at + https://developer.pdf.co/api/convert-excel/index.html#post-tag-xls-convert-to-txt + for comprehensive guidelines. + + Swagger operation ID: `XLStoTXT`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/xls/convert/to/txt" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def xls_to_xml( + self, + input: XLStoXMLInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Spreadsheet to XML + + Convert XLS/XLSX or CSV into XML file. Please see api documentation at + https://developer.pdf.co/api/convert-excel/index.html#post-tag-xls-convert-to-xml + for comprehensive guidelines. + + Swagger operation ID: `XLStoXML`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/xls/convert/to/xml" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_rotate_pages( + self, + input: PDFRotatePagesInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Rotate PDF Pages + + Rotate PDF Pages. Please see api documentation at + https://developer.pdf.co/api/pdf-rotate-pages/index.html for + comprehensive guidelines. + + Swagger operation ID: `PDFRotatePages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/edit/rotate" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_auto_rotate_pages( + self, + input: PDFAutoRotatePagesInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Rotate PDF Pages (Auto) + + Uses AI to automatically fix the rotation of pages inside scanned PDF + based on text analysis. Please see api documentation at + https://developer.pdf.co/api/pdf-rotate-pages/index.html#post-tag-pdf-edit-rotate-auto + for comprehensive guidelines. + + Swagger operation ID: `PDFAutoRotatePages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/edit/rotate/auto" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_delete_pages( + self, + input: PDFDeletePagesInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF Delete Pages + + Delete pages in PDF. Please see api documentation at + https://developer.pdf.co/api/pdf-delete-pages/index.html for + comprehensive guidelines. + + Swagger operation ID: `PDFDeletePages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1/pdf/edit/delete-pages" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_compress( + self, + input: PDFCompressInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF Compress and Optimize + + Optimize PDF document to reduce its size. Please see api documentation + at https://developer.pdf.co/api/pdf-optimize/index.html for + comprehensive guidelines. + + Swagger operation ID: `PDFCompress`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/optimize" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_classifier( + self, + input: PDFClassifierInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Document Classifier + + Auto classification Of Incoming Documents based on keywords-based + rules. For example, you can define rules to find which vendor provided + the document to find which template to apply accordingly. Please see + api documentation at + https://developer.pdf.co/api/document-classifier/index.html for + comprehensive guidelines. + + Swagger operation ID: `PDFClassifier`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/pdf/classifier" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def email_send( + self, + input: EmailSendInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send Email with Attachments + + Send Email with Attachments. Please see api documentation at + https://developer.pdf.co/api/email-send-and-decode/index.html for + comprehensive guidelines. + + Swagger operation ID: `EmailSend`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/email/send" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def email_decode( + self, + input: EmailDecodeInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Email Information + + Get Email Information such as sender/recipient, subject, body, etc. + Please see api documentation at + https://developer.pdf.co/api/email-send-and-decode/index.html#post-tag-email-decode + for comprehensive guidelines. + + Swagger operation ID: `EmailDecode`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/email/decode" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def email_attachment_extraction( + self, + input: EmailAttachmentExtractionInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Email Attachment Extraction + + Extract Email attachments with basic email information. Please see api + documentation at + https://developer.pdf.co/api/email-send-and-decode/index.html#post-tag-email-extract-attachments + for comprehensive guidelines. + + Swagger operation ID: `EmailAttachmentExtraction`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1/email/extract-attachments" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def pdf_attachment_extraction( + self, + input: PDFAttachmentExtractionInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + PDF Attachment Extraction + + Extract attachments from input PDF document. Please see api + documentation at + https://developer.pdf.co/api/extract-attachments/index.html for + comprehensive guidelines. + + Swagger operation ID: `PDFAttachmentExtraction`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1/pdf/attachments/extract" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/pipedrive.py b/src/azure/connectors/aio/pipedrive.py new file mode 100644 index 0000000..ff7225e --- /dev/null +++ b/src/azure/connectors/aio/pipedrive.py @@ -0,0 +1,592 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# PipedriveClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.pipedrive import ( + ActivityResponse, + AddActivityRequest, + AddDealRequest, + DealResponse, + DealResponseV2, + ListActivityTypesResponse, + ListCurrenciesResponse, + ListDealsResponse, + ListOrganizationsResponse, + ListPersonsResponse, + ListPipelinesResponse, + ListStagesResponse, + StageResponse, + TrigNewActivityResponse, + TrigNewDealResponse, + UpdateDealStageRequest, + UpdateDealStatusRequest, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "PipedriveClient", + "ActivityResponse", + "AddActivityRequest", + "AddDealRequest", + "DealResponse", + "DealResponseV2", + "ListActivityTypesResponse", + "ListCurrenciesResponse", + "ListDealsResponse", + "ListOrganizationsResponse", + "ListPersonsResponse", + "ListPipelinesResponse", + "ListStagesResponse", + "StageResponse", + "TrigNewActivityResponse", + "TrigNewDealResponse", + "UpdateDealStageRequest", + "UpdateDealStatusRequest", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class PipedriveClient(ConnectorClientBase): + """Typed client for pipedrive connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a PipedriveClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "pipedrive" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def get_deal( + self, + deal_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get deal by id + + This operation retrieves all details of an existing deal, given its id. + + Swagger operation ID: `GetDeal`. + + Args: + deal_id: Deal. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1/deals/{quote(str(deal_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_deal_status( + self, + input: UpdateDealStatusRequest | Mapping[str, Any], + deal_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update deal status + + This operation is used to update the status associated with a deal, + given its id. + + Swagger operation ID: `UpdateDealStatus`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + deal_id: Deal. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/update_status_deal/v1/deals/{quote(str(deal_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_activity( + self, + input: AddActivityRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add activity + + This operation is used to create a new activity for the authorized + account. + + Swagger operation ID: `AddActivity`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/activities" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_stage( + self, + stage_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get stage by id + + This operation returns data about a specific stage. + + Swagger operation ID: `GetStage`. + + Args: + stage_id: Stage Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1/stages/{quote(str(stage_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_deal( + self, + input: AddDealRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add deal + + This operation creates a new deal for the authorized account. + + Swagger operation ID: `AddDealV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/connector-v2/v1/deals" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_deal_stage( + self, + input: UpdateDealStageRequest | Mapping[str, Any], + deal_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update deal stage + + This operation is used to update the stage associated with a deal, + given its id. + + Swagger operation ID: `UpdateDealStageV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + deal_id: Deal. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/connector-v2" + f"/update_stage_deal" + f"/v1" + f"/deals" + f"/{quote(str(deal_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_deals( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List deals + + List deals + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListDeals`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/deals" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("data", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/planner.py b/src/azure/connectors/aio/planner.py new file mode 100644 index 0000000..d7bee10 --- /dev/null +++ b/src/azure/connectors/aio/planner.py @@ -0,0 +1,1157 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# PlannerClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.planner import ( + AppliedCategories, + AssignUsersInput, + CreateBucketInput, + CreateBucketResponse, + CreateTaskRequest, + ErrorResponse, + GetPlanDetailsResponse, + GetTaskDetailsResponse, + GetTaskResponse, + GetTaskResponseV2, + GetTaskResponseV3, + ListBucketsResponse, + ListGroupsResponse, + ListMyPlansResponse, + ListTasksResponse, + UnassignUsersInput, + UpdateTaskDetailsRequest, + UpdateTaskRequest, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "PlannerClient", + "AppliedCategories", + "AssignUsersInput", + "CreateBucketInput", + "CreateBucketResponse", + "CreateTaskRequest", + "ErrorResponse", + "GetPlanDetailsResponse", + "GetTaskDetailsResponse", + "GetTaskResponse", + "GetTaskResponseV2", + "GetTaskResponseV3", + "ListBucketsResponse", + "ListGroupsResponse", + "ListMyPlansResponse", + "ListTasksResponse", + "UnassignUsersInput", + "UpdateTaskDetailsRequest", + "UpdateTaskRequest", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class PlannerClient(ConnectorClientBase): + """Typed client for planner connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a PlannerClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "planner" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def delete_task( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a task + + Deletes an existing Planner task. + + Swagger operation ID: `DeleteTask`. + + Args: + id: The unique identifier of the task to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/planner/tasks/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def unassign_users( + self, + input: UnassignUsersInput | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Remove assignees from a task + + Remove assignees from an existing Planner task. + + Swagger operation ID: `UnassignUsers`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: The unique identifier of the task to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/planner/tasks/{quote(str(id), safe='')}/unassignusers" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def assign_users( + self, + input: AssignUsersInput | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add assignees to a task + + Add assignees to an existing Planner task. + + Swagger operation ID: `AssignUsers`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: The unique identifier of the task to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/planner/tasks/{quote(str(id), safe='')}/assignusers" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_group_plans( + self, + group_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List plans for a group + + List plans owned by the group specified. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListGroupPlans`. + + Args: + group_id: Id of the group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/groups/{quote(str(group_id), safe='')}/planner/plans" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_plan_details( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get plan details + + Get plan details where the task belongs to + + Swagger operation ID: `GetPlanDetails`. + + Args: + id: The unique plan id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/planner/plans/{quote(str(id), safe='')}/details" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_bucket( + self, + input: CreateBucketInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a bucket + + Create a bucket in Planner for the specified plan and group. + + Swagger operation ID: `CreateBucket_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/v1.0/planner/buckets" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_task( + self, + input: CreateTaskRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a task + + Create a new task in Planner. + + Swagger operation ID: `CreateTask_V4`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/beta/planner/tasks" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_task( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a task + + Get an existing Planner task. + + Swagger operation ID: `GetTask_V2`. + + Args: + id: The unique identifier of the task to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/planner/tasks/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_task_details( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get task details + + Get the task details for an existing task. + + Swagger operation ID: `GetTaskDetails_V2`. + + Args: + id: The unique identifier of the task to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/planner/tasks/{quote(str(id), safe='')}/details" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_buckets( + self, + id: str, + group_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List buckets + + List the buckets in a plan. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListBuckets_V3`. + + Args: + id: The unique identifier of the plan. + group_id: The group to retrieve the plan. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/v1.0/planner/plans/{quote(str(id), safe='')}/buckets" + ) + query_params = [] + value = str(group_id) + if isinstance(group_id, bool): + value = value.lower() + query_params.append(f"groupId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_my_tasks( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List my tasks + + List the tasks assigned to me. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListMyTasks_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/me/planner/tasks" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_tasks( + self, + id: str, + group_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List tasks + + List the tasks in a plan. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTasks_V3`. + + Args: + id: The unique identifier of the plan. + group_id: The group to retrieve the plan. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/v1.0/planner/plans/{quote(str(id), safe='')}/tasks" + ) + query_params = [] + value = str(group_id) + if isinstance(group_id, bool): + value = value.lower() + query_params.append(f"groupId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_task( + self, + input: UpdateTaskRequest | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a task + + Update an existing Planner task. + + Swagger operation ID: `UpdateTask_V3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: The unique identifier of the task to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/v1.0/planner/tasks/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_task_details( + self, + input: UpdateTaskDetailsRequest | Mapping[str, Any], + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update task details + + Update the task details for an existing task. + + Swagger operation ID: `UpdateTaskDetails_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: The unique identifier of the task to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/planner/tasks/{quote(str(id), safe='')}/details" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_groups( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List groups that I am member of + + Get groups that the user is a direct member of. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListGroups`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/me/memberOf" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/plivo.py b/src/azure/connectors/aio/plivo.py new file mode 100644 index 0000000..29c586e --- /dev/null +++ b/src/azure/connectors/aio/plivo.py @@ -0,0 +1,411 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# PlivoClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.plivo import ( + Call, + GetMessageResponse, + ListMessagesResponse, + MakeCallResponse, + SMS, + SendSMSResponse, +) + +__all__ = [ + "PlivoClient", + "Call", + "GetMessageResponse", + "ListMessagesResponse", + "MakeCallResponse", + "SMS", + "SendSMSResponse", +] + + +# Type Definitions + +# Client Class + +class PlivoClient(ConnectorClientBase): + """Typed client for plivo connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a PlivoClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "plivo" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def make_call( + self, + input: Call | Mapping[str, Any], + auth_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Make a call + + This operation is used to make a call. + + Swagger operation ID: `MakeCall`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + auth_id: Auth ID of your Plivo account. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1/Account/{quote(str(auth_id), safe='')}/Call/" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_messages( + self, + auth_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all messages + + This operation returns a list of all messages associated with your + Plivo account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListMessages`. + + Args: + auth_id: Auth ID of your Plivo account. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1/Account/{quote(str(auth_id), safe='')}/Message/" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("objects", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def send_sms( + self, + input: SMS | Mapping[str, Any], + auth_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send SMS + + This operation is used to send a text message. + + Swagger operation ID: `SendSMS`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + auth_id: Auth ID of your Plivo account. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1/Account/{quote(str(auth_id), safe='')}/Message/" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_message( + self, + auth_id: str, + message_uuid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get message + + This operation is used to fetch the details of a message, given the + message ID. + + Swagger operation ID: `GetMessage`. + + Args: + auth_id: Auth ID of your Plivo account. + message_uuid: UUID of the message for which the details need to be + fetched. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1" + f"/Account" + f"/{quote(str(auth_id), safe='')}" + f"/Message" + f"/{quote(str(message_uuid), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/plumsail.py b/src/azure/connectors/aio/plumsail.py new file mode 100644 index 0000000..bf1173b --- /dev/null +++ b/src/azure/connectors/aio/plumsail.py @@ -0,0 +1,3529 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# PlumsailClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping +from urllib.parse import quote +import json + +from azure.core.polling import AsyncLROPoller +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorPollingMethod, +) + +from azure.connectors.plumsail import ( + AddPowerAutomateWebhookData, + Any2PdfRequest, + ApplyDocxTemplateRequest, + ApplyHtmlFlowTemplateRequest, + ApplyHtmlTemplateResponse, + ApplyPptxTemplateRequest, + ApplyXlsxTemplateRequest, + BooleanResultResponse, + CompressPdfRequest, + CreateArchiveRequest, + Csv2XlsxColumnMapping, + Csv2XlsxRequest, + Doc2DocxRequest, + DocumentContentWithFilenameResponse, + DocumentProcessingResponse, + DocumentsArrayResponse, + DocumentsWithFilenamesResponse, + Docx2PdfRequest, + Email2PdfRequest, + ExtractArchiveRequest, + FileData, + FillInPdfFormRequest, + FlowDocumentsJobsAddWatermarkToPdfInput, + FlowDocumentsJobsGetPdfFormPostResponse, + FlowDocumentsJobsSplitPdfInput, + FlowProcessesFlowJobsExecuteProcessInput, + GetPdfFormRequest, + GetPdfProtectionInfoResponse, + Html2DocxFlowRequest, + Html2PdfFlowRequest, + Image2PdfRequest, + Json2CsvRequest, + Json2XlsxColumnMapping, + Json2XlsxRequest, + LicenseInfo, + MergeAny2PdfFileData, + MergeAny2PdfRequest, + MergeDocxRequest, + MergeFieldsTemplateRequest, + MergePdfRequest, + MergeXlsxRequest, + ParseCsvFlowRequest, + ParseCsvSchemaResponse, + Pdf2ImageRequest, + Pdf2TextRequest, + PdfProtectionInfoRequest, + Ppt2PptxRequest, + Pptx2PdfRequest, + ProcessJsonData, + ProcessSchemaDynamicType, + ProfileInfo, + ProtectPdfRequest, + RegExpMatchRequest, + RegExpMatchSchemaResponseClass, + RegExpReplaceRequest, + RegExpTestRequest, + SplitPdfRequest, + StringResultResponse, + Xls2XlsxRequest, + Xlsx2PdfRequest, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "PlumsailClient", + "AddPowerAutomateWebhookData", + "Any2PdfRequest", + "ApplyDocxTemplateRequest", + "ApplyHtmlFlowTemplateRequest", + "ApplyHtmlTemplateResponse", + "ApplyPptxTemplateRequest", + "ApplyXlsxTemplateRequest", + "BooleanResultResponse", + "CompressPdfRequest", + "CreateArchiveRequest", + "Csv2XlsxColumnMapping", + "Csv2XlsxRequest", + "Doc2DocxRequest", + "DocumentContentWithFilenameResponse", + "DocumentProcessingResponse", + "DocumentsArrayResponse", + "DocumentsWithFilenamesResponse", + "Docx2PdfRequest", + "Email2PdfRequest", + "ExtractArchiveRequest", + "FileData", + "FillInPdfFormRequest", + "FlowDocumentsJobsAddWatermarkToPdfInput", + "FlowDocumentsJobsGetPdfFormPostResponse", + "FlowDocumentsJobsSplitPdfInput", + "FlowProcessesFlowJobsExecuteProcessInput", + "GetPdfFormRequest", + "GetPdfProtectionInfoResponse", + "Html2DocxFlowRequest", + "Html2PdfFlowRequest", + "Image2PdfRequest", + "Json2CsvRequest", + "Json2XlsxColumnMapping", + "Json2XlsxRequest", + "LicenseInfo", + "MergeAny2PdfFileData", + "MergeAny2PdfRequest", + "MergeDocxRequest", + "MergeFieldsTemplateRequest", + "MergePdfRequest", + "MergeXlsxRequest", + "ParseCsvFlowRequest", + "ParseCsvSchemaResponse", + "Pdf2ImageRequest", + "Pdf2TextRequest", + "PdfProtectionInfoRequest", + "Ppt2PptxRequest", + "Pptx2PdfRequest", + "ProcessJsonData", + "ProcessSchemaDynamicType", + "ProfileInfo", + "ProtectPdfRequest", + "RegExpMatchRequest", + "RegExpMatchSchemaResponseClass", + "RegExpReplaceRequest", + "RegExpTestRequest", + "SplitPdfRequest", + "StringResultResponse", + "Xls2XlsxRequest", + "Xlsx2PdfRequest", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class PlumsailClient(ConnectorClientBase): + """Typed client for plumsail connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a PlumsailClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "plumsail" + + async def profiles_me_get( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Profile Info + + Get Profile Info returns information about current user and license. + + Swagger operation ID: `ProfilesMeGet`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/profiles/me" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def begin_flow_v1_documents_jobs_apply_docx_template( + self, + input: ApplyDocxTemplateRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Create document from DOCX template + + Create document from DOCX template. More information: + https://plumsail.com/docs/documents/v1.x/document-generation/docx/index.html + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsApplyDocxTemplatePost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/Documents/jobs/ApplyDocxTemplate" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_apply_xlsx_template( + self, + input: ApplyXlsxTemplateRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Create document from XLSX template + + Create document from XLSX template. More information: + https://plumsail.com/docs/documents/v1.x/document-generation/xlsx/index.html + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsApplyXlsxTemplatePost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/Documents/jobs/ApplyXlsxTemplate" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_apply_pptx( + self, + input: ApplyPptxTemplateRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Create document from PPTX template + + Create document from PPTX template. More information: + https://plumsail.com/docs/documents/v1.x/document-generation/pptx/index.html + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsApplyPptxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/ApplyPptx" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_apply_docx( + self, + input: MergeFieldsTemplateRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Fill merge fields in DOCX document + + Fill merge fields in DOCX document takes a DOCX document with merge + fields and replaces them by specified data. The keys in data object + should be the same as names of MergeFields (Express block) in document. + Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#fill-merge-fields-in-docx-document + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsApplyDocxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/ApplyDocx" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_apply_html( + self, + input: ApplyHtmlFlowTemplateRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Create HTML from template + + Create HTML takes input HTML template string or file and replaces + special {{Tokens}} by specified data. We use Mustache framework for + templates internally. More information about templates in Mustache + docs: http://mustache.github.io/mustache.5.html. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#create-html-from-template + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsApplyHtmlPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/ApplyHtml" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_html2_pdf( + self, + input: Html2PdfFlowRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Convert HTML to PDF + + Convert HTML to PDF file. This action takes HTML markup, renders it and + converts to PDF document. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-html-to-pdf + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsHtml2PdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Html2Pdf" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_html2_docx( + self, + input: Html2DocxFlowRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Convert HTML to DOCX + + Convert HTML to DOCX document. This action takes HTML markup, renders + it and converts to DOCX document. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-html-to-docx + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsHtml2DocxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Html2Docx" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_docx2_pdf( + self, + input: Docx2PdfRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Convert DOCX to PDF + + Convert DOCX to PDF files. This action takes DOCX document and converts + it to PDF. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-docx-to-pdf + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsDocx2PdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Docx2Pdf" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_xslx2_pdf( + self, + input: Xlsx2PdfRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Convert XLSX to PDF + + Convert XLSX to PDF files. This action takes XLSX document and converts + it to PDF. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-xlsx-to-pdf + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsXslx2PdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Xslx2Pdf" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_pptx2_pdf( + self, + input: Pptx2PdfRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Convert PPTX to PDF + + Convert PPTX to PDF files. This action takes PPTX document and converts + it to PDF. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-pptx-to-pdf + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsPptx2PdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Pptx2Pdf" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_any2_pdf_v2( + self, + input: Any2PdfRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Convert to PDF + + Convert provided file to PDF file. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-to-pdf + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsAny2PdfV2Post`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Any2PdfV2" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_email2_pdf( + self, + input: Email2PdfRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Convert Email to PDF + + Convert provided Email to PDF file. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-email-to-pdf + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsEmail2PdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Email2Pdf" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_doc2_docx( + self, + input: Doc2DocxRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Convert DOC to DOCX + + Convert DOC to DOCX files. This action takes DOC document and converts + it to DOCX. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-doc-to-docx + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsDoc2DocxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Doc2Docx" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_xls2_xlsx( + self, + input: Xls2XlsxRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Convert XLS to XLSX + + Convert XLS to XLSX files. This action takes XLS document and converts + it to XLSX. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-xls-to-xlsx + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsXls2XlsxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Xls2Xlsx" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_ppt2_pptx( + self, + input: Ppt2PptxRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Convert PPT to PPTX + + Convert PPT to PPTX files. This action takes PPT document and converts + it to PPTX. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-ppt-to-pptx + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsPpt2PptxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Ppt2Pptx" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_split_pdf_v2( + self, + input: FlowDocumentsJobsSplitPdfInput | Mapping[str, Any], + type_: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Split PDF + + Split PDF takes PDF document and splits it. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#split-pdf + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsSplitPdfV2Post`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + type_: How to split the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/SplitPdfV2" + ) + query_params = [] + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_merge_any_to_pdf_v2( + self, + input: MergeAny2PdfRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Merge any files into PDF + + Convert and merge multiple files into a single PDF document. + Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#merge-any-files-into-pdf + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsMergeAnyToPdfV2Post`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/Documents/jobs/MergeAnyToPdfV2" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_extract_text_from_pdf( + self, + input: Pdf2TextRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Extract text from PDF document + + Extract text from PDF takes PDF document and extracts text to Raw or + HTML format. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#extract-text-from-pdf-document + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsExtractTextFromPdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/Documents/jobs/ExtractTextFromPdf" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_pdf2_image_v2( + self, + input: Pdf2ImageRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Convert PDF to Image + + Convert PDF to image. This action takes PDF document and converts it to + Image (jpeg, png, gif, bmp, etc). Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-pdf-to-image + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsPdf2ImageV2Post`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/Documents/jobs/Pdf2ImageV2" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_image2_pdf( + self, + input: Image2PdfRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Convert Images to PDF + + It takes images and converts them to a PDF document + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsImage2PdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Image2Pdf" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_fill_in_pdf_form( + self, + input: FillInPdfFormRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Fill in PDF Form + + Fill in PDF Form fills out PDF from by provided data. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#fill-in-pdf-form + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsFillInPdfFormPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/Documents/jobs/FillInPdfForm" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_get_pdf_form( + self, + input: GetPdfFormRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Get Form from PDF + + Get Form from PDF returns fillable form data from PDF as JSON. + Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#get-form-from-pdf + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsGetPdfFormPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/GetPdfForm" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_protect_pdf( + self, + input: ProtectPdfRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Protect PDF document + + Protect PDF document adds passwords, copy, printing, and other + protections to PDF files. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#protect-pdf-document + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsProtectPdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/ProtectPdf" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_get_pdf_protection_info( + self, + input: PdfProtectionInfoRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Get information about PDF protection + + Get information about PDF protection returns information whether the + document is password protected. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#get-pdf-protection-information + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsGetPdfProtectionInfoPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/Documents/jobs/GetPdfProtectionInfo" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_compress_pdf( + self, + input: CompressPdfRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Compress PDF document + + Compress PDF document size if possible and optimize it. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#compress-pdf-document + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsCompressPdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/Documents/jobs/CompressPdf" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_add_watermark_to_pdf( + self, + input: FlowDocumentsJobsAddWatermarkToPdfInput | Mapping[str, Any], + type_: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Add a watermark to PDF + + Add a watermark to PDF as text, an image, HTML, or PDF. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#add-watermark-to-pdf + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsAddWatermarkToPdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + type_: The type of the watermark. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/Documents/jobs/AddWatermarkToPdf" + ) + query_params = [] + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_merge_docx( + self, + input: MergeDocxRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Merge DOCX files + + Merge DOCX files takes an array of Docx documents and merge it into + single file. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#merge-docx-files + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsMergeDocxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/MergeDocx" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_parse_csv( + self, + input: ParseCsvFlowRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Parse CSV + + Parse CSV works like Parse JSON but for CSV files. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#parse-csv + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsParseCsvPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/ParseCsv" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_csv2_xlsx( + self, + input: Csv2XlsxRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Convert CSV to Excel + + Convert CSV to Excel file (XLSX). Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#csv-to-excel + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsCsv2XlsxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Csv2Xlsx" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_json2_xlsx( + self, + input: Json2XlsxRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Convert JSON to Excel + + Convert JSON to Excel file (XLSX). Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#json-to-excel + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsJson2XlsxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Json2Xlsx" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_json2_csv( + self, + input: Json2CsvRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Convert JSON to CSV + + Convert JSON to CSV file. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#json-to-csv + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsJson2CsvPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Json2Csv" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_reg_exp_match( + self, + input: RegExpMatchRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Regular Expression Match + + Regular Expression Match searches for an input string for all + occurrences of a regular expression and returns all the matches. We + would recommend to use Regex Hero to test your expressions. It supports + the same syntax as actions. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#regular-expression-match + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsRegExpMatchPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/Documents/jobs/RegExpMatch" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_reg_exp_replace( + self, + input: RegExpReplaceRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Regular Expression Replace + + Regular Expression Replace replaces all strings that match a regular + expression pattern with a specified replacement string in a specified + input string. We would recommend to use Regex Hero to test your + expressions. It supports the same syntax as actions. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#regular-expression-replace + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsRegExpReplacePost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/Documents/jobs/RegExpReplace" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_reg_exp_test( + self, + input: RegExpTestRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Regular Expression Test + + Regular Expression Test indicates whether the regular expression + specified in the Regex constructor finds a match in a specified input + string. We would recommend to use Regex Hero to test your expressions. + It supports the same syntax as actions. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#regular-expression-test + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsRegExpTestPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/RegExpTest" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_create_archive( + self, + input: CreateArchiveRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Create Archive + + Compresses and adds files to a ZIP archive. + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsCreateArchivePost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/Documents/jobs/CreateArchive" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_extract_archive( + self, + input: ExtractArchiveRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Extract Archive + + Extract files from archive. + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsExtractArchivePost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/Documents/jobs/ExtractArchive" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_documents_jobs_merge_xlsx( + self, + input: MergeXlsxRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[dict[str, Any] | None]: + """ + Merge XLSX files + + Merge XLSX files takes an array of Xlsx documents and merge it into + single file. Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#merge-xlsx-files + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsMergeXlsxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/flow/v1/Documents/jobs/MergeXlsx" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_processes_flow_jobs_execute_process( + self, + input: FlowProcessesFlowJobsExecuteProcessInput | Mapping[str, Any], + process_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Start document generation process with json + + Start document generation process fills a DOCX, XLSX, PPTX or PDF + template related to the selected process with the JSON data. + Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html##start-process-json + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: `FlowV1ProcessesFlowJobsExecuteProcessPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + process_id: The name of process to be started. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/ProcessesFlow/jobs/ExecuteProcess" + ) + query_params = [] + value = str(process_id) + if isinstance(process_id, bool): + value = value.lower() + query_params.append(f"processId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def begin_flow_v1_processes_flow_jobs_execute_process_with_generated_data( + self, + input: ProcessJsonData | Mapping[str, Any], + process_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncLROPoller[bytes]: + """ + Start document generation process + + Start document generation process fills a DOCX, XLSX, PPTX or PDF + template related to the selected process with the JSON data. + Documentation - + https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#start-document-generation-process + + Returns an Azure Core async poller for the connector operation. + + Swagger operation ID: + `FlowV1ProcessesFlowJobsExecuteProcessWithGeneratedDataPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + process_id: The name of process to be started. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncLROPoller[bytes]: An Azure Core poller for the connector + operation. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/ProcessesFlow/jobs/ExecuteProcessWithGeneratedData" + ) + query_params = [] + value = str(process_id) + if isinstance(process_id, bool): + value = value.lower() + query_params.append(f"processId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return AsyncLROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) + + async def flow_v1_documents_flow_schema_split_pdf( + self, + type_: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + SplitPdfSchema + + System + + Swagger operation ID: `FlowV1DocumentsFlowSchemaSplitPdfPost`. + + Args: + type_: How to split the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/DocumentsFlow/Schema/SplitPdf" + ) + query_params = [] + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def flow_v1_documents_flow_schema_add_watermark_to_pdf( + self, + type_: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + AddWatermarkToPdfSchema + + System + + Swagger operation ID: `FlowV1DocumentsFlowSchemaAddWatermarkToPdfPost`. + + Args: + type_: The type of the watermark. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/DocumentsFlow/Schema/AddWatermarkToPdf" + ) + query_params = [] + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def flow_v1_processes_flow_schema_get_processes( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + GetProcessesSchema + + System + + Swagger operation ID: `FlowV1ProcessesFlowSchemaGetProcessesPost`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/ProcessesFlow/Schema/GetProcesses" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def flow_v1_documents_flow_schema_parse_csv( + self, + headers_parameter: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + ParseCsv + + System + + Swagger operation ID: `FlowV1DocumentsFlowSchemaParseCsvPost`. + + Args: + headers_parameter: headers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/DocumentsFlow/Schema/ParseCsv" + ) + query_params = [] + value = str(headers_parameter) + if isinstance(headers_parameter, bool): + value = value.lower() + query_params.append(f"headers={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def flow_v1_processes_flow_schema_get_json_data( + self, + process_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + GetJsonSchema + + System + + Swagger operation ID: `FlowV1ProcessesFlowSchemaGetJsonDataPost`. + + Args: + process_id: The name of process to be started. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/ProcessesFlow/Schema/GetJsonData" + ) + query_params = [] + value = str(process_id) + if isinstance(process_id, bool): + value = value.lower() + query_params.append(f"processId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def flow_v1_processes_flow_triggers_by_process_id_schema_get( + self, + process_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get schema of a process + + Returns schema of a process + + Swagger operation ID: + `FlowV1ProcessesFlowTriggersByProcessIdSchemaGet`. + + Args: + process_id: processId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow" + f"/v1" + f"/ProcessesFlow" + f"/triggers" + f"/{quote(str(process_id), safe='')}" + f"/schema" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + async def flow_v1_documents_flow_schema_reg_exp_match( + self, + pattern: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + RegexMatchSchema + + System + + Swagger operation ID: `FlowV1DocumentsFlowSchemaRegExpMatchPost`. + + Args: + pattern: pattern. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flow/v1/DocumentsFlow/Schema/RegExpMatch" + ) + query_params = [] + value = str(pattern) + if isinstance(pattern, bool): + value = value.lower() + query_params.append(f"pattern={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) diff --git a/src/azure/connectors/aio/powerbi.py b/src/azure/connectors/aio/powerbi.py new file mode 100644 index 0000000..e60af8d --- /dev/null +++ b/src/azure/connectors/aio/powerbi.py @@ -0,0 +1,1946 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# PowerbiClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.powerbi import ( + Alert, + Columns, + CreateGoalRequest, + CreateGoalResponse, + CreateScorecardRequest, + CreatedScorecard, + Datasets, + DynamicPowerBiButtonClickedTriggerResult, + EffectiveIdentity, + EvaluatedAlert, + ExecuteDatasetQueriesJsonInput, + ExecuteDatasetQueriesJsonResponse, + ExportFilter, + ExportPayloadPaginatedReport, + ExportPayloadPowerBIReport, + ExportReportPage, + ExportReportSettings, + FetchedGoal, + FetchedGoals, + GetGoalCheckinResponse, + GetGoalCheckinsResponse, + GoalChanged, + GoalNotes, + GoalRefreshIssue, + GoalRefreshIssues, + GoalStatusChanged, + GoalValueChanged, + GoalValueCheckinNoteInput, + GoalValueCheckinRequest, + GoalValueCheckinUpdateRequest, + GoalValueOrNoteUpserted, + GoalsAssigned, + Groups, + IdentityBlob, + ListedScorecard, + ListedScorecards, + PageBookmark, + Payload, + PowerBiButtonClickedOutputs, + QueryExecutionResults, + QuerySpecification, + Reports, + Tables, + UpdateGoalRequest, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "PowerbiClient", + "Alert", + "Columns", + "CreateGoalRequest", + "CreateGoalResponse", + "CreateScorecardRequest", + "CreatedScorecard", + "Datasets", + "DynamicPowerBiButtonClickedTriggerResult", + "EffectiveIdentity", + "EvaluatedAlert", + "ExecuteDatasetQueriesJsonInput", + "ExecuteDatasetQueriesJsonResponse", + "ExportFilter", + "ExportPayloadPaginatedReport", + "ExportPayloadPowerBIReport", + "ExportReportPage", + "ExportReportSettings", + "FetchedGoal", + "FetchedGoals", + "GetGoalCheckinResponse", + "GetGoalCheckinsResponse", + "GoalChanged", + "GoalNotes", + "GoalRefreshIssue", + "GoalRefreshIssues", + "GoalStatusChanged", + "GoalValueChanged", + "GoalValueCheckinNoteInput", + "GoalValueCheckinRequest", + "GoalValueCheckinUpdateRequest", + "GoalValueOrNoteUpserted", + "GoalsAssigned", + "Groups", + "IdentityBlob", + "ListedScorecard", + "ListedScorecards", + "PageBookmark", + "Payload", + "PowerBiButtonClickedOutputs", + "QueryExecutionResults", + "QuerySpecification", + "Reports", + "Tables", + "UpdateGoalRequest", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class PowerbiClient(ConnectorClientBase): + """Typed client for powerbi connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a PowerbiClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "powerbi" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_scorecards( + self, + groupid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get scorecards + + Gets a list of Power BI scorecards in the specified workspace. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetScorecards`. + + Args: + groupid: The unique identifier of the workspace. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myOrg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/internalScorecards" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_scorecard( + self, + input: CreateScorecardRequest | Mapping[str, Any], + groupid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a scorecard + + Creates a scorecard for Power BI goals. + + Swagger operation ID: `CreateScorecard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myOrg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/internalScorecards" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_multiple_goals( + self, + groupid: str, + scorecard_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get multiple goals + + Get a list of Power BI goals in the specified scorecard. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMultipleGoals`. + + Args: + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myOrg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/internalScorecards({quote(str(scorecard_id), safe='')})" + f"/goals" + ) + query_params = [] + query_params.append("$expand=" + quote("aggregations", safe='')) + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_goal( + self, + input: CreateGoalRequest | Mapping[str, Any], + groupid: str, + scorecard_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a goal + + Creates a Power BI goal on the specified scorecard. + + Swagger operation ID: `CreateGoal`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myOrg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/internalScorecards({quote(str(scorecard_id), safe='')})" + f"/goals" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_goal( + self, + groupid: str, + scorecard_id: str, + goal_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a goal + + Gets the specified Power BI goal on a scorecard. + + Swagger operation ID: `GetGoal`. + + Args: + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + goal_id: The unique identifier of the goal. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myOrg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/internalScorecards({quote(str(scorecard_id), safe='')})" + f"/goals({quote(str(goal_id), safe='')})" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + query_params.append("$expand=" + quote("aggregations", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_goal( + self, + input: UpdateGoalRequest | Mapping[str, Any], + groupid: str, + scorecard_id: str, + goal_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update a goal + + Updates the Power BI goal's state. + + Swagger operation ID: `UpdateGoal`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + goal_id: The unique identifier of the goal. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myOrg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/internalScorecards({quote(str(scorecard_id), safe='')})" + f"/goals({quote(str(goal_id), safe='')})" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + async def execute_dataset_query( + self, + input: QuerySpecification | Mapping[str, Any], + groupid: str, + datasetid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Run a query against a dataset + + Use the Power BI REST API to run a query. + + Swagger operation ID: `ExecuteDatasetQuery`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + datasetid: The unique identifier of the dataset. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myorg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/datasets" + f"/{quote(str(datasetid), safe='')}" + f"/executeQueries" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def execute_dataset_queries_json( + self, + input: ExecuteDatasetQueriesJsonInput | Mapping[str, Any], + groupid: str, + datasetid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Run a json query against a dataset + + Use the Power BI REST API to run a query in json format. + + Swagger operation ID: `ExecuteDatasetQueriesJson`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + datasetid: The unique identifier of the dataset. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/internalFlowActionOverloadAsJson" + f"/v1.0" + f"/myorg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/datasets" + f"/{quote(str(datasetid), safe='')}" + f"/executeQueries" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_rows( + self, + input: Payload | Mapping[str, Any], + groupid: str, + datasetid: str, + tablename: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add rows to a dataset + + Use Power BI REST API to add rows to a dataset. + + Swagger operation ID: `AddRows`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + datasetid: The unique identifier of the dataset. + tablename: The name of the table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myorg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/datasets" + f"/{quote(str(datasetid), safe='')}" + f"/tables" + f"/{quote(str(tablename), safe='')}" + f"/rows" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def goal_value_checkin_note( + self, + input: GoalValueCheckinNoteInput, + groupid: str, + scorecard_id: str, + goal_id: str, + goal_checkin: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add a note to a check-in + + Appends a new note to a check-in of a Power BI goal. + + Swagger operation ID: `GoalValueCheckinNote`. + + Args: + input: The request body. + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + goal_id: The unique identifier of the goal. + goal_checkin: Example: 2021-07-21. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myorg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/internalScorecards({quote(str(scorecard_id), safe='')})" + f"/goals({quote(str(goal_id), safe='')})" + f"/goalValues({quote(str(goal_checkin), safe='')})" + f"/notes" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def goal_value_checkin( + self, + input: GoalValueCheckinRequest | Mapping[str, Any], + groupid: str, + scorecard_id: str, + goal_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Create a check-in + + Creates a Power BI goal check-in. + + Swagger operation ID: `GoalValueCheckin`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + goal_id: The unique identifier of the goal. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myorg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/internalScorecards({quote(str(scorecard_id), safe='')})" + f"/goals({quote(str(goal_id), safe='')})" + f"/goalValues" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_goal_checkins( + self, + groupid: str, + scorecard_id: str, + goal_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get goal check-ins + + Get all check-ins on a Power BI goal. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetGoalCheckins`. + + Args: + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + goal_id: The unique identifier of the goal. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myorg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/internalScorecards({quote(str(scorecard_id), safe='')})" + f"/goals({quote(str(goal_id), safe='')})" + f"/goalValues" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + query_params.append("$expand=" + quote("notes", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_goal_checkin( + self, + input: GoalValueCheckinUpdateRequest | Mapping[str, Any], + groupid: str, + scorecard_id: str, + goal_id: str, + goal_checkin: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update a check-in + + Updates a Power BI goal check-in. + + Swagger operation ID: `UpdateGoalCheckin`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + goal_id: The unique identifier of the goal. + goal_checkin: Example: 2021-07-21. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myorg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/internalScorecards({quote(str(scorecard_id), safe='')})" + f"/goals({quote(str(goal_id), safe='')})" + f"/goalValues({quote(str(goal_checkin), safe='')})" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_goal_checkin( + self, + groupid: str, + scorecard_id: str, + goal_id: str, + goal_checkin: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a goal check-in + + Get a check-in on a Power BI goal. + + Swagger operation ID: `GetGoalCheckin`. + + Args: + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + goal_id: The unique identifier of the goal. + goal_checkin: Example: 2021-07-21. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myorg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/internalScorecards({quote(str(scorecard_id), safe='')})" + f"/goals({quote(str(goal_id), safe='')})" + f"/goalValues({quote(str(goal_checkin), safe='')})" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + query_params.append("$expand=" + quote("notes", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def refresh_dataset( + self, + groupid: str, + datasetid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Refresh a dataset + + Use Power BI REST API to refresh a powerbi dataset. + + Swagger operation ID: `RefreshDataset`. + + Args: + groupid: The unique identifier of the workspace. + datasetid: The unique identifier of the dataset. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myorg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/datasets" + f"/{quote(str(datasetid), safe='')}" + f"/refreshes" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def initiate_export_to_file_for_pbi_reports( + self, + input: ExportPayloadPowerBIReport | Mapping[str, Any], + groupid: str, + reportid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Export To File for Power BI Reports + + Use Power BI Rest API to inititate export for Power BI reports + + Swagger operation ID: `InitiateExportToFileForPbiReports`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + reportid: The unique identifier of a pbi report. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myorg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/reports" + f"/{quote(str(reportid), safe='')}" + f"/ExportTo" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def initiate_export_to_file_for_paginated_reports( + self, + input: ExportPayloadPaginatedReport | Mapping[str, Any], + groupid: str, + reportid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Export To File for Paginated Reports + + Use Power BI Rest API to inititate export for paginated reports + + Swagger operation ID: `InitiateExportToFileForPaginatedReports`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + reportid: The unique identifier of a paginated report. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myorg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/reports" + f"/{quote(str(reportid), safe='')}" + f"/ExportToPaginatedReports" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + def list_groups( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + ListGroups + + Get Groups for Power BI. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListGroups`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/myorg/groups" + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_alerts( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get alerts from Power BI + + Return a list of alerts for a signed in user. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAlerts`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/metadata/v201606/alerts" + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_datasets( + self, + groupid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + ListDatasets + + Get datasets for Power BI group. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListDatasets`. + + Args: + groupid: The unique identifier of the workspace. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/myorg/groups/{quote(str(groupid), safe='')}/datasets" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_tables( + self, + groupid: str, + datasetid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + ListTables + + Get tables for Power BI dataset. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTables`. + + Args: + groupid: The unique identifier of the workspace. + datasetid: The unique identifier of the dataset. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myorg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/datasets" + f"/{quote(str(datasetid), safe='')}" + f"/tables" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_reports_in_group( + self, + groupid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Reports in Group + + Returns a list of reports from the specified workspace. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetReportsInGroup`. + + Args: + groupid: The unique identifier of the workspace. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/myorg/groups/{quote(str(groupid), safe='')}/reports" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_columns( + self, + groupid: str, + datasetid: str, + tablename: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + GetColumns + + Get columns for Power BI dataset table. + + Swagger operation ID: `GetColumns`. + + Args: + groupid: The unique identifier of the workspace. + datasetid: The unique identifier of the dataset. + tablename: The name of the table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/myorg" + f"/groups" + f"/{quote(str(groupid), safe='')}" + f"/datasets" + f"/{quote(str(datasetid), safe='')}" + f"/tables" + f"/{quote(str(tablename), safe='')}" + f"/columns" + ) + query_params = [] + query_params.append("pbi_source=" + quote("powerAutomate", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/projectplace.py b/src/azure/connectors/aio/projectplace.py new file mode 100644 index 0000000..c8eddc5 --- /dev/null +++ b/src/azure/connectors/aio/projectplace.py @@ -0,0 +1,354 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# ProjectplaceClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.projectplace import ( + CreateCardInput, + CreateCardResponse, + MoveCardInput, + MoveCardResponse, + SetWebhookCardCreateInput, + SetWebhookCardDueDateInput, + SetWebhookPropertiesChangeInput, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "ProjectplaceClient", + "CreateCardInput", + "CreateCardResponse", + "MoveCardInput", + "MoveCardResponse", + "SetWebhookCardCreateInput", + "SetWebhookCardDueDateInput", + "SetWebhookPropertiesChangeInput", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class ProjectplaceClient(ConnectorClientBase): + """Typed client for projectplace connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a ProjectplaceClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "projectplace" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_card( + self, + input: CreateCardInput | Mapping[str, Any], + board_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Card + + Creates a new card with the parameters provided + + Swagger operation ID: `create_card`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + board_id: The id of the Board where the card should be created. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1" + f"/external_notifications" + f"/{quote(str(board_id), safe='')}" + f"/create_card" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def move_card( + self, + input: MoveCardInput | Mapping[str, Any], + board_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Move card to another column + + Move a card on the selected board + + Swagger operation ID: `move_card`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + board_id: The id of the Board where the card should be created. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1" + f"/external_notifications" + f"/{quote(str(board_id), safe='')}" + f"/move_card" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_boards( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Lists the boards the user have access to + + Lists the boards that are part of the projects the user have access to + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `list_boards`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1/external_notifications/lists/list_boards" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/replicon.py b/src/azure/connectors/aio/replicon.py new file mode 100644 index 0000000..3ab5772 --- /dev/null +++ b/src/azure/connectors/aio/replicon.py @@ -0,0 +1,912 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# RepliconClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping +from urllib.parse import quote +import json + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, +) + +from azure.connectors.replicon import ( + BulkGetProjectDetails3Input, + BulkGetTimeEnteredSummaryInput, + BulkGetTimeEnteredSummaryResponse, + CreateProjectOrApplyModificationsInput, + CreateProjectOrApplyModificationsResponse, + CreateTaskHierarchyOrApplyModificationsInput, + CreateTaskHierarchyOrApplyModificationsResponse, + Date, + Duration, + GetDescendantTaskDetailsInput, + GetDescendantTaskDetailsResponse, + GetTimesheetSummaryInput, + GetTimesheetSummaryResponse, + MoveTaskInput, + ProjectDetailsResponse, + PutProjectTeamMemberAssignmentsInput, + PutResourceAssignmentsInput, + TaskListServiceGetDataInput, + TaskListServiceGetDataResponse, + TenantEndpointDetails, + UserListServiceGetDataInput, + UserListServiceGetDataResponse, + WebhookSubscriptionResponse, + WebhookSubscriptionsRestAPIInput, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "RepliconClient", + "BulkGetProjectDetails3Input", + "BulkGetTimeEnteredSummaryInput", + "BulkGetTimeEnteredSummaryResponse", + "CreateProjectOrApplyModificationsInput", + "CreateProjectOrApplyModificationsResponse", + "CreateTaskHierarchyOrApplyModificationsInput", + "CreateTaskHierarchyOrApplyModificationsResponse", + "Date", + "Duration", + "GetDescendantTaskDetailsInput", + "GetDescendantTaskDetailsResponse", + "GetTimesheetSummaryInput", + "GetTimesheetSummaryResponse", + "MoveTaskInput", + "ProjectDetailsResponse", + "PutProjectTeamMemberAssignmentsInput", + "PutResourceAssignmentsInput", + "TaskListServiceGetDataInput", + "TaskListServiceGetDataResponse", + "TenantEndpointDetails", + "UserListServiceGetDataInput", + "UserListServiceGetDataResponse", + "WebhookSubscriptionResponse", + "WebhookSubscriptionsRestAPIInput", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class RepliconClient(ConnectorClientBase): + """Typed client for replicon connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a RepliconClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "replicon" + + async def bulk_get_project_details3( + self, + input: BulkGetProjectDetails3Input | Mapping[str, Any], + host_url: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Project Details + + Get the project details from Replicon + + Swagger operation ID: `BulkGetProjectDetails3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/services/ProjectService1.svc/BulkGetProjectDetails3" + ) + query_params = [] + value = str(host_url) + if isinstance(host_url, bool): + value = value.lower() + query_params.append(f"hostUrl={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_project_or_apply_modifications( + self, + input: CreateProjectOrApplyModificationsInput | Mapping[str, Any], + host_url: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Project Or Apply Modifications + + Create Project Or Apply Modifications in Replicon + + Swagger operation ID: `CreateProjectOrApplyModifications`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/services/ProjectService1.svc/CreateProjectOrApplyModifications" + ) + query_params = [] + value = str(host_url) + if isinstance(host_url, bool): + value = value.lower() + query_params.append(f"hostUrl={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def user_list_service_get_data( + self, + input: UserListServiceGetDataInput | Mapping[str, Any], + host_url: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get User List + + Get User List Data from Replicon + + Swagger operation ID: `UserListServiceGetData`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/services/UserListService1.svc/GetData" + ) + query_params = [] + value = str(host_url) + if isinstance(host_url, bool): + value = value.lower() + query_params.append(f"hostUrl={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_descendant_task_details( + self, + input: GetDescendantTaskDetailsInput | Mapping[str, Any], + host_url: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Descendant Task Details + + Get Hierarchial Task Details from Replicon + + Swagger operation ID: `GetDescendantTaskDetails`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/services/TaskService1.svc/GetDescendantTaskDetails" + ) + query_params = [] + value = str(host_url) + if isinstance(host_url, bool): + value = value.lower() + query_params.append(f"hostUrl={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_task_hierarchy_or_apply_modifications( + self, + input: CreateTaskHierarchyOrApplyModificationsInput | Mapping[str, Any], + host_url: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Task Hierarchy Or Apply Modifications + + Create Task Hierarchy Or Apply Modifications to a Replicon Task + + Swagger operation ID: `CreateTaskHierarchyOrApplyModifications`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/services" + f"/TaskService1.svc" + f"/CreateTaskHierarchyOrApplyModifications" + ) + query_params = [] + value = str(host_url) + if isinstance(host_url, bool): + value = value.lower() + query_params.append(f"hostUrl={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def move_task( + self, + input: MoveTaskInput | Mapping[str, Any], + host_url: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Move Task + + Move Task to a new Parent + + Swagger operation ID: `MoveTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/services/TaskService1.svc/MoveTask" + ) + query_params = [] + value = str(host_url) + if isinstance(host_url, bool): + value = value.lower() + query_params.append(f"hostUrl={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def task_list_service_get_data( + self, + input: TaskListServiceGetDataInput | Mapping[str, Any], + host_url: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Task List Service Get Data + + Get Task List Service Data From Replicon + + Swagger operation ID: `TaskListServiceGetData`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/services/TaskListService1.svc/GetData" + ) + query_params = [] + value = str(host_url) + if isinstance(host_url, bool): + value = value.lower() + query_params.append(f"hostUrl={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_timesheet_summary( + self, + input: GetTimesheetSummaryInput | Mapping[str, Any], + host_url: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Timesheet Summary + + Get Timesheet Summary from Replicon + + Swagger operation ID: `GetTimesheetSummary`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/services/TimesheetService1.svc/GetTimesheetSummary" + ) + query_params = [] + value = str(host_url) + if isinstance(host_url, bool): + value = value.lower() + query_params.append(f"hostUrl={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def bulk_get_time_entered_summary( + self, + input: BulkGetTimeEnteredSummaryInput | Mapping[str, Any], + host_url: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Time Entered Summary + + Get Time Entered by Task Uri from Replicon + + Swagger operation ID: `BulkGetTimeEnteredSummary`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/services/TaskService1.svc/BulkGetTimeEnteredSummary" + ) + query_params = [] + value = str(host_url) + if isinstance(host_url, bool): + value = value.lower() + query_params.append(f"hostUrl={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def put_project_team_member_assignments( + self, + input: PutProjectTeamMemberAssignmentsInput | Mapping[str, Any], + host_url: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Put Project Team Member Assignments + + Rewrite Team Member assignment of Project + + Swagger operation ID: `PutProjectTeamMemberAssignments`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/services/ProjectService1.svc/PutProjectTeamMemberAssignments" + ) + query_params = [] + value = str(host_url) + if isinstance(host_url, bool): + value = value.lower() + query_params.append(f"hostUrl={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def put_resource_assignments( + self, + input: PutResourceAssignmentsInput | Mapping[str, Any], + host_url: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Rewrite Resource Assignment of a task + + Update the Resource assignment to a specified task + + Swagger operation ID: `PutResourceAssignments`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/services/TaskService1.svc/PutResourceAssignments" + ) + query_params = [] + value = str(host_url) + if isinstance(host_url, bool): + value = value.lower() + query_params.append(f"hostUrl={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_my_tenant_endpoint_details( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Tenant End Point Details + + Get End Point Details of the Tenant + + Swagger operation ID: `GetMyTenantEndpointDetails`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/DiscoveryService1.svc/GetMyTenantEndpointDetails" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/revai.py b/src/azure/connectors/aio/revai.py new file mode 100644 index 0000000..fc74275 --- /dev/null +++ b/src/azure/connectors/aio/revai.py @@ -0,0 +1,2228 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# RevaiClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.revai import ( + AccountGetResponse, + AlignmentGetResponse, + AlignmentInput, + AlignmentPostResponse, + AlignmentTranscriptGetResponse, + AnalysisGetResponse, + AnalysisInput, + AnalysisPostResponse, + AnalysisResultGetResponse, + ExtractionGetResponse, + ExtractionInput, + ExtractionPostResponse, + ExtractionResultGetResponse, + IdentificationGetResponse, + IdentificationInput, + IdentificationPostResponse, + IdentificationResultGetResponse, + TranscriptGetResponse, + TranscriptionGetResponse, + TranscriptionInput, + TranscriptionPostResponse, + VocabularyGetResponse, + VocabularyInput, + VocabularyPostResponse, +) + +__all__ = [ + "RevaiClient", + "AccountGetResponse", + "AlignmentGetResponse", + "AlignmentInput", + "AlignmentPostResponse", + "AlignmentTranscriptGetResponse", + "AnalysisGetResponse", + "AnalysisInput", + "AnalysisPostResponse", + "AnalysisResultGetResponse", + "ExtractionGetResponse", + "ExtractionInput", + "ExtractionPostResponse", + "ExtractionResultGetResponse", + "IdentificationGetResponse", + "IdentificationInput", + "IdentificationPostResponse", + "IdentificationResultGetResponse", + "TranscriptGetResponse", + "TranscriptionGetResponse", + "TranscriptionInput", + "TranscriptionPostResponse", + "VocabularyGetResponse", + "VocabularyInput", + "VocabularyPostResponse", +] + + +# Type Definitions + +# Client Class + +class RevaiClient(ConnectorClientBase): + """Typed client for revai connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a RevaiClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "revai" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def transcription_get( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get transcription job + + Returns information about a transcription job. + + Swagger operation ID: `TranscriptionGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/speechtotext/v1/jobs/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def transcription_delete( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete transcription job + + Deletes a transcription job. All data related to the job, such as input + media and transcript, will be permanently deleted. A job can only be + deleted once it's completed (either with success or failure). + + Swagger operation ID: `TranscriptionDelete`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/speechtotext/v1/jobs/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_transcriptions_get( + self, + *, + limit: Optional[int] = None, + starting_after: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get transcription job list + + Retrieve a list of transcription jobs submitted within the last 30 + days. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `TranscriptionsGet`. + + Args: + limit: The limit. + starting_after: The starting after. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/speechtotext/v1/jobs" + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if starting_after is not None: + value = str(starting_after) + if isinstance(starting_after, bool): + value = value.lower() + query_params.append(f"starting_after={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def transcription( + self, + input: TranscriptionInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Submit transcription job + + Starts an asynchronous job to transcribe speech-to-text for a media + file. + + Swagger operation ID: `TranscriptionPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/speechtotext/v1/jobs" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_transcript_get( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get transcript + + Returns the transcript for a completed transcription job. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `TranscriptGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/speechtotext/v1/jobs/{quote(str(id), safe='')}/transcript" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("monologues", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def captions_get( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get captions + + Returns the caption output for a transcription job. We currently + support the SubRip (SRT) format. + + Swagger operation ID: `CaptionsGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/speechtotext/v1/jobs/{quote(str(id), safe='')}/captions" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def account_get( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get account + + Get the developer's account information. + + Swagger operation ID: `AccountGet`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/speechtotext/v1/account" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_vocabularies_get( + self, + *, + limit: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get list of vocabularies + + Retrieves a list of most recent custom vocabularies' processing + information. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `VocabulariesGet`. + + Args: + limit: The limit. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/speechtotext/v1/vocabularies" + ) + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def vocabulary( + self, + input: VocabularyInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Submit custom vocabulary + + Submits a Custom Vocabulary for asynchronous processing. + + Swagger operation ID: `VocabularyPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/speechtotext/v1/vocabularies" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def vocabulary_get( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get vocabulary + + Retrieve a custom vocabulary processing information. + + Swagger operation ID: `VocabularyGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/speechtotext/v1/vocabularies/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def vocabulary_delete( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete vocabulary + + Deletes a custom vocabulary. All data related to the custom vocabulary, + such as webhooks and metadata, will be permanently deleted. + + Swagger operation ID: `VocabularyDelete`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/speechtotext/v1/vocabularies/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_extractions_get( + self, + *, + limit: Optional[int] = None, + starting_after: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get topic extraction jobs + + Retrieves a list of topic extraction jobs submitted within the last 30 + days in reverse chronological order. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ExtractionsGet`. + + Args: + limit: The limit. + starting_after: The starting after. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/topic_extraction/v1/jobs" + ) + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if starting_after is not None: + value = str(starting_after) + if isinstance(starting_after, bool): + value = value.lower() + query_params.append(f"starting_after={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def extraction( + self, + input: ExtractionInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Submit topic extraction job + + Starts an asynchronous job to extract topics from a transcript. + + Swagger operation ID: `ExtractionPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/topic_extraction/v1/jobs" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def extraction_get( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get topic extraction job + + Returns information about a topic extraction job. + + Swagger operation ID: `ExtractionGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/topic_extraction/v1/jobs/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def extraction_delete( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete topic extraction jo + + Deletes a topic extraction job. All data related to the job will be + permanently deleted. + + Swagger operation ID: `ExtractionDelete`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/topic_extraction/v1/jobs/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_extraction_result_get( + self, + id: str, + *, + threshold: Optional[float] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get topic extraction result + + Returns the results for a completed topic extraction job. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ExtractionResultGet`. + + Args: + id: The identifier. + threshold: The threshold. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/topic_extraction/v1/jobs/{quote(str(id), safe='')}/result" + ) + query_params = [] + if threshold is not None: + value = str(threshold) + if isinstance(threshold, bool): + value = value.lower() + query_params.append(f"threshold={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("topics", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def analysises_get( + self, + *, + limit: Optional[int] = None, + starting_after: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get sentiment analysis jobs + + Gets a list of sentiment analysis jobs submitted within the last 30 + days in reverse chronological order. + + Swagger operation ID: `AnalysisesGet`. + + Args: + limit: The limit. + starting_after: The starting after. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/sentiment_analysis/v1/jobs" + ) + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if starting_after is not None: + value = str(starting_after) + if isinstance(starting_after, bool): + value = value.lower() + query_params.append(f"starting_after={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + async def analysis( + self, + input: AnalysisInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Submit sentiment analysis job + + Starts an asynchronous job to analyze sentiments in a transcript. + + Swagger operation ID: `AnalysisPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/sentiment_analysis/v1/jobs" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def analysis_get( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get sentiment analysis job + + Returns information about a sentiment analysis job. + + Swagger operation ID: `AnalysisGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/sentiment_analysis/v1/jobs/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def analysis_delete( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete sentiment analysis job + + Deletes a sentiment analysis job. All data related to the job will be + permanently deleted. + + Swagger operation ID: `AnalysisDelete`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/sentiment_analysis/v1/jobs/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_analysis_result_get( + self, + id: str, + *, + filter_for: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get sentiment analysis result + + Returns the results for a completed sentiment analysis job. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `AnalysisResultGet`. + + Args: + id: The identifier. + filter_for: The filter for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/sentiment_analysis/v1/jobs/{quote(str(id), safe='')}/result" + ) + query_params = [] + if filter_for is not None: + value = str(filter_for) + if isinstance(filter_for, bool): + value = value.lower() + query_params.append(f"filter_for={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("messages", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_identifications_get( + self, + *, + limit: Optional[int] = None, + starting_after: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get language identification jobs + + Retrieves a list of language identification jobs submitted within the + last 30 days in reverse chronological order. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `IdentificationsGet`. + + Args: + limit: The limit. + starting_after: The starting after. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/languageid/v1/jobs" + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if starting_after is not None: + value = str(starting_after) + if isinstance(starting_after, bool): + value = value.lower() + query_params.append(f"starting_after={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def identification( + self, + input: IdentificationInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Submit language identification job + + Starts an asynchronous job to identify the most probable language in + the audio. + + Swagger operation ID: `IdentificationPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/languageid/v1/jobs" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def identification_get( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get language identification job + + Returns information about a language identification job. + + Swagger operation ID: `IdentificationGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/languageid/v1/jobs/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def identification_delete( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete language identification job + + Deletes a language identification job. All data related to the job will + be permanently deleted. + + Swagger operation ID: `IdentificationDelete`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/languageid/v1/jobs/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def identification_result_get( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get language identification result + + Returns the results for a completed language identification job. + + Swagger operation ID: `IdentificationResultGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/languageid/v1/jobs/{quote(str(id), safe='')}/result" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_alignments_get( + self, + *, + limit: Optional[int] = None, + starting_after: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get forced alignment jobs + + Retrieve a list of alignment jobs submitted within the last 30 days in + reverse chronological order. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `AlignmentsGet`. + + Args: + limit: The limit. + starting_after: The starting after. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/alignment/v1/jobs" + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if starting_after is not None: + value = str(starting_after) + if isinstance(starting_after, bool): + value = value.lower() + query_params.append(f"starting_after={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def alignment( + self, + input: AlignmentInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Submit forced alignment job + + Starts an asynchronous job to obtain precise word timings for an audio + file and text transcript. + + Swagger operation ID: `AlignmentPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/alignment/v1/jobs" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def alignment_get( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get forced alignment job + + Returns information about a forced alignment job. + + Swagger operation ID: `AlignmentGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/alignment/v1/jobs/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def alignment_delete( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete forced alignment job + + Deletes a forced alignment job. All data related to the job will be + permanently deleted. + + Swagger operation ID: `AlignmentDelete`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/alignment/v1/jobs/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_alignment_transcript_get( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get forced alignment transcript + + Returns the results for a completed forced alignment job. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `AlignmentTranscriptGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/alignment/v1/jobs/{quote(str(id), safe='')}/transcript" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("monologues", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/rss.py b/src/azure/connectors/aio/rss.py new file mode 100644 index 0000000..c8214ad --- /dev/null +++ b/src/azure/connectors/aio/rss.py @@ -0,0 +1,242 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# RssClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.rss import ( + FeedItem, + TriggerBatchResponseFeedItem, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "RssClient", + "FeedItem", + "TriggerBatchResponseFeedItem", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class RssClient(ConnectorClientBase): + """Typed client for rss connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a RssClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "rss" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_feed_items( + self, + feed_url: str, + *, + since: Optional[str] = None, + since_property: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all RSS feed items + + This operation retrieves all items from an RSS feed. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListFeedItems`. + + Args: + feed_url: The RSS feed URL (Example: + http://rss.cnn.com/rss/cnn_topstories.rss). + since: The date since when RSS feed should be retrieved (Example: + 2018-12-29 10:24:05Z). + since_property: Chosen property will be used for trigger state. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/ListFeedItems" + query_params = [] + value = str(feed_url) + if isinstance(feed_url, bool): + value = value.lower() + query_params.append(f"feedUrl={quote(value, safe='')}") + if since is not None: + value = str(since) + if isinstance(since, bool): + value = value.lower() + query_params.append(f"since={quote(value, safe='')}") + if since_property is not None: + value = str(since_property) + if isinstance(since_property, bool): + value = value.lower() + query_params.append(f"sinceProperty={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/salesforce.py b/src/azure/connectors/aio/salesforce.py new file mode 100644 index 0000000..a80c94d --- /dev/null +++ b/src/azure/connectors/aio/salesforce.py @@ -0,0 +1,2601 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# SalesforceClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.salesforce import ( + BlobDataSetsMetadata, + CheckJobResponse, + CloseJobRequest, + CreateJobParameters, + CreateJobRequest, + CreateJobResponse, + DataSet, + DataSetsList, + DataSetsMetadata, + ExecuteSoqlQueryParameters, + ExternalIdField, + ExternalIdFieldsList, + GetAllJobsResponse, + GetCurrentUserInfoResponse, + GetItemByExternalIdResponse, + GetItemResponse, + InstanceUrlResponse, + Item, + ItemsList, + JobInfo, + MCPQueryRequest, + MCPQueryResponse, + ObjectEntity, + ObjectWithoutType, + PassThroughNativeQuery, + PatchItemByExternalIdInput, + PatchItemByExternalIdResponse, + PatchItemInput, + PatchItemResponse, + PostItemInput, + PostItemResponse, + Procedure, + SOSLSearchQueryResponse, + SearchRecordObject, + Table, + TableCapabilitiesMetadata, + TableFilterRestrictionsMetadata, + TableMetadata, + TableSelectRestrictionsMetadata, + TableSortRestrictionsMetadata, + TablesList, + TabularDataSetsMetadata, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "SalesforceClient", + "BlobDataSetsMetadata", + "CheckJobResponse", + "CloseJobRequest", + "CreateJobParameters", + "CreateJobRequest", + "CreateJobResponse", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "ExecuteSoqlQueryParameters", + "ExternalIdField", + "ExternalIdFieldsList", + "GetAllJobsResponse", + "GetCurrentUserInfoResponse", + "GetItemByExternalIdResponse", + "GetItemResponse", + "InstanceUrlResponse", + "Item", + "ItemsList", + "JobInfo", + "MCPQueryRequest", + "MCPQueryResponse", + "ObjectEntity", + "ObjectWithoutType", + "PassThroughNativeQuery", + "PatchItemByExternalIdInput", + "PatchItemByExternalIdResponse", + "PatchItemInput", + "PatchItemResponse", + "PostItemInput", + "PostItemResponse", + "Procedure", + "SOSLSearchQueryResponse", + "SearchRecordObject", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TablesList", + "TabularDataSetsMetadata", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class SalesforceClient(ConnectorClientBase): + """Typed client for salesforce connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a SalesforceClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "salesforce" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_tables( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get object types + + This operation lists the available Salesforce object types. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTables`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/datasets/default/tables" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_item_by_external_id( + self, + table: str, + external_id_field: str, + external_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a Record by External ID + + This operation retrieves a record using an external ID. + + Swagger operation ID: `GetItemByExternalId`. + + Args: + table: The Salesforce object type like 'Leads'. + external_id_field: Field marked as external ID field on Salesforce + object. + external_id: External ID of the record to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/externalIdFields" + f"/{quote(quote(str(external_id_field), safe=''), safe='')}" + f"/{quote(quote(str(external_id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_items( + self, + table: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get records + + This operation gets records of a certain Salesforce object type like + 'Leads'. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItems`. + + Args: + table: The Salesforce object type like 'Leads'. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_items_table_account( + self, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Account records from Salesforce + + This operation gets Account records from Salesforce. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItems_table_account`. + + Args: + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/tables/account/items" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_items_table_user( + self, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get User records from Salesforce + + This operation gets User records from Salesforce. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItems_table_user`. + + Args: + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/tables/user/items" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_items_table_case( + self, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Case records from Salesforce + + This operation gets Case records from Salesforce. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItems_table_case`. + + Args: + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/tables/case/items" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_items_table_opportunity( + self, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Opportunity records from Salesforce + + This operation gets Opportunity records from Salesforce. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItems_table_opportunity`. + + Args: + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/tables/opportunity/items" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_items_table_product2( + self, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Product records from Salesforce + + This operation gets Product records from Salesforce. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItems_table_product2`. + + Args: + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/tables/product2/items" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_items_table_contact( + self, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Contact records from Salesforce + + This operation gets Contact records from Salesforce. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItems_table_contact`. + + Args: + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/default/tables/contact/items" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def delete_item( + self, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete record + + This operation deletes a record. + + Swagger operation ID: `DeleteItem`. + + Args: + table: The Salesforce object type like 'Leads'. + id: The unique identifier of record to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def execute_soql_query( + self, + input: ExecuteSoqlQueryParameters | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Execute a SOQL query + + Execute a SOQL query. + + Swagger operation ID: `ExecuteSoqlQuery`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/soql/executesoqlquery" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_all_jobs( + self, + *, + concurreny_mode: Optional[str] = None, + is_pk_chunking_enabled: Optional[bool] = None, + job_type: Optional[str] = None, + query_locator: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get all jobs + + Get a list of all jobs + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAllJobs`. + + Args: + concurreny_mode: Concurrency Mode. + is_pk_chunking_enabled: Is PK Chunking Enabled. + job_type: Job Type. + query_locator: Query Locator. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/codeless/jobs/ingest" + query_params = [] + if concurreny_mode is not None: + value = str(concurreny_mode) + if isinstance(concurreny_mode, bool): + value = value.lower() + query_params.append(f"concurrenyMode={quote(value, safe='')}") + if is_pk_chunking_enabled is not None: + value = str(is_pk_chunking_enabled) + if isinstance(is_pk_chunking_enabled, bool): + value = value.lower() + query_params.append(f"isPkChunkingEnabled={quote(value, safe='')}") + if job_type is not None: + value = str(job_type) + if isinstance(job_type, bool): + value = value.lower() + query_params.append(f"jobType={quote(value, safe='')}") + if query_locator is not None: + value = str(query_locator) + if isinstance(query_locator, bool): + value = value.lower() + query_params.append(f"queryLocator={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("records", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def upload_job_data( + self, + input: bytes, + job_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Upload job data + + Uploads data for a job using CSV data. + + Swagger operation ID: `UploadJobData`. + + Args: + input: The binary request body. + job_id: Job ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless/jobs/ingest/{quote(str(job_id), safe='')}/batches" + ) + + response = await self.http_client.send( + "PUT", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_job_info( + self, + job_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get job info + + Retrieves detailed information about a job. + + Swagger operation ID: `GetJobInfo`. + + Args: + job_id: Job ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless/jobs/ingest/{quote(str(job_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def close_job( + self, + input: CloseJobRequest | Mapping[str, Any], + job_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Close or abort a job + + Closes or aborts a job. Use UploadComplete to close a job, or Aborted + to abort a job. If you close a job, Salesforce queues the job and + uploaded data for processing, and you can't add any additional job + data. If you abort a job, the job does not get queued or processed. + + Swagger operation ID: `CloseJob`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + job_id: Job ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless/jobs/ingest/{quote(str(job_id), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_job( + self, + job_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a job + + Deletes a job. To be deleted, a job must have a state of + UploadComplete, JobComplete, Aborted, or Failed. + + Swagger operation ID: `DeleteJob`. + + Args: + job_id: Job ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless/jobs/ingest/{quote(str(job_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_job_record_results( + self, + job_id: str, + result_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get job results + + Retrieves a list of records based on the result type for a completed + job. + + Swagger operation ID: `GetJobRecordResults`. + + Args: + job_id: Job ID. + result_type: Result Type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/codeless/jobs/ingest/{quote(str(job_id), safe='')}/results" + ) + query_params = [] + value = str(result_type) + if isinstance(result_type, bool): + value = value.lower() + query_params.append(f"resultType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def execute_sosl_query( + self, + q: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Execute SOSL search query + + Execute the specified SOSL search qyery + + Swagger operation ID: `ExecuteSOSLQuery`. + + Args: + q: SOSL search string. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/codeless/search" + query_params = [] + value = str(q) + if isinstance(q, bool): + value = value.lower() + query_params.append(f"q={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def http_request( + self, + input: bytes, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send an HTTP request + + Construct a Salesforce REST API request to invoke + + Swagger operation ID: `HttpRequest`. + + Args: + input: The binary request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/codeless/httprequest" + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def mcp_salesforce_management( + self, + input: MCPQueryRequest | Mapping[str, Any], + *, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + MCP server for Salesforce + + MCP server for Salesforce + + Swagger operation ID: `mcp_SalesforceManagement`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + session_id: sessionId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/mcp/SalesforceManagement" + ) + query_params = [] + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_job( + self, + input: CreateJobParameters | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a job + + Creates a job, which represents a bulk operation (and associated data) + that is sent to Salesforce for asynchronous processing. Provide job + data via an Upload Job Data request. + + Swagger operation ID: `CreateJobV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/bulk/createjob" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_item( + self, + table: str, + id: str, + *, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get record + + This operation gets a record. + + Swagger operation ID: `GetItem_V2`. + + Args: + table: table name. + id: item key. + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + query_params = [] + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def patch_item( + self, + input: PatchItemInput | Mapping[str, Any], + table: str, + id: str, + *, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update record + + This operation updates a record and allows null values. + + Swagger operation ID: `PatchItem_V3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: table name. + id: item key. + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v3" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + query_params = [] + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def patch_item_by_external_id( + self, + input: PatchItemByExternalIdInput | Mapping[str, Any], + table: str, + external_id_field: str, + external_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Insert or Update (Upsert) a Record by External ID + + This operation inserts or updates (upserts) a record using an external + ID. + + Swagger operation ID: `PatchItemByExternalIdV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: The Salesforce object type like 'Leads'. + external_id_field: Field marked as external ID field on Salesforce + object. + external_id: External ID of the record to upsert. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/externalIdFields" + f"/{quote(quote(str(external_id_field), safe=''), safe='')}" + f"/{quote(quote(str(external_id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def post_item( + self, + input: PostItemInput | Mapping[str, Any], + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create record + + This operation creates a record and allows null values. + + Swagger operation ID: `PostItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: table name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_external_id_fields( + self, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get External ID Fields + + This operation retrieves external ID fields of Salesforce object type. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetExternalIdFields`. + + Args: + table: The Salesforce object type like 'Leads'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/externalIdFields" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_metadata_for_get_item( + self, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + GetMetadataForGetItem + + Swagger operation ID: `GetMetadataForGetItem`. + + Args: + table: table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/$metadata.json" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/getitem" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_metadata_for_patch_item( + self, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + GetMetadataForPatchItem + + Swagger operation ID: `GetMetadataForPatchItem`. + + Args: + table: table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/$metadata.json" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/patchitem" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_metadata_for_post_item( + self, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + GetMetadataForPostItem + + Swagger operation ID: `GetMetadataForPostItem`. + + Args: + table: table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/$metadata.json" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/postitem" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_table( + self, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get object metadata + + This operation gets the object metadata for a Salesforce object type. + + Swagger operation ID: `GetTable`. + + Args: + table: Salesforce object type like 'Leads'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/$metadata.json" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/seismicplanner.py b/src/azure/connectors/aio/seismicplanner.py new file mode 100644 index 0000000..f3fdb58 --- /dev/null +++ b/src/azure/connectors/aio/seismicplanner.py @@ -0,0 +1,2757 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# SeismicplannerClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.seismicplanner import ( + Association, + AssociationReq, + AsyncOperationResponse, + Comment, + CommentQueryResponse, + ContentRef, + CreateCommentModel, + CreateProject, + CreateRequest, + CreateTask, + CustomProperty, + CustomPropertyDataDisplay, + CustomPropertyValues, + CustomPropertyValuesInput, + CustomPropertyValuesValues, + DeleteRequest, + Follower, + Meta, + MetaQueryInfo, + PlannerProject, + PlannerProjectQueryResponse, + PlannerRequest, + PlannerRequestQueryResponse, + PlannerSubTask, + PlannerTask, + PlannerTaskQueryResponse, + PossibleValuesItem, + ProblemDetails, + ProjectAssociatedNodes, + RequestFormCustomProperties, + ScopeSettingsItemDefinition, + StatusSchema, + StatusSchemaQueryResponse, + UpdateCommentModel, + UpdateProject, + UpdateRequest, + UpdateTask, + ValueSchemaPropertyDefinition, +) + +__all__ = [ + "SeismicplannerClient", + "Association", + "AssociationReq", + "AsyncOperationResponse", + "Comment", + "CommentQueryResponse", + "ContentRef", + "CreateCommentModel", + "CreateProject", + "CreateRequest", + "CreateTask", + "CustomProperty", + "CustomPropertyDataDisplay", + "CustomPropertyValues", + "CustomPropertyValuesInput", + "CustomPropertyValuesValues", + "DeleteRequest", + "Follower", + "Meta", + "MetaQueryInfo", + "PlannerProject", + "PlannerProjectQueryResponse", + "PlannerRequest", + "PlannerRequestQueryResponse", + "PlannerSubTask", + "PlannerTask", + "PlannerTaskQueryResponse", + "PossibleValuesItem", + "ProblemDetails", + "ProjectAssociatedNodes", + "RequestFormCustomProperties", + "ScopeSettingsItemDefinition", + "StatusSchema", + "StatusSchemaQueryResponse", + "UpdateCommentModel", + "UpdateProject", + "UpdateRequest", + "UpdateTask", + "ValueSchemaPropertyDefinition", +] + + +# Type Definitions + +# Client Class + +class SeismicplannerClient(ConnectorClientBase): + """Typed client for seismicplanner connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a SeismicplannerClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "seismicplanner" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_comments( + self, + space_id: str, + node_id: str, + *, + creator_ids: Optional[List[str]] = None, + cursor: Optional[str] = None, + limit: Optional[int] = None, + sort: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get comments + + Get all comments for a given project, task, or request. Requires node + (project, task, or request) ID. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetComments`. + + Args: + space_id: Space ID. + node_id: Node ID. + creator_ids: List of user IDs to query by creator. + cursor: Cursor used for pagination. + limit: Number to limit records. + sort: Sort by query. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/nodes" + f"/{quote(str(node_id), safe='')}" + f"/comments" + ) + query_params = [] + item: object + if creator_ids is not None: + if isinstance(creator_ids, list): + joined_parts = [] + for item in creator_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"creatorIds={quote(joined, safe='')}") + else: + value = str(creator_ids) + if isinstance(creator_ids, bool): + value = value.lower() + query_params.append(f"creatorIds={quote(value, safe='')}") + if cursor is not None: + value = str(cursor) + if isinstance(cursor, bool): + value = value.lower() + query_params.append(f"cursor={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if sort is not None: + if isinstance(sort, list): + joined_parts = [] + for item in sort: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"sort={quote(joined, safe='')}") + else: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_comment( + self, + input: CreateCommentModel | Mapping[str, Any], + space_id: str, + node_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create comment + + Create a comment on a given project, task, or request. Requires node + (project, task, or request) ID. + + Swagger operation ID: `CreateComment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + node_id: Node ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/nodes" + f"/{quote(str(node_id), safe='')}" + f"/comments" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_comment( + self, + space_id: str, + node_id: str, + comment_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get comment + + Get a single comment. Requires node (project, task, or request) and + comment ID. + + Swagger operation ID: `GetComment`. + + Args: + space_id: Space ID. + node_id: Node ID. + comment_id: Comment ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/nodes" + f"/{quote(str(node_id), safe='')}" + f"/comments" + f"/{quote(str(comment_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_comment( + self, + space_id: str, + node_id: str, + comment_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete comment + + Delete a comment. Requires node (project, task, or request) and comment + ID. + + Swagger operation ID: `DeleteComment`. + + Args: + space_id: Space ID. + node_id: Node ID. + comment_id: Comment ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/nodes" + f"/{quote(str(node_id), safe='')}" + f"/comments" + f"/{quote(str(comment_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def update_comment( + self, + input: UpdateCommentModel | Mapping[str, Any], + space_id: str, + node_id: str, + comment_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update comment + + Update an existing comment. Requires node (project, task, or request) + and comment ID. + + Swagger operation ID: `UpdateComment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + node_id: Node ID. + comment_id: Comment ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/nodes" + f"/{quote(str(node_id), safe='')}" + f"/comments" + f"/{quote(str(comment_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_projects( + self, + space_id: str, + *, + planned_end_date_from: Optional[str] = None, + planned_end_date_to: Optional[str] = None, + planned_start_date_from: Optional[str] = None, + planned_start_date_to: Optional[str] = None, + ids: Optional[List[str]] = None, + title: Optional[str] = None, + manager_ids: Optional[List[str]] = None, + creator_ids: Optional[List[str]] = None, + associated_node_ids: Optional[List[str]] = None, + cursor: Optional[str] = None, + limit: Optional[int] = None, + sort: Optional[List[str]] = None, + custom_properties: Optional[str] = None, + follower_ids: Optional[List[str]] = None, + include_associations: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get projects + + Get a list of projects with their attributes and associations. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetProjects`. + + Args: + space_id: Space ID. + planned_end_date_from: Filter from a planned end date. + planned_end_date_to: Filter to a planned end date. + planned_start_date_from: Filter from a planned start date. + planned_start_date_to: Filter to a planned start date. + ids: List of project IDs to query by. + title: Project title to query by. + manager_ids: List of user IDs to query by manager. + creator_ids: List of user IDs to query by creator. + associated_node_ids: List of association IDs to query by. + cursor: Cursor used for pagination. + limit: Number to limit records returned. + sort: Sort query. + custom_properties: List of custom properties to query by. + follower_ids: List of user IDs to query by follower. + include_associations: Indicator to allow for inclusion of + association data. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner/v2/spaces/{quote(str(space_id), safe='')}/projects" + ) + query_params = [] + item: object + if planned_end_date_from is not None: + value = str(planned_end_date_from) + if isinstance(planned_end_date_from, bool): + value = value.lower() + query_params.append(f"plannedEndDateFrom={quote(value, safe='')}") + if planned_end_date_to is not None: + value = str(planned_end_date_to) + if isinstance(planned_end_date_to, bool): + value = value.lower() + query_params.append(f"plannedEndDateTo={quote(value, safe='')}") + if planned_start_date_from is not None: + value = str(planned_start_date_from) + if isinstance(planned_start_date_from, bool): + value = value.lower() + query_params.append(f"plannedStartDateFrom={quote(value, safe='')}") + if planned_start_date_to is not None: + value = str(planned_start_date_to) + if isinstance(planned_start_date_to, bool): + value = value.lower() + query_params.append(f"plannedStartDateTo={quote(value, safe='')}") + if ids is not None: + if isinstance(ids, list): + joined_parts = [] + for item in ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"ids={quote(joined, safe='')}") + else: + value = str(ids) + if isinstance(ids, bool): + value = value.lower() + query_params.append(f"ids={quote(value, safe='')}") + if title is not None: + value = str(title) + if isinstance(title, bool): + value = value.lower() + query_params.append(f"title={quote(value, safe='')}") + if manager_ids is not None: + if isinstance(manager_ids, list): + joined_parts = [] + for item in manager_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"managerIds={quote(joined, safe='')}") + else: + value = str(manager_ids) + if isinstance(manager_ids, bool): + value = value.lower() + query_params.append(f"managerIds={quote(value, safe='')}") + if creator_ids is not None: + if isinstance(creator_ids, list): + joined_parts = [] + for item in creator_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"creatorIds={quote(joined, safe='')}") + else: + value = str(creator_ids) + if isinstance(creator_ids, bool): + value = value.lower() + query_params.append(f"creatorIds={quote(value, safe='')}") + if associated_node_ids is not None: + if isinstance(associated_node_ids, list): + joined_parts = [] + for item in associated_node_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"associatedNodeIds={quote(joined, safe='')}") + else: + value = str(associated_node_ids) + if isinstance(associated_node_ids, bool): + value = value.lower() + query_params.append(f"associatedNodeIds={quote(value, safe='')}") + if cursor is not None: + value = str(cursor) + if isinstance(cursor, bool): + value = value.lower() + query_params.append(f"cursor={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if sort is not None: + if isinstance(sort, list): + joined_parts = [] + for item in sort: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"sort={quote(joined, safe='')}") + else: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if custom_properties is not None: + value = str(custom_properties) + if isinstance(custom_properties, bool): + value = value.lower() + query_params.append(f"customProperties={quote(value, safe='')}") + if follower_ids is not None: + if isinstance(follower_ids, list): + joined_parts = [] + for item in follower_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"followerIds={quote(joined, safe='')}") + else: + value = str(follower_ids) + if isinstance(follower_ids, bool): + value = value.lower() + query_params.append(f"followerIds={quote(value, safe='')}") + if include_associations is not None: + value = str(include_associations) + if isinstance(include_associations, bool): + value = value.lower() + query_params.append(f"includeAssociations={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def delete_projects( + self, + space_id: str, + ids: List[str], + *, + delete_tasks: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete projects + + Delete one or more projects. + + Swagger operation ID: `DeleteProjects`. + + Args: + space_id: Space ID. + ids: List of project IDs. + delete_tasks: Also delete associated tasks. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner/v2/spaces/{quote(str(space_id), safe='')}/projects" + ) + query_params = [] + item: object + if isinstance(ids, list): + joined_parts = [] + for item in ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"ids={quote(joined, safe='')}") + else: + value = str(ids) + if isinstance(ids, bool): + value = value.lower() + query_params.append(f"ids={quote(value, safe='')}") + if delete_tasks is not None: + value = str(delete_tasks) + if isinstance(delete_tasks, bool): + value = value.lower() + query_params.append(f"deleteTasks={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_project( + self, + input: CreateProject | Mapping[str, Any], + space_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create project + + Create a project. + + Swagger operation ID: `CreateProject`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner/v2/spaces/{quote(str(space_id), safe='')}/projects" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_project( + self, + space_id: str, + project_id: str, + *, + associated_nodes_depth: Optional[int] = None, + include_works: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get project + + Get a single project by ID. Return tasks if desired. + + Swagger operation ID: `GetProject`. + + Args: + space_id: Space ID. + project_id: Project ID. + associated_nodes_depth: Number to indicate depth of associated node + data returned. + include_works: Indicator to include associated tasks data. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/projects" + f"/{quote(str(project_id), safe='')}" + ) + query_params = [] + if associated_nodes_depth is not None: + value = str(associated_nodes_depth) + if isinstance(associated_nodes_depth, bool): + value = value.lower() + query_params.append(f"associatedNodesDepth={quote(value, safe='')}") + if include_works is not None: + value = str(include_works) + if isinstance(include_works, bool): + value = value.lower() + query_params.append(f"includeWorks={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_project( + self, + space_id: str, + project_id: str, + *, + delete_tasks: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete project + + Delete a project. + + Swagger operation ID: `DeleteProject`. + + Args: + space_id: Space ID. + project_id: Project ID. + delete_tasks: Also delete associated tasks. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/projects" + f"/{quote(str(project_id), safe='')}" + ) + query_params = [] + if delete_tasks is not None: + value = str(delete_tasks) + if isinstance(delete_tasks, bool): + value = value.lower() + query_params.append(f"deleteTasks={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_project( + self, + input: UpdateProject | Mapping[str, Any], + space_id: str, + project_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a project + + Update and return a project. + + Swagger operation ID: `UpdateProject`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + project_id: Project ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/projects" + f"/{quote(str(project_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_requests( + self, + space_id: str, + *, + planned_end_date_from: Optional[str] = None, + planned_end_date_to: Optional[str] = None, + planned_start_date_from: Optional[str] = None, + planned_start_date_to: Optional[str] = None, + created_at_from: Optional[str] = None, + created_at_to: Optional[str] = None, + updated_at_from: Optional[str] = None, + updated_at_to: Optional[str] = None, + ids: Optional[List[str]] = None, + title: Optional[str] = None, + assignee_ids: Optional[List[str]] = None, + priorities: Optional[List[str]] = None, + keywords: Optional[str] = None, + assigner_ids: Optional[List[str]] = None, + creator_ids: Optional[List[str]] = None, + step_ids: Optional[List[int]] = None, + status_schema_id: Optional[str] = None, + cursor: Optional[str] = None, + limit: Optional[int] = None, + sort: Optional[List[str]] = None, + project_id: Optional[str] = None, + has_project: Optional[bool] = None, + custom_properties: Optional[str] = None, + follower_ids: Optional[List[str]] = None, + associated_node_ids: Optional[List[str]] = None, + content_refs: Optional[List[str]] = None, + include_request_form_custom_properties: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get requests + + Get a list of requests. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetRequests`. + + Args: + space_id: Space ID. + planned_end_date_from: filter by request due date (inclusive). + planned_end_date_to: filter by request due date (exclusive). + planned_start_date_from: filter by request start date (inclusive). + planned_start_date_to: filter by request start date (exclusive). + created_at_from: filter by request created date (inclusive). + created_at_to: filter by request created date (exclusive). + updated_at_from: filter by request updated date (inclusive). + updated_at_to: filter by request updated date (exclusive). + ids: A list of request IDs. + title: Keyword values to search for on request titles. + assignee_ids: A list of assignees' user IDs to filter by. + priorities: A list of priority values, Available values : critical, + high, medium, low. + keywords: Keyword values to search. + assigner_ids: A list of assigner' user Ids to filter by. + creator_ids: A list of creators' user IDs to filter by. + step_ids: A list of step IDs to filter by. + status_schema_id: Status schema ID to filter by. + cursor: A token used to guide the next page window. + limit: Number of items to return per page, default: 50. + sort: Sort by requests. + project_id: The project ID a request is associated to. + has_project: Filter by if requests are associated with a project. + custom_properties: Filter by custom properties. + follower_ids: A list of followers' user id. + associated_node_ids: A list of Associated node IDs to filter by. + content_refs: List of content reference objects. + include_request_form_custom_properties: whether to include request + form custom properties, default false. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner/v2/spaces/{quote(str(space_id), safe='')}/requests" + ) + query_params = [] + item: object + if planned_end_date_from is not None: + value = str(planned_end_date_from) + if isinstance(planned_end_date_from, bool): + value = value.lower() + query_params.append(f"plannedEndDateFrom={quote(value, safe='')}") + if planned_end_date_to is not None: + value = str(planned_end_date_to) + if isinstance(planned_end_date_to, bool): + value = value.lower() + query_params.append(f"plannedEndDateTo={quote(value, safe='')}") + if planned_start_date_from is not None: + value = str(planned_start_date_from) + if isinstance(planned_start_date_from, bool): + value = value.lower() + query_params.append(f"plannedStartDateFrom={quote(value, safe='')}") + if planned_start_date_to is not None: + value = str(planned_start_date_to) + if isinstance(planned_start_date_to, bool): + value = value.lower() + query_params.append(f"plannedStartDateTo={quote(value, safe='')}") + if created_at_from is not None: + value = str(created_at_from) + if isinstance(created_at_from, bool): + value = value.lower() + query_params.append(f"createdAtFrom={quote(value, safe='')}") + if created_at_to is not None: + value = str(created_at_to) + if isinstance(created_at_to, bool): + value = value.lower() + query_params.append(f"createdAtTo={quote(value, safe='')}") + if updated_at_from is not None: + value = str(updated_at_from) + if isinstance(updated_at_from, bool): + value = value.lower() + query_params.append(f"updatedAtFrom={quote(value, safe='')}") + if updated_at_to is not None: + value = str(updated_at_to) + if isinstance(updated_at_to, bool): + value = value.lower() + query_params.append(f"updatedAtTo={quote(value, safe='')}") + if ids is not None: + if isinstance(ids, list): + joined_parts = [] + for item in ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"ids={quote(joined, safe='')}") + else: + value = str(ids) + if isinstance(ids, bool): + value = value.lower() + query_params.append(f"ids={quote(value, safe='')}") + if title is not None: + value = str(title) + if isinstance(title, bool): + value = value.lower() + query_params.append(f"title={quote(value, safe='')}") + if assignee_ids is not None: + if isinstance(assignee_ids, list): + joined_parts = [] + for item in assignee_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"assigneeIds={quote(joined, safe='')}") + else: + value = str(assignee_ids) + if isinstance(assignee_ids, bool): + value = value.lower() + query_params.append(f"assigneeIds={quote(value, safe='')}") + if priorities is not None: + if isinstance(priorities, list): + joined_parts = [] + for item in priorities: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"priorities={quote(joined, safe='')}") + else: + value = str(priorities) + if isinstance(priorities, bool): + value = value.lower() + query_params.append(f"priorities={quote(value, safe='')}") + if keywords is not None: + value = str(keywords) + if isinstance(keywords, bool): + value = value.lower() + query_params.append(f"keywords={quote(value, safe='')}") + if assigner_ids is not None: + if isinstance(assigner_ids, list): + joined_parts = [] + for item in assigner_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"assignerIds={quote(joined, safe='')}") + else: + value = str(assigner_ids) + if isinstance(assigner_ids, bool): + value = value.lower() + query_params.append(f"assignerIds={quote(value, safe='')}") + if creator_ids is not None: + if isinstance(creator_ids, list): + joined_parts = [] + for item in creator_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"creatorIds={quote(joined, safe='')}") + else: + value = str(creator_ids) + if isinstance(creator_ids, bool): + value = value.lower() + query_params.append(f"creatorIds={quote(value, safe='')}") + if step_ids is not None: + if isinstance(step_ids, list): + joined_parts = [] + for item in step_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"stepIds={quote(joined, safe='')}") + else: + value = str(step_ids) + if isinstance(step_ids, bool): + value = value.lower() + query_params.append(f"stepIds={quote(value, safe='')}") + if status_schema_id is not None: + value = str(status_schema_id) + if isinstance(status_schema_id, bool): + value = value.lower() + query_params.append(f"statusSchemaId={quote(value, safe='')}") + if cursor is not None: + value = str(cursor) + if isinstance(cursor, bool): + value = value.lower() + query_params.append(f"cursor={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if sort is not None: + if isinstance(sort, list): + joined_parts = [] + for item in sort: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"sort={quote(joined, safe='')}") + else: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if project_id is not None: + value = str(project_id) + if isinstance(project_id, bool): + value = value.lower() + query_params.append(f"projectId={quote(value, safe='')}") + if has_project is not None: + value = str(has_project) + if isinstance(has_project, bool): + value = value.lower() + query_params.append(f"hasProject={quote(value, safe='')}") + if custom_properties is not None: + value = str(custom_properties) + if isinstance(custom_properties, bool): + value = value.lower() + query_params.append(f"customProperties={quote(value, safe='')}") + if follower_ids is not None: + if isinstance(follower_ids, list): + joined_parts = [] + for item in follower_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"followerIds={quote(joined, safe='')}") + else: + value = str(follower_ids) + if isinstance(follower_ids, bool): + value = value.lower() + query_params.append(f"followerIds={quote(value, safe='')}") + if associated_node_ids is not None: + if isinstance(associated_node_ids, list): + joined_parts = [] + for item in associated_node_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"associatedNodeIds={quote(joined, safe='')}") + else: + value = str(associated_node_ids) + if isinstance(associated_node_ids, bool): + value = value.lower() + query_params.append(f"associatedNodeIds={quote(value, safe='')}") + if content_refs is not None: + if isinstance(content_refs, list): + joined_parts = [] + for item in content_refs: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"contentRefs={quote(joined, safe='')}") + else: + value = str(content_refs) + if isinstance(content_refs, bool): + value = value.lower() + query_params.append(f"contentRefs={quote(value, safe='')}") + if include_request_form_custom_properties is not None: + value = str(include_request_form_custom_properties) + if isinstance(include_request_form_custom_properties, bool): + value = value.lower() + query_params.append(f"includeRequestFormCustomProperties={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def delete_requests( + self, + input: DeleteRequest | Mapping[str, Any], + space_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete requests + + Bulk delete requests. + + Swagger operation ID: `DeleteRequests`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner/v2/spaces/{quote(str(space_id), safe='')}/requests" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_request( + self, + input: CreateRequest | Mapping[str, Any], + space_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create request + + Create a request. + + Swagger operation ID: `CreateRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner/v2/spaces/{quote(str(space_id), safe='')}/requests" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_request( + self, + space_id: str, + request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get request + + Get a single request. + + Swagger operation ID: `GetRequest`. + + Args: + space_id: Space ID. + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/requests" + f"/{quote(str(request_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_request( + self, + space_id: str, + request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete request + + Delete a request. + + Swagger operation ID: `DeleteRequest`. + + Args: + space_id: Space ID. + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/requests" + f"/{quote(str(request_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def update_request( + self, + input: UpdateRequest | Mapping[str, Any], + space_id: str, + request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update request + + Update a request. + + Swagger operation ID: `UpdateRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/requests" + f"/{quote(str(request_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_status_schemas( + self, + space_id: str, + *, + is_default: Optional[bool] = None, + type_: Optional[str] = None, + ids: Optional[List[str]] = None, + creator_ids: Optional[List[str]] = None, + cursor: Optional[str] = None, + limit: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get status schemas + + Get a list of task/request status schemas. These schemas hold the data + for set statuses for specific work. Example: `(Not started, In + progress, Complete)` + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetStatusSchemas`. + + Args: + space_id: Space ID. + is_default: Get default status schema. + type_: Query by node type. + ids: List of status schemas IDs. + creator_ids: List of user IDs to query by creator. + cursor: Cursor used for pagination. + limit: Number to limit returned records. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner/v2/spaces/{quote(str(space_id), safe='')}/statusschema" + ) + query_params = [] + item: object + if is_default is not None: + value = str(is_default) + if isinstance(is_default, bool): + value = value.lower() + query_params.append(f"isDefault={quote(value, safe='')}") + if type_ is not None: + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if ids is not None: + if isinstance(ids, list): + joined_parts = [] + for item in ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"ids={quote(joined, safe='')}") + else: + value = str(ids) + if isinstance(ids, bool): + value = value.lower() + query_params.append(f"ids={quote(value, safe='')}") + if creator_ids is not None: + if isinstance(creator_ids, list): + joined_parts = [] + for item in creator_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"creatorIds={quote(joined, safe='')}") + else: + value = str(creator_ids) + if isinstance(creator_ids, bool): + value = value.lower() + query_params.append(f"creatorIds={quote(value, safe='')}") + if cursor is not None: + value = str(cursor) + if isinstance(cursor, bool): + value = value.lower() + query_params.append(f"cursor={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_status_schema( + self, + space_id: str, + status_schema_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get status schema + + Get a single status schema by ID. These schemas hold the data for set + statuses for specific work. Example: `(Not started, In progress, + Complete)` + + Swagger operation ID: `GetStatusSchema`. + + Args: + space_id: Space ID. + status_schema_id: Status schema ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/statusschema" + f"/{quote(str(status_schema_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tasks( + self, + space_id: str, + *, + planned_end_date_from: Optional[str] = None, + planned_end_date_to: Optional[str] = None, + planned_start_date_from: Optional[str] = None, + planned_start_date_to: Optional[str] = None, + created_at_from: Optional[str] = None, + created_at_to: Optional[str] = None, + updated_at_from: Optional[str] = None, + updated_at_to: Optional[str] = None, + ids: Optional[List[str]] = None, + title: Optional[str] = None, + description: Optional[str] = None, + assignee_ids: Optional[List[str]] = None, + priorities: Optional[List[str]] = None, + keywords: Optional[str] = None, + assigner_ids: Optional[List[str]] = None, + step_ids: Optional[List[int]] = None, + status_schema_id: Optional[str] = None, + cursor: Optional[str] = None, + limit: Optional[int] = None, + sort: Optional[List[str]] = None, + recursive: Optional[bool] = None, + project_id: Optional[str] = None, + has_project: Optional[bool] = None, + custom_properties: Optional[str] = None, + follower_ids: Optional[List[str]] = None, + associated_node_ids: Optional[List[str]] = None, + creator_ids: Optional[List[str]] = None, + include_associations: Optional[bool] = None, + parent_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get tasks + + Get a list of tasks. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTasks`. + + Args: + space_id: Space ID. + planned_end_date_from: Filter by task due date (inclusive). + planned_end_date_to: Filter by task due date (exclusive). + planned_start_date_from: Filter by task start date (inclusive). + planned_start_date_to: Filter by task start date (exclusive). + created_at_from: Filter by task created date (inclusive). + created_at_to: Filter by task created date (exclusive). + updated_at_from: Filter by task updated date (inclusive). + updated_at_to: Filter by task updated date (exclusive). + ids: Filter by a list of task IDs. + title: Filter by task title. + description: Filter by task description. + assignee_ids: List of user IDs to filter by assignee. + priorities: Filter by list of priorities. + keywords: Filter by keywords. + assigner_ids: List of user IDs to filter by user that assigned the + task. + step_ids: Filter by status value IDs. + status_schema_id: Filter by status schema IDs. + cursor: Cursor used for pagination. + limit: Number to limit returned records. + sort: Sort by query. + recursive: Include subtasks within the returned list. + project_id: Filter by project ID. + has_project: Filter by tasks that are associated with a project. + custom_properties: Filter by custom property values. + follower_ids: List of user IDs to filter by followers. + associated_node_ids: List of association IDs to filter by. + creator_ids: List of user IDs to filter by creator. + include_associations: Include association data in the response. + parent_id: List of task IDs to filter by. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner/v2/spaces/{quote(str(space_id), safe='')}/tasks" + ) + query_params = [] + item: object + if planned_end_date_from is not None: + value = str(planned_end_date_from) + if isinstance(planned_end_date_from, bool): + value = value.lower() + query_params.append(f"plannedEndDateFrom={quote(value, safe='')}") + if planned_end_date_to is not None: + value = str(planned_end_date_to) + if isinstance(planned_end_date_to, bool): + value = value.lower() + query_params.append(f"plannedEndDateTo={quote(value, safe='')}") + if planned_start_date_from is not None: + value = str(planned_start_date_from) + if isinstance(planned_start_date_from, bool): + value = value.lower() + query_params.append(f"plannedStartDateFrom={quote(value, safe='')}") + if planned_start_date_to is not None: + value = str(planned_start_date_to) + if isinstance(planned_start_date_to, bool): + value = value.lower() + query_params.append(f"plannedStartDateTo={quote(value, safe='')}") + if created_at_from is not None: + value = str(created_at_from) + if isinstance(created_at_from, bool): + value = value.lower() + query_params.append(f"createdAtFrom={quote(value, safe='')}") + if created_at_to is not None: + value = str(created_at_to) + if isinstance(created_at_to, bool): + value = value.lower() + query_params.append(f"createdAtTo={quote(value, safe='')}") + if updated_at_from is not None: + value = str(updated_at_from) + if isinstance(updated_at_from, bool): + value = value.lower() + query_params.append(f"updatedAtFrom={quote(value, safe='')}") + if updated_at_to is not None: + value = str(updated_at_to) + if isinstance(updated_at_to, bool): + value = value.lower() + query_params.append(f"updatedAtTo={quote(value, safe='')}") + if ids is not None: + if isinstance(ids, list): + joined_parts = [] + for item in ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"ids={quote(joined, safe='')}") + else: + value = str(ids) + if isinstance(ids, bool): + value = value.lower() + query_params.append(f"ids={quote(value, safe='')}") + if title is not None: + value = str(title) + if isinstance(title, bool): + value = value.lower() + query_params.append(f"title={quote(value, safe='')}") + if description is not None: + value = str(description) + if isinstance(description, bool): + value = value.lower() + query_params.append(f"description={quote(value, safe='')}") + if assignee_ids is not None: + if isinstance(assignee_ids, list): + joined_parts = [] + for item in assignee_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"assigneeIds={quote(joined, safe='')}") + else: + value = str(assignee_ids) + if isinstance(assignee_ids, bool): + value = value.lower() + query_params.append(f"assigneeIds={quote(value, safe='')}") + if priorities is not None: + if isinstance(priorities, list): + joined_parts = [] + for item in priorities: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"priorities={quote(joined, safe='')}") + else: + value = str(priorities) + if isinstance(priorities, bool): + value = value.lower() + query_params.append(f"priorities={quote(value, safe='')}") + if keywords is not None: + value = str(keywords) + if isinstance(keywords, bool): + value = value.lower() + query_params.append(f"keywords={quote(value, safe='')}") + if assigner_ids is not None: + if isinstance(assigner_ids, list): + joined_parts = [] + for item in assigner_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"assignerIds={quote(joined, safe='')}") + else: + value = str(assigner_ids) + if isinstance(assigner_ids, bool): + value = value.lower() + query_params.append(f"assignerIds={quote(value, safe='')}") + if step_ids is not None: + if isinstance(step_ids, list): + joined_parts = [] + for item in step_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"stepIds={quote(joined, safe='')}") + else: + value = str(step_ids) + if isinstance(step_ids, bool): + value = value.lower() + query_params.append(f"stepIds={quote(value, safe='')}") + if status_schema_id is not None: + value = str(status_schema_id) + if isinstance(status_schema_id, bool): + value = value.lower() + query_params.append(f"statusSchemaId={quote(value, safe='')}") + if cursor is not None: + value = str(cursor) + if isinstance(cursor, bool): + value = value.lower() + query_params.append(f"cursor={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if sort is not None: + if isinstance(sort, list): + joined_parts = [] + for item in sort: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"sort={quote(joined, safe='')}") + else: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if recursive is not None: + value = str(recursive) + if isinstance(recursive, bool): + value = value.lower() + query_params.append(f"recursive={quote(value, safe='')}") + if project_id is not None: + value = str(project_id) + if isinstance(project_id, bool): + value = value.lower() + query_params.append(f"projectId={quote(value, safe='')}") + if has_project is not None: + value = str(has_project) + if isinstance(has_project, bool): + value = value.lower() + query_params.append(f"hasProject={quote(value, safe='')}") + if custom_properties is not None: + value = str(custom_properties) + if isinstance(custom_properties, bool): + value = value.lower() + query_params.append(f"customProperties={quote(value, safe='')}") + if follower_ids is not None: + if isinstance(follower_ids, list): + joined_parts = [] + for item in follower_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"followerIds={quote(joined, safe='')}") + else: + value = str(follower_ids) + if isinstance(follower_ids, bool): + value = value.lower() + query_params.append(f"followerIds={quote(value, safe='')}") + if associated_node_ids is not None: + if isinstance(associated_node_ids, list): + joined_parts = [] + for item in associated_node_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"associatedNodeIds={quote(joined, safe='')}") + else: + value = str(associated_node_ids) + if isinstance(associated_node_ids, bool): + value = value.lower() + query_params.append(f"associatedNodeIds={quote(value, safe='')}") + if creator_ids is not None: + if isinstance(creator_ids, list): + joined_parts = [] + for item in creator_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"creatorIds={quote(joined, safe='')}") + else: + value = str(creator_ids) + if isinstance(creator_ids, bool): + value = value.lower() + query_params.append(f"creatorIds={quote(value, safe='')}") + if include_associations is not None: + value = str(include_associations) + if isinstance(include_associations, bool): + value = value.lower() + query_params.append(f"includeAssociations={quote(value, safe='')}") + if parent_id is not None: + value = str(parent_id) + if isinstance(parent_id, bool): + value = value.lower() + query_params.append(f"parentId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_task( + self, + input: CreateTask | Mapping[str, Any], + space_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create task + + Create a task. + + Swagger operation ID: `CreateTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner/v2/spaces/{quote(str(space_id), safe='')}/tasks" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_task( + self, + space_id: str, + task_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get task + + Get a single task by ID. + + Swagger operation ID: `GetTask`. + + Args: + space_id: Space ID. + task_id: Task ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/tasks" + f"/{quote(str(task_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_task( + self, + space_id: str, + task_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete task + + Delete a task. + + Swagger operation ID: `DeleteTask`. + + Args: + space_id: Space ID. + task_id: Task ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/tasks" + f"/{quote(str(task_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_task( + self, + input: UpdateTask | Mapping[str, Any], + space_id: str, + task_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update task + + Update an existing task. + + Swagger operation ID: `UpdateTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + task_id: Task ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/planner" + f"/v2" + f"/spaces" + f"/{quote(str(space_id), safe='')}" + f"/tasks" + f"/{quote(str(task_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/sendgrid.py b/src/azure/connectors/aio/sendgrid.py new file mode 100644 index 0000000..0f9c4ca --- /dev/null +++ b/src/azure/connectors/aio/sendgrid.py @@ -0,0 +1,781 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# SendgridClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.sendgrid import ( + AddGlobalSuppressRequestAndResponse, + Bounce, + Bounces, + EmailAttachment, + EmailIsUnsubscribedResponse, + EmailRequest, + EmailResponse, + GetGlobalSuppressEmptyResponse, + GetGlobalSuppressResponse, + ObjectEntity, + Recipient, + RecipientList, + RecipientLists, + Recipients, + ScopeList, +) + +__all__ = [ + "SendgridClient", + "AddGlobalSuppressRequestAndResponse", + "Bounce", + "Bounces", + "EmailAttachment", + "EmailIsUnsubscribedResponse", + "EmailRequest", + "EmailResponse", + "GetGlobalSuppressEmptyResponse", + "GetGlobalSuppressResponse", + "ObjectEntity", + "Recipient", + "RecipientList", + "RecipientLists", + "Recipients", + "ScopeList", +] + + +# Type Definitions + +# Client Class + +class SendgridClient(ConnectorClientBase): + """Typed client for sendgrid connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a SendgridClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "sendgrid" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def add_global_suppression( + self, + input: AddGlobalSuppressRequestAndResponse | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add a global suppression + + Add a global suppression + + Swagger operation ID: `AddGlobalSuppression`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/suppressions/global" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_global_suppression( + self, + email: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get the global suppression + + Get the global suppression + + Swagger operation ID: `GetGlobalSuppression`. + + Args: + email: The email to check. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/suppressions/global/{quote(str(email), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_global_suppression( + self, + email: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete the global suppression + + Delete the global suppression + + Swagger operation ID: `DeleteGlobalSuppression`. + + Args: + email: The email to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/suppressions/global/{quote(str(email), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_recipient_to_list( + self, + list_id: str, + recipient_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add recipient to list + + Add an individual recipient to a recipient list. + + Swagger operation ID: `AddRecipientToList`. + + Args: + list_id: Unique id of the recipient list. + recipient_id: Unique id of the recipient. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v3" + f"/contactdb" + f"/lists" + f"/{quote(str(list_id), safe='')}" + f"/recipients" + f"/{quote(str(recipient_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_bounce( + self, + email: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get bounce for an email + + Get a specific bounce for a given email address. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetBounce`. + + Args: + email: The email to check. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/suppression/bounces/{quote(str(email), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def delete_bounce( + self, + email: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete an email from bounce list + + Delete an email address from your bounce list. + + Swagger operation ID: `DeleteBounce`. + + Args: + email: The email to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/suppression/bounces/{quote(str(email), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def check_email_is_in_unsubscribes_list( + self, + email: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Check if email is in unsubscribed email list + + Check if email is in unsubscribed email list. + + Swagger operation ID: `CheckEmailIsInUnsubscribesList`. + + Args: + email: The email to check. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/unsubscribes/{quote(str(email), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_email( + self, + input: EmailRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send email + + Sends an email (V4). Limited to 1000 recipients. + + Swagger operation ID: `SendEmailV4`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v4/mail/send" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_recipient_lists( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Recipient Lists + + Retrieves all the recipient lists. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListRecipientLists`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v3/contactdb/lists" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("lists", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_recipients( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List Recipients + + Retrieves all registered recipients. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListRecipients`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v3/contactdb/recipients" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("recipients", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/servicebus.py b/src/azure/connectors/aio/servicebus.py new file mode 100644 index 0000000..009506a --- /dev/null +++ b/src/azure/connectors/aio/servicebus.py @@ -0,0 +1,2335 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# ServicebusClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.servicebus import ( + CreateTopicSubscriptionInput, + ObjectEntity, + SendMessagesInput, + ServiceBusEntity, + ServiceBusMessage, + Subscription, + SubscriptionCorrelationFilter, + SubscriptionFilter, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "ServicebusClient", + "CreateTopicSubscriptionInput", + "ObjectEntity", + "SendMessagesInput", + "ServiceBusEntity", + "ServiceBusMessage", + "Subscription", + "SubscriptionCorrelationFilter", + "SubscriptionFilter", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class ServicebusClient(ConnectorClientBase): + """Typed client for servicebus connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a ServicebusClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "servicebus" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def send_message( + self, + input: ServiceBusMessage | Mapping[str, Any], + entity_name: str, + *, + system_properties: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Send message + + This operation sends a message to a queue or topic. + + Swagger operation ID: `SendMessage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entity_name: Name of the queue or topic. + system_properties: System properties - None or Run Details. Run + Details will add run metadata property details as custom + properties in the message. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(entity_name), safe=''), safe='')}/messages" + ) + query_params = [] + if system_properties is not None: + value = str(system_properties) + if isinstance(system_properties, bool): + value = value.lower() + query_params.append(f"systemProperties={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def send_messages( + self, + input: SendMessagesInput, + entity_name: str, + *, + system_properties: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Send one or more messages + + This operation sends one or more messages to a queue or topic. + + Swagger operation ID: `SendMessages`. + + Args: + input: The request body. + entity_name: Name of the queue or topic. + system_properties: System properties - None or Run Details. Run + Details will add run metadata property details as custom + properties in the message. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(entity_name), safe=''), safe='')}" + f"/messages" + f"/batch" + ) + query_params = [] + if system_properties is not None: + value = str(system_properties) + if isinstance(system_properties, bool): + value = value.lower() + query_params.append(f"systemProperties={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def complete_message_in_queue( + self, + queue_name: str, + lock_token: str, + *, + queue_type: Optional[str] = None, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Complete the message in a queue + + The operation completes a message in a queue. + + Swagger operation ID: `CompleteMessageInQueue`. + + Args: + queue_name: Name of the queue. + lock_token: Lock token of the message to complete. + queue_type: Queue type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(queue_name), safe=''), safe='')}" + f"/messages" + f"/complete" + ) + query_params = [] + value = str(lock_token) + if isinstance(lock_token, bool): + value = value.lower() + query_params.append(f"lockToken={quote(value, safe='')}") + if queue_type is not None: + value = str(queue_type) + if isinstance(queue_type, bool): + value = value.lower() + query_params.append(f"queueType={quote(value, safe='')}") + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def abandon_message_in_queue( + self, + queue_name: str, + lock_token: str, + *, + queue_type: Optional[str] = None, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Abandon the message in a queue + + The operation abandons a message in a queue. + + Swagger operation ID: `AbandonMessageInQueue`. + + Args: + queue_name: Name of the queue. + lock_token: Lock token of the message to abandon. + queue_type: Queue type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(queue_name), safe=''), safe='')}" + f"/messages" + f"/abandon" + ) + query_params = [] + value = str(lock_token) + if isinstance(lock_token, bool): + value = value.lower() + query_params.append(f"lockToken={quote(value, safe='')}") + if queue_type is not None: + value = str(queue_type) + if isinstance(queue_type, bool): + value = value.lower() + query_params.append(f"queueType={quote(value, safe='')}") + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_deferred_message_from_queue( + self, + queue_name: str, + sequence_number: int, + *, + queue_type: Optional[str] = None, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get deferred message from a queue + + The operation gets a deferred message from a queue. + + Swagger operation ID: `GetDeferredMessageFromQueue`. + + Args: + queue_name: Name of the queue. + sequence_number: Sequence number of message. + queue_type: Queue type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(queue_name), safe=''), safe='')}" + f"/messages" + f"/defer" + ) + query_params = [] + value = str(sequence_number) + if isinstance(sequence_number, bool): + value = value.lower() + query_params.append(f"sequenceNumber={quote(value, safe='')}") + if queue_type is not None: + value = str(queue_type) + if isinstance(queue_type, bool): + value = value.lower() + query_params.append(f"queueType={quote(value, safe='')}") + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def defer_message_in_queue( + self, + queue_name: str, + lock_token: str, + *, + queue_type: Optional[str] = None, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Defer the message in a queue + + The operation defers a message in a queue. + + Swagger operation ID: `DeferMessageInQueue`. + + Args: + queue_name: Name of the queue. + lock_token: Lock token of the message to defer. + queue_type: Queue type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(queue_name), safe=''), safe='')}" + f"/messages" + f"/defer" + ) + query_params = [] + value = str(lock_token) + if isinstance(lock_token, bool): + value = value.lower() + query_params.append(f"lockToken={quote(value, safe='')}") + if queue_type is not None: + value = str(queue_type) + if isinstance(queue_type, bool): + value = value.lower() + query_params.append(f"queueType={quote(value, safe='')}") + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def dead_letter_message_in_queue( + self, + queue_name: str, + lock_token: str, + *, + session_id: Optional[str] = None, + dead_letter_reason: Optional[str] = None, + dead_letter_error_description: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Dead-letter the message in a queue + + The operation moves the message to the Dead-Letter Queue. + + Swagger operation ID: `DeadLetterMessageInQueue`. + + Args: + queue_name: Name of the queue. + lock_token: Lock token of the message to dead-letter. + session_id: Session id. + dead_letter_reason: Dead letter reason. + dead_letter_error_description: Dead letter error description. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(queue_name), safe=''), safe='')}" + f"/messages" + f"/deadletter" + ) + query_params = [] + value = str(lock_token) + if isinstance(lock_token, bool): + value = value.lower() + query_params.append(f"lockToken={quote(value, safe='')}") + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if dead_letter_reason is not None: + value = str(dead_letter_reason) + if isinstance(dead_letter_reason, bool): + value = value.lower() + query_params.append(f"deadLetterReason={quote(value, safe='')}") + if dead_letter_error_description is not None: + value = str(dead_letter_error_description) + if isinstance(dead_letter_error_description, bool): + value = value.lower() + query_params.append(f"deadLetterErrorDescription={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def renew_lock_on_message_in_queue( + self, + queue_name: str, + lock_token: str, + *, + queue_type: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Renew lock on the message in a queue + + The operation renews lock on a message in a queue. + + Swagger operation ID: `RenewLockOnMessageInQueue`. + + Args: + queue_name: Name of the queue. + lock_token: Lock token of the message to renew lock. + queue_type: Queue type - Main or DeadLetter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(queue_name), safe=''), safe='')}" + f"/messages" + f"/renewlock" + ) + query_params = [] + value = str(lock_token) + if isinstance(lock_token, bool): + value = value.lower() + query_params.append(f"lockToken={quote(value, safe='')}") + if queue_type is not None: + value = str(queue_type) + if isinstance(queue_type, bool): + value = value.lower() + query_params.append(f"queueType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_messages_from_queue_with_peek_lock( + self, + queue_name: str, + *, + max_message_count: Optional[int] = None, + queue_type: Optional[str] = None, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get messages from a queue (peek-lock) + + The operation receives messages from a queue with peek-lock. If maximum + message count is not provided, it reads 20 messages. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMessagesFromQueueWithPeekLock`. + + Args: + queue_name: Name of the queue. + max_message_count: The maximum number of messages to return in the + batch. + queue_type: Queue type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(queue_name), safe=''), safe='')}" + f"/messages" + f"/batch" + f"/peek" + ) + query_params = [] + if max_message_count is not None: + value = str(max_message_count) + if isinstance(max_message_count, bool): + value = value.lower() + query_params.append(f"maxMessageCount={quote(value, safe='')}") + if queue_type is not None: + value = str(queue_type) + if isinstance(queue_type, bool): + value = value.lower() + query_params.append(f"queueType={quote(value, safe='')}") + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def close_session_in_queue( + self, + queue_name: str, + session_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Close a session in a queue + + The operation closes a session in a queue. + + Swagger operation ID: `CloseSessionInQueue`. + + Args: + queue_name: Name of a queue. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(queue_name), safe=''), safe='')}" + f"/sessions" + f"/{quote(str(session_id), safe='')}" + f"/close" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def renew_lock_on_session_in_queue( + self, + queue_name: str, + session_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Renew lock on the session in a queue + + The operation renews a session in a queue. + + Swagger operation ID: `RenewLockOnSessionInQueue`. + + Args: + queue_name: Name of the queue. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(queue_name), safe=''), safe='')}" + f"/sessions" + f"/{quote(str(session_id), safe='')}" + f"/renewlock" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def complete_message_in_topic( + self, + topic_name: str, + subscription_name: str, + lock_token: str, + *, + subscription_type: Optional[str] = None, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Complete the message in a topic subscription + + The operation completes a message in a topic subscription. + + Swagger operation ID: `CompleteMessageInTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + lock_token: Lock token of the message to complete. + subscription_type: Subscription type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(topic_name), safe=''), safe='')}" + f"/subscriptions" + f"/{quote(str(subscription_name), safe='')}" + f"/messages" + f"/complete" + ) + query_params = [] + value = str(lock_token) + if isinstance(lock_token, bool): + value = value.lower() + query_params.append(f"lockToken={quote(value, safe='')}") + if subscription_type is not None: + value = str(subscription_type) + if isinstance(subscription_type, bool): + value = value.lower() + query_params.append(f"subscriptionType={quote(value, safe='')}") + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def abandon_message_in_topic( + self, + topic_name: str, + subscription_name: str, + lock_token: str, + *, + subscription_type: Optional[str] = None, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Abandon the message in a topic subscription + + The operation abandons a message in a topic subscription. + + Swagger operation ID: `AbandonMessageInTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + lock_token: Lock token of the message to abandon. + subscription_type: Subscription type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(topic_name), safe=''), safe='')}" + f"/subscriptions" + f"/{quote(str(subscription_name), safe='')}" + f"/messages" + f"/abandon" + ) + query_params = [] + value = str(lock_token) + if isinstance(lock_token, bool): + value = value.lower() + query_params.append(f"lockToken={quote(value, safe='')}") + if subscription_type is not None: + value = str(subscription_type) + if isinstance(subscription_type, bool): + value = value.lower() + query_params.append(f"subscriptionType={quote(value, safe='')}") + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_deferred_message_from_topic( + self, + topic_name: str, + subscription_name: str, + sequence_number: int, + *, + subscription_type: Optional[str] = None, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get deferred message from a topic subscription + + The operation gets a deferred message from a topic subscription. + + Swagger operation ID: `GetDeferredMessageFromTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + sequence_number: Sequence number of message. + subscription_type: Queue type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(topic_name), safe=''), safe='')}" + f"/subscriptions" + f"/{quote(str(subscription_name), safe='')}" + f"/messages" + f"/defer" + ) + query_params = [] + value = str(sequence_number) + if isinstance(sequence_number, bool): + value = value.lower() + query_params.append(f"sequenceNumber={quote(value, safe='')}") + if subscription_type is not None: + value = str(subscription_type) + if isinstance(subscription_type, bool): + value = value.lower() + query_params.append(f"subscriptionType={quote(value, safe='')}") + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def defer_message_in_topic( + self, + topic_name: str, + subscription_name: str, + lock_token: str, + *, + subscription_type: Optional[str] = None, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Defer the message in a topic subscription + + The operation defers a message in a topic subscription. + + Swagger operation ID: `DeferMessageInTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + lock_token: Lock token of the message to defer. + subscription_type: Subscription type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(topic_name), safe=''), safe='')}" + f"/subscriptions" + f"/{quote(str(subscription_name), safe='')}" + f"/messages" + f"/defer" + ) + query_params = [] + value = str(lock_token) + if isinstance(lock_token, bool): + value = value.lower() + query_params.append(f"lockToken={quote(value, safe='')}") + if subscription_type is not None: + value = str(subscription_type) + if isinstance(subscription_type, bool): + value = value.lower() + query_params.append(f"subscriptionType={quote(value, safe='')}") + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def dead_letter_message_in_topic( + self, + topic_name: str, + subscription_name: str, + lock_token: str, + *, + session_id: Optional[str] = None, + dead_letter_reason: Optional[str] = None, + dead_letter_error_description: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Dead-letter the message in a topic subscription + + The operation moves the message to the topic Dead-Letter Queue. + + Swagger operation ID: `DeadLetterMessageInTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + lock_token: Lock token of the message to dead-letter. + session_id: Session id. + dead_letter_reason: Dead letter reason. + dead_letter_error_description: Dead letter error description. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(topic_name), safe=''), safe='')}" + f"/subscriptions" + f"/{quote(str(subscription_name), safe='')}" + f"/messages" + f"/deadletter" + ) + query_params = [] + value = str(lock_token) + if isinstance(lock_token, bool): + value = value.lower() + query_params.append(f"lockToken={quote(value, safe='')}") + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if dead_letter_reason is not None: + value = str(dead_letter_reason) + if isinstance(dead_letter_reason, bool): + value = value.lower() + query_params.append(f"deadLetterReason={quote(value, safe='')}") + if dead_letter_error_description is not None: + value = str(dead_letter_error_description) + if isinstance(dead_letter_error_description, bool): + value = value.lower() + query_params.append(f"deadLetterErrorDescription={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def renew_lock_on_message_in_topic( + self, + topic_name: str, + subscription_name: str, + lock_token: str, + *, + subscription_type: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Renew lock on the message in a topic subscription + + The operation renews lock on a message in a topic subscription. + + Swagger operation ID: `RenewLockOnMessageInTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + lock_token: Lock token of the message to renew lock. + subscription_type: Subscription type - Main or DeadLetter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(topic_name), safe=''), safe='')}" + f"/subscriptions" + f"/{quote(str(subscription_name), safe='')}" + f"/messages" + f"/renewlock" + ) + query_params = [] + value = str(lock_token) + if isinstance(lock_token, bool): + value = value.lower() + query_params.append(f"lockToken={quote(value, safe='')}") + if subscription_type is not None: + value = str(subscription_type) + if isinstance(subscription_type, bool): + value = value.lower() + query_params.append(f"subscriptionType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def create_topic_subscription( + self, + input: CreateTopicSubscriptionInput | Mapping[str, Any], + topic_name: str, + subscription_name: str, + *, + subscription_filter_type: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a topic subscription + + The operation creates a topic subscription. + + Swagger operation ID: `CreateTopicSubscription`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + subscription_filter_type: Filter type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(topic_name), safe=''), safe='')}" + f"/subscriptions" + f"/{quote(str(subscription_name), safe='')}" + ) + query_params = [] + if subscription_filter_type is not None: + value = str(subscription_filter_type) + if isinstance(subscription_filter_type, bool): + value = value.lower() + query_params.append(f"subscriptionFilterType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_topic_subscription( + self, + topic_name: str, + subscription_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a topic subscription + + The operation deletes a topic subscription. + + Swagger operation ID: `DeleteTopicSubscription`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(topic_name), safe=''), safe='')}" + f"/subscriptions" + f"/{quote(str(subscription_name), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_messages_from_topic_with_peek_lock( + self, + topic_name: str, + subscription_name: str, + *, + max_message_count: Optional[int] = None, + subscription_type: Optional[str] = None, + session_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get messages from a topic subscription (peek-lock) + + The operation receives messages from a topic subscription with + peek-lock. If maximum message count is not provided, it reads 20 + messages. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMessagesFromTopicWithPeekLock`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + max_message_count: The maximum number of messages to return in the + batch. + subscription_type: Subscription type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(topic_name), safe=''), safe='')}" + f"/subscriptions" + f"/{quote(str(subscription_name), safe='')}" + f"/messages" + f"/batch" + f"/peek" + ) + query_params = [] + if max_message_count is not None: + value = str(max_message_count) + if isinstance(max_message_count, bool): + value = value.lower() + query_params.append(f"maxMessageCount={quote(value, safe='')}") + if subscription_type is not None: + value = str(subscription_type) + if isinstance(subscription_type, bool): + value = value.lower() + query_params.append(f"subscriptionType={quote(value, safe='')}") + if session_id is not None: + value = str(session_id) + if isinstance(session_id, bool): + value = value.lower() + query_params.append(f"sessionId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def close_session_in_topic( + self, + topic_name: str, + subscription_name: str, + session_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Close a session in the topic + + The operation closes a session in the topic. + + Swagger operation ID: `CloseSessionInTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(topic_name), safe=''), safe='')}" + f"/subscriptions" + f"/{quote(str(subscription_name), safe='')}" + f"/sessions" + f"/{quote(str(session_id), safe='')}" + f"/close" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def renew_lock_on_session_in_topic( + self, + topic_name: str, + subscription_name: str, + session_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Renew lock on the session in a topic subscription + + The operation renews a session in a topic subscription. + + Swagger operation ID: `RenewLockOnSessionInTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/{quote(quote(str(topic_name), safe=''), safe='')}" + f"/subscriptions" + f"/{quote(str(subscription_name), safe='')}" + f"/sessions" + f"/{quote(str(session_id), safe='')}" + f"/renewlock" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_entities( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get all entities + + This operation gets all queues and topics in the Service Bus namespace. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetEntities`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/entities" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_system_properties( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[str]: + """ + Get the list of system properties + + This operation gets list of properties. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetSystemProperties`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[str]: An Azure Core pager over connector results. + Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/systemproperties" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[str]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_queues( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[str]: + """ + Get all queues + + This operation gets all queues in the Service Bus namespace. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetQueues`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[str]: An Azure Core pager over connector results. + Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/queues" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[str]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_session_options( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[str]: + """ + Get session options + + This operation gets the list of options for session handling - None, + Next available. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetSessionOptions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[str]: An Azure Core pager over connector results. + Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/sessionoptions" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[str]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_topics( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[str]: + """ + Get all topics + + This operation gets all topics in the Service Bus namespace. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTopics`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[str]: An Azure Core pager over connector results. + Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/topics" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[str]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_subscriptions( + self, + topic_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[str]: + """ + Get the subscriptions for a topic + + This operation gets the list of subscriptions for a topic in the + Service Bus namespace. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetSubscriptions`. + + Args: + topic_name: Topic name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[str]: An Azure Core pager over connector results. + Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/topics" + f"/{quote(quote(str(topic_name), safe=''), safe='')}" + f"/subscriptions" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[str]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_subscription_filter( + self, + subscription_filter_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get metadata of a filter + + Get metadata of a filter. + + Swagger operation ID: `GetSubscriptionFilterV2`. + + Args: + subscription_filter_type: Subscription filter type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/subscriptionfilterV2" + query_params = [] + value = str(subscription_filter_type) + if isinstance(subscription_filter_type, bool): + value = value.lower() + query_params.append(f"subscriptionFilterType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/sharepointonline.py b/src/azure/connectors/aio/sharepointonline.py new file mode 100644 index 0000000..b0455d3 --- /dev/null +++ b/src/azure/connectors/aio/sharepointonline.py @@ -0,0 +1,5959 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# SharepointonlineClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.sharepointonline import ( + ApplicationPermissionIdentity, + ApprovalData, + ApproveHubSiteJoinResponse, + BlobDataSetsMetadata, + BlobMetadata, + BlobMetadataPage, + BlobMetadataResponse, + CopyFileParameters, + CopyFolderParameters, + CreateAgreementsSolutionDocumentInput, + CreateApprovalRequestInput, + CreateContentAssemblyDocumentInput, + CreateNewDocumentSetParameters, + CreateNewDocumentSetResponse, + CreateNewFolderParameters, + CreateNewFolderResponse, + DataSet, + DataSetsList, + DataSetsMetadata, + DeletedItem, + DeletedItemList, + FileCheckInParameters, + FormFieldMetadata, + GetItemChangesMetadataResponse, + GetItemChangesResponse, + GetItemResponse, + GroupPermissionIdentity, + HubSiteJoinApprovalOutput, + Item, + ItemGrantAccessBody, + ItemPermissionAddBody, + ItemPermissionCreateLinkBody, + ItemPermissionRecipient, + ItemPermissionUpdateBody, + ItemReference, + ItemsList, + MoveFileParameters, + MoveFolderParameters, + ObjectEntity, + PassThroughNativeQuery, + PatchFileItemInput, + PatchFileItemResponse, + PatchFileItemWithPredictedValuesParameters, + PatchItemInput, + PatchItemResponse, + Permission, + PermissionIdentitySet, + PermissionsList, + PostItemInput, + PostItemResponse, + Procedure, + PublishedResult, + SPBlobMetadataResponse, + SPContentType, + SPForASelectedFileResponse, + SPListEntity, + SPListExpandedUser, + SPListItemAttachment, + SetApprovalStatusOutput, + SharePointHttpRequestBodyParameters, + SharePointIds, + SharingInvitation, + SharingLink, + SharingLinkPermission, + SharingLinkPermissionIdentitySet, + SharingLinkUserPermissionIdentity, + SubmitDocGenFormInput, + Table, + TableCapabilitiesMetadata, + TableCountRestrictionsMetadata, + TableFilterRestrictionsMetadata, + TableForm, + TableMetadata, + TableSelectRestrictionsMetadata, + TableSortRestrictionsMetadata, + TablesList, + TabularDataSetsMetadata, + UserPermissionIdentity, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "SharepointonlineClient", + "ApplicationPermissionIdentity", + "ApprovalData", + "ApproveHubSiteJoinResponse", + "BlobDataSetsMetadata", + "BlobMetadata", + "BlobMetadataPage", + "BlobMetadataResponse", + "CopyFileParameters", + "CopyFolderParameters", + "CreateAgreementsSolutionDocumentInput", + "CreateApprovalRequestInput", + "CreateContentAssemblyDocumentInput", + "CreateNewDocumentSetParameters", + "CreateNewDocumentSetResponse", + "CreateNewFolderParameters", + "CreateNewFolderResponse", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "DeletedItem", + "DeletedItemList", + "FileCheckInParameters", + "FormFieldMetadata", + "GetItemChangesMetadataResponse", + "GetItemChangesResponse", + "GetItemResponse", + "GroupPermissionIdentity", + "HubSiteJoinApprovalOutput", + "Item", + "ItemGrantAccessBody", + "ItemPermissionAddBody", + "ItemPermissionCreateLinkBody", + "ItemPermissionRecipient", + "ItemPermissionUpdateBody", + "ItemReference", + "ItemsList", + "MoveFileParameters", + "MoveFolderParameters", + "ObjectEntity", + "PassThroughNativeQuery", + "PatchFileItemInput", + "PatchFileItemResponse", + "PatchFileItemWithPredictedValuesParameters", + "PatchItemInput", + "PatchItemResponse", + "Permission", + "PermissionIdentitySet", + "PermissionsList", + "PostItemInput", + "PostItemResponse", + "Procedure", + "PublishedResult", + "SPBlobMetadataResponse", + "SPContentType", + "SPForASelectedFileResponse", + "SPListEntity", + "SPListExpandedUser", + "SPListItemAttachment", + "SetApprovalStatusOutput", + "SharePointHttpRequestBodyParameters", + "SharePointIds", + "SharingInvitation", + "SharingLink", + "SharingLinkPermission", + "SharingLinkPermissionIdentitySet", + "SharingLinkUserPermissionIdentity", + "SubmitDocGenFormInput", + "Table", + "TableCapabilitiesMetadata", + "TableCountRestrictionsMetadata", + "TableFilterRestrictionsMetadata", + "TableForm", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TablesList", + "TabularDataSetsMetadata", + "UserPermissionIdentity", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class SharepointonlineClient(ConnectorClientBase): + """Typed client for sharepointonline connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a SharepointonlineClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "sharepointonline" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_agreements_solution_document( + self, + input: CreateAgreementsSolutionDocumentInput | Mapping[str, Any], + dataset: str, + template: str, + *, + document_name: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Agreements Solution - Generate document within Agreements Solution + workspace + + Use this action to create documents based on modern templates in a + Agreements Solution workspace. This is behind a payment wall currently + in planning (either license or PayG). + + Swagger operation ID: `CreateAgreementsSolutionDocument`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + template: Agreements Solution template. + document_name: Document file name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/agreements" + f"/templates" + f"/{quote(quote(str(template), safe=''), safe='')}" + f"/createnewdocument" + ) + query_params = [] + if document_name is not None: + value = str(document_name) + if isinstance(document_name, bool): + value = value.lower() + query_params.append(f"documentName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_all_tables( + self, + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get all lists and libraries + + Get all lists and libraries. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAllTables`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/alltables" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def approve_hub_site_join( + self, + dataset: str, + joining_site_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Approve hub site join request + + Approve hub site join request. This will return an approval token that + can be used to complete the join request using the join hub site + action. + + Swagger operation ID: `ApproveHubSiteJoin`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + joining_site_id: Id of the requesting site. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/approvehubsitejoin" + ) + query_params = [] + value = str(joining_site_id) + if isinstance(joining_site_id, bool): + value = value.lower() + query_params.append(f"joiningSiteId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def cancel_hub_site_join_approval( + self, + dataset: str, + *, + approval_correlation_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Cancel hub site join request + + Cancel hub join request. If applicable, you should specify the same + Approval Correlation Id as used in the \"Set hub site join status to + pending\" action. + + Swagger operation ID: `CancelHubSiteJoinApproval`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + approval_correlation_id: Approval correlation identifier for this + request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/cancelhubsitejoinapproval" + ) + query_params = [] + if approval_correlation_id is not None: + value = str(approval_correlation_id) + if isinstance(approval_correlation_id, bool): + value = value.lower() + query_params.append(f"approvalCorrelationId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def create_sharing_link( + self, + input: ItemPermissionCreateLinkBody | Mapping[str, Any], + dataset: str, + table: str, + id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create sharing link for a file or folder + + Create sharing link for a file or folder. + + Swagger operation ID: `CreateSharingLink`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + id: Id of the file or folder item. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/codeless" + f"/_api" + f"/v2.0" + f"/sites" + f"/root" + f"/lists" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/driveItem" + f"/createLink" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def copy_file( + self, + dataset: str, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Copy file (deprecated) + + Copies a file to a SharePoint site. + + Swagger operation ID: `CopyFile`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + source: Path to the source file. + destination: Path to the destination file. + overwrite: Whether or not to overwrite the destination file if it + exists. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/copyFile" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def copy_file_2( + self, + input: CopyFileParameters | Mapping[str, Any], + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Copy file + + Copies a file. Works in a similar way to the \"Copy to\" command in + SharePoint libraries. Returns information about the new file after + copy. + + Swagger operation ID: `CopyFileAsync`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/copyFileAsync" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def copy_folder( + self, + input: CopyFolderParameters | Mapping[str, Any], + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Copy folder + + Copies a folder. Works in a similar way to the \"Copy to\" command in + SharePoint libraries. Returns information about the new folder after + copy. + + Swagger operation ID: `CopyFolderAsync`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/copyFolderAsync" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_file( + self, + input: bytes, + dataset: str, + folder_path: str, + name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create file + + Uploads a file to a SharePoint site. Make sure to pick an existing + library. + + Swagger operation ID: `CreateFile`. + + Args: + input: The binary request body. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + folder_path: Must start with an existing library. Add folders if + needed. + name: Name of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/{quote(quote(str(dataset), safe=''), safe='')}/files" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_file_metadata( + self, + dataset: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file metadata + + Gets information about the file such as size, etag, created date, etc. + Uses a file identifier to pick the file. Use \"Get file properties\" + action to get to the values stored in the columns in the library. + + Swagger operation ID: `GetFileMetadata`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + id: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/files" + f"/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_file( + self, + input: bytes, + dataset: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update file + + Updates the contents of the file specified by the file identifier. + + Swagger operation ID: `UpdateFile`. + + Args: + input: The binary request body. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + id: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/files" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PUT", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_file( + self, + dataset: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete file + + Deletes the file specified by the file identifier. + + Swagger operation ID: `DeleteFile`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + id: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/files" + f"/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_file_content( + self, + dataset: str, + id: str, + *, + infer_content_type: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file content + + Gets file contents using the file identifier. The contents can be + copied somewhere else, or be used as an attachment. + + Swagger operation ID: `GetFileContent`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + id: Select a file. + infer_content_type: Infer content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/files" + f"/{quote(str(id), safe='')}" + f"/content" + ) + query_params = [] + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def get_file_thumbnail( + self, + dataset: str, + id: str, + size: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file thumbnail + + Gets the thumbnail of a file by its file identifier. + + Swagger operation ID: `GetFileThumbnail`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + id: Select a file. + size: The size of the thumbnail to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/files" + f"/{quote(str(id), safe='')}" + f"/thumbnail" + ) + query_params = [] + value = str(size) + if isinstance(size, bool): + value = value.lower() + query_params.append(f"size={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + def list_root_folder( + self, + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List root folder + + Returns files in the root SharePoint folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListRootFolder`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/{quote(quote(str(dataset), safe=''), safe='')}/folders" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_folder( + self, + dataset: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List folder + + Returns files contained in a SharePoint folder. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListFolder`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + id: Unique identifier of the folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/folders" + f"/{quote(str(id), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_file_metadata_by_path( + self, + dataset: str, + path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file metadata using path + + Gets information about the file such as size, etag, created date, etc. + Uses a file path to pick the file. Use \"Get file properties\" action + to get to the values stored in the columns in the library. + + Swagger operation ID: `GetFileMetadataByPath`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + path: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/GetFileByPath" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_file_content_by_path( + self, + dataset: str, + path: str, + *, + infer_content_type: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get file content using path + + Gets file contents using the file path. + + Swagger operation ID: `GetFileContentByPath`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + path: Select a file. + infer_content_type: Infer content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/GetFileContentByPath" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if infer_content_type is not None: + value = str(infer_content_type) + if isinstance(infer_content_type, bool): + value = value.lower() + query_params.append(f"inferContentType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def get_folder_metadata( + self, + dataset: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get folder metadata + + Gets information about the folder. Uses a file identifier to pick the + folder. + + Swagger operation ID: `GetFolderMetadata`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + id: Select a folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/GetFolder" + ) + query_params = [] + value = str(id) + if isinstance(id, bool): + value = value.lower() + query_params.append(f"id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_folder_metadata_by_path( + self, + dataset: str, + path: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get folder metadata using path + + Gets information about the folder. Uses a folder path to pick the + folder. + + Swagger operation ID: `GetFolderMetadataByPath`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + path: Select a folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/GetFolderByPath" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(path) + if isinstance(path, bool): + value = value.lower() + query_params.append(f"path={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def http_request( + self, + input: SharePointHttpRequestBodyParameters | Mapping[str, Any], + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Send an HTTP request to SharePoint + + Construct a SharePoint REST API to invoke. Note - This action may + execute any SharePoint REST API you have access to. Please proceed with + caution. + + Swagger operation ID: `HttpRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/httprequest" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def join_hub_site( + self, + dataset: str, + hub_site_id: str, + *, + approval_token: Optional[str] = None, + approval_correlation_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Join hub site + + Join the requested site to the hub site. An Approval Token is required + to complete the join successfully if that hub requires approval. If + applicable, you should specify the same Approval Correlation Id as used + in the \"Set hub site join status to pending\" action. + + Swagger operation ID: `JoinHubSite`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + hub_site_id: Id of the hub site. + approval_token: Approval token for this request. + approval_correlation_id: Approval correlation identifier for this + request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/joinhubsite" + ) + query_params = [] + value = str(hub_site_id) + if isinstance(hub_site_id, bool): + value = value.lower() + query_params.append(f"hubSiteId={quote(value, safe='')}") + if approval_token is not None: + value = str(approval_token) + if isinstance(approval_token, bool): + value = value.lower() + query_params.append(f"approvalToken={quote(value, safe='')}") + if approval_correlation_id is not None: + value = str(approval_correlation_id) + if isinstance(approval_correlation_id, bool): + value = value.lower() + query_params.append(f"approvalCorrelationId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def move_file( + self, + input: MoveFileParameters | Mapping[str, Any], + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Move file + + Moves a file. Works in a similar way to the \"Move to\" command in + SharePoint libraries. Returns information about the new file after + move. + + Swagger operation ID: `MoveFileAsync`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/moveFileAsync" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def move_folder( + self, + input: MoveFolderParameters | Mapping[str, Any], + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Move folder + + Moves a folder. Works in a similar way to the \"Move to\" command in + SharePoint libraries. Returns information about the new folder after + move. + + Swagger operation ID: `MoveFolderAsync`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/moveFolderAsync" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def notify_hub_site_join_approval_started( + self, + dataset: str, + *, + approval_correlation_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Set hub site join status to pending + + Set the requested site's hub join request status to pending. The + Approval Correlation Id is an optional parameter that helps SharePoint + identify a particular hub join request. The requesting site can only + have one pending request at a given time. + + Swagger operation ID: `NotifyHubSiteJoinApprovalStarted`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + approval_correlation_id: Approval correlation identifier for this + request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/notifyhubsitejoinapprovalstarted" + ) + query_params = [] + if approval_correlation_id is not None: + value = str(approval_correlation_id) + if isinstance(approval_correlation_id, bool): + value = value.lower() + query_params.append(f"approvalCorrelationId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_tables( + self, + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get lists + + Gets SharePoint lists from a site. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTables`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets/{quote(quote(str(dataset), safe=''), safe='')}/tables" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_new_document_set( + self, + input: CreateNewDocumentSetParameters | Mapping[str, Any], + dataset: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create new document set + + Creates a new document set list item. + + Swagger operation ID: `CreateNewDocumentSet`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/createnewdocumentset" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_new_folder( + self, + input: CreateNewFolderParameters | Mapping[str, Any], + dataset: str, + table: str, + *, + view: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create new folder + + Creates a new folder or folder path. + + Swagger operation ID: `CreateNewFolder`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list or library name. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/createnewfolder" + ) + query_params = [] + if view is not None: + value = str(view) + if isinstance(view, bool): + value = value.lower() + query_params.append(f"view={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def search_for_user( + self, + dataset: str, + table: str, + entity_id: str, + search_value: str, + *, + view: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Resolve person + + Returns a single matching user value so it can be assigned to a column + of type person. If there are no matches, or multiple matches, this + action will error out. + + Swagger operation ID: `SearchForUser`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: Pick the list or library that the column is in. + entity_id: Pick the column you want to assign the value to. + search_value: Use the email address, or the full name of the user. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/entities" + f"/{quote(quote(str(entity_id), safe=''), safe='')}" + f"/searchforuser" + ) + query_params = [] + value = str(search_value) + if isinstance(search_value, bool): + value = value.lower() + query_params.append(f"searchValue={quote(value, safe='')}") + if view is not None: + value = str(view) + if isinstance(view, bool): + value = value.lower() + query_params.append(f"view={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_table_form( + self, + dataset: str, + table: str, + form: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get form metadata (preview) + + Use this action to get the form metadata, which includes the form ID, + title, link, form type, and the output format. It also gets the form + questions used to collect information. Document generation forms is a + part of AI in SharePoint Public Preview. For more info on getting + started, see: + https://learn.microsoft.com/sharepoint/dev/declarative-customization/structured-documents. + + Swagger operation ID: `GetTableForm`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + form: Form identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/forms" + f"/{quote(quote(str(form), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def submit_doc_gen_form( + self, + input: SubmitDocGenFormInput | Mapping[str, Any], + dataset: str, + table: str, + form: str, + *, + view: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Generate a document from a form (preview) + + Use this action to create documents from a document generation + template. Map the template fields to the corresponding content in the + data source. Document generation forms is a part of AI in SharePoint + Public Preview. For more info on getting started, see: + https://learn.microsoft.com/sharepoint/dev/declarative-customization/structured-documents. + + Swagger operation ID: `SubmitDocGenForm`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint document library name. + form: Form identifier. + view: This parameter does nothing. Please do not use. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/forms" + f"/{quote(quote(str(form), safe=''), safe='')}" + f"/submitdocgenform" + ) + query_params = [] + if view is not None: + value = str(view) + if isinstance(view, bool): + value = value.lower() + query_params.append(f"view={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_file_items( + self, + dataset: str, + table: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + folder_path: Optional[str] = None, + view_scope_option: Optional[str] = None, + view: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get files (properties only) + + Gets the properties saved in the columns in the library for all folders + and files stored in the library. You can also filter down to the items + that match a condition. An \"Apply to each\" section is usually used to + work with the output from this action. When using this with the + On-Premises Data Gateway, the name of the library to connect to may + need to be entered manually. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetFileItems`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + folder_path: Select a folder, or leave blank for the whole library. + view_scope_option: Return entries contained in sub-folders (default + = true). + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/getfileitems" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if folder_path is not None: + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + if view_scope_option is not None: + value = str(view_scope_option) + if isinstance(view_scope_option, bool): + value = value.lower() + query_params.append(f"viewScopeOption={quote(value, safe='')}") + if view is not None: + value = str(view) + if isinstance(view, bool): + value = value.lower() + query_params.append(f"view={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_items( + self, + dataset: str, + table: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + folder_path: Optional[str] = None, + view_scope_option: Optional[str] = None, + view: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get items + + Gets items from a SharePoint list. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItems`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + folder_path: Select a folder, or leave blank for the whole list. + view_scope_option: Return entries contained in sub-folders (default + = true). + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if folder_path is not None: + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + if view_scope_option is not None: + value = str(view_scope_option) + if isinstance(view_scope_option, bool): + value = value.lower() + query_params.append(f"viewScopeOption={quote(value, safe='')}") + if view is not None: + value = str(view) + if isinstance(view, bool): + value = value.lower() + query_params.append(f"view={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def post_item( + self, + input: PostItemInput | Mapping[str, Any], + dataset: str, + table: str, + *, + view: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create item + + Creates a new item in a SharePoint list. + + Swagger operation ID: `PostItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + query_params = [] + if view is not None: + value = str(view) + if isinstance(view, bool): + value = value.lower() + query_params.append(f"view={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_item( + self, + dataset: str, + table: str, + id: int, + *, + view: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get item + + Gets a single item by its id from a SharePoint list. + + Swagger operation ID: `GetItem`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + id: Unique identifier of item to be retrieved. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(str(id), safe='')}" + ) + query_params = [] + if view is not None: + value = str(view) + if isinstance(view, bool): + value = value.lower() + query_params.append(f"view={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_item( + self, + dataset: str, + table: str, + id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete item + + Deletes an item from a SharePoint list. + + Swagger operation ID: `DeleteItem`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + id: Unique identifier of item to be deleted. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def patch_item( + self, + input: PatchItemInput | Mapping[str, Any], + dataset: str, + table: str, + id: int, + *, + view: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update item + + Updates an item in a SharePoint list. + + Swagger operation ID: `PatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + id: Unique identifier of item to be updated. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(str(id), safe='')}" + ) + query_params = [] + if view is not None: + value = str(view) + if isinstance(view, bool): + value = value.lower() + query_params.append(f"view={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_approval_request( + self, + input: CreateApprovalRequestInput | Mapping[str, Any], + dataset: str, + table: str, + id: int, + approval_type: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create an approval request for an item or file + + Creates an approval request for an item or file. + + Swagger operation ID: `CreateApprovalRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list or library name. + id: Id of the item the approval request is being created for. + approval_type: Select an approval type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/approval" + ) + query_params = [] + value = str(approval_type) + if isinstance(approval_type, bool): + value = value.lower() + query_params.append(f"approvalType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_item_changes( + self, + dataset: str, + table: str, + id: int, + since: str, + *, + until: Optional[str] = None, + include_drafts: Optional[bool] = None, + view: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get changes for an item or a file (properties only) + + Returns information about columns that have changed within a given time + window. Note: The list must have Versioning turned on. + + Swagger operation ID: `GetItemChanges`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list or library name. + id: Id of the item you want to fetch changes for. + since: Trigger Window Start token or an item version label (ex: + 3.0) or an ISO 8601 date (YYYY-MM-DDThh:mmZ). + until: Trigger Window End token or an item version label (ex: 3.0) + or an ISO 8601 date (YYYY-MM-DDThh:mmZ). If blank, defaults to + latest version. + include_drafts: Boolean for whether to consider changes from minor + (draft) versions. + view: Returns only columns defined in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/changes" + ) + query_params = [] + value = str(since) + if isinstance(since, bool): + value = value.lower() + query_params.append(f"since={quote(value, safe='')}") + if until is not None: + value = str(until) + if isinstance(until, bool): + value = value.lower() + query_params.append(f"until={quote(value, safe='')}") + if include_drafts is not None: + value = str(include_drafts) + if isinstance(include_drafts, bool): + value = value.lower() + query_params.append(f"includeDrafts={quote(value, safe='')}") + if view is not None: + value = str(view) + if isinstance(view, bool): + value = value.lower() + query_params.append(f"view={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def check_in_file( + self, + input: FileCheckInParameters | Mapping[str, Any], + dataset: str, + table: str, + id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Check in file + + Check in a checked out file in a document library, which makes the + version of the document available to others. + + Swagger operation ID: `CheckInFile`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + id: Id of the list item the file is attached to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/checkinfile" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def check_out_file( + self, + dataset: str, + table: str, + id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Check out file + + Check out a file in a document library to prevent others from editing + the document, and your changes from being visible until the documented + is checked in. + + Swagger operation ID: `CheckOutFile`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + id: Id of the list item the file is attached to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/checkoutfile" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def discard_file_check_out( + self, + dataset: str, + table: str, + id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Discard check out + + If you check out a file and don't make changes to it, or you make + changes that you don't want to keep, you can simply discard the + checkout, rather than saving the file. If your organization tracks + versions, a new version is created each time you check a file back into + the library. By discarding the checkout, you can avoid making new + versions when you haven't made any changes to the file. + + Swagger operation ID: `DiscardFileCheckOut`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + id: Id of the list item the file is attached to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/discardfilecheckout" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_file_item( + self, + dataset: str, + table: str, + id: int, + *, + view: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get file properties + + Gets the properties saved in the columns in the library for the item + specified by the item id. You can add a \"Get file content\" step and + use the \"File identifier\" property returned by this action to get to + the contents of the file. When using this with the On-Premises Data + Gateway, the name of the library to connect to may need to be entered + manually. + + Swagger operation ID: `GetFileItem`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + id: Unique identifier of item to be retrieved. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(str(id), safe='')}" + f"/getfileitem" + ) + query_params = [] + if view is not None: + value = str(view) + if isinstance(view, bool): + value = value.lower() + query_params.append(f"view={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def grant_access( + self, + input: ItemGrantAccessBody | Mapping[str, Any], + dataset: str, + table: str, + id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Grant access to an item or a folder + + Grant access to an item or a folder in SharePoint to specific people. + + Swagger operation ID: `GrantAccess`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list or library name. + id: Unique identifier of the item or folder you want to grant + access to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/grantaccess" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def patch_file_item( + self, + input: PatchFileItemInput | Mapping[str, Any], + dataset: str, + table: str, + id: int, + *, + view: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update file properties + + Updates the properties stored in columns in a library for the item + specified by the item id. Use \"Update file\" action to update file + contents. When using this with the On-Premises Data Gateway, the name + of the library to connect to may need to be entered manually. + + Swagger operation ID: `PatchFileItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + id: Unique identifier of item to be updated. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(str(id), safe='')}" + f"/patchfileitem" + ) + query_params = [] + if view is not None: + value = str(view) + if isinstance(view, bool): + value = value.lower() + query_params.append(f"view={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def patch_file_item_with_predicted_values( + self, + input: PatchFileItemWithPredictedValuesParameters | Mapping[str, Any], + dataset: str, + table: str, + id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update file properties using AI Builder model results + + Updates the values stored in library columns for a file analyzed by the + model specified by the ModelId. + + Swagger operation ID: `PatchFileItemWithPredictedValues`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: Library Name. + id: Unique identifier of item to be updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(str(id), safe='')}" + f"/patchfileitemwithpredictedvalues" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def set_approval_status( + self, + dataset: str, + table: str, + id: int, + approval_action: str, + *, + comments: Optional[str] = None, + entity_tag: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Set content approval status + + Sets the content approval status for an item in a list or library that + has content approval turned on. You must provide an ETag for pages and + files. You can get the ETag using the Get File Metadata action. This + action is only available for SharePoint Online and SharePoint 2019. + + Swagger operation ID: `SetApprovalStatus`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + id: Id of the item you are setting the status of. + approval_action: Pick the approval action. + comments: Add the comments from the approver. + entity_tag: Add an ETag (required for files and pages). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/setapprovalstatus" + ) + query_params = [] + value = str(approval_action) + if isinstance(approval_action, bool): + value = value.lower() + query_params.append(f"approvalAction={quote(value, safe='')}") + if comments is not None: + value = str(comments) + if isinstance(comments, bool): + value = value.lower() + query_params.append(f"comments={quote(value, safe='')}") + if entity_tag is not None: + value = str(entity_tag) + if isinstance(entity_tag, bool): + value = value.lower() + query_params.append(f"entityTag={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def unshare_item( + self, + dataset: str, + table: str, + id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Stop sharing an item or a file + + Delete all links giving access to an item or a file and remove all + people with direct access except for owners. + + Swagger operation ID: `UnshareItem`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list or library name. + id: Unique identifier of the item or file you want to stop sharing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + f"/unshare" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_item_attachments( + self, + dataset: str, + table: str, + item_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get attachments + + Returns the list of attachments for the specified list item. You can + add a \"Get attachment content\" step and use the \"File identifier\" + property returned by this action to get to the contents of the file. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItemAttachments`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + item_id: Id of the list item to get attachments from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(item_id), safe=''), safe='')}" + f"/attachments" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_attachment( + self, + input: bytes, + dataset: str, + table: str, + item_id: int, + display_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add attachment + + Adds a new attachment to the specified list item. + + Swagger operation ID: `CreateAttachment`. + + Args: + input: The binary request body. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + item_id: Id of the list item to attach the file to. + display_name: File name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(item_id), safe=''), safe='')}" + f"/attachments" + ) + query_params = [] + value = str(display_name) + if isinstance(display_name, bool): + value = value.lower() + query_params.append(f"displayName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_attachment( + self, + dataset: str, + table: str, + item_id: int, + attachment_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete attachment + + Deletes the specified attachment. + + Swagger operation ID: `DeleteAttachment`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + item_id: Id of the list item the file is attached to. + attachment_id: File identifier for the attachment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(item_id), safe=''), safe='')}" + f"/attachments" + f"/{quote(str(attachment_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_attachment_content( + self, + dataset: str, + table: str, + item_id: int, + attachment_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get attachment content + + Returns file contents using the file identifier. The contents can be + copied somewhere else, or be used as an attachment. + + Swagger operation ID: `GetAttachmentContent`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + item_id: Id of the list item the file is attached to. + attachment_id: File identifier for the attachment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(item_id), safe=''), safe='')}" + f"/attachments" + f"/{quote(str(attachment_id), safe='')}" + f"/$value" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def create_content_assembly_document( + self, + input: CreateContentAssemblyDocumentInput | Mapping[str, Any], + dataset: str, + table: str, + template: str, + *, + folder_path: Optional[str] = None, + file_name: Optional[str] = None, + view: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Generate document using Microsoft Syntex (preview) + + Use this action to create documents based on modern templates from + Microsoft Syntex. This preview requires a Syntex license. Pricing is + subject to change. For more info see: + https://docs.microsoft.com/en-us/microsoft-365/contentunderstanding/content-assembly. + + Swagger operation ID: `CreateContentAssemblyDocument`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint document library name. + template: Document template. + folder_path: Must start with an existing library. + file_name: Document file name. + view: This parameter does nothing. Please do not use. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/templates" + f"/{quote(quote(str(template), safe=''), safe='')}" + f"/createnewdocument" + ) + query_params = [] + if folder_path is not None: + value = str(folder_path) + if isinstance(folder_path, bool): + value = value.lower() + query_params.append(f"folderPath={quote(value, safe='')}") + if file_name is not None: + value = str(file_name) + if isinstance(file_name, bool): + value = value.lower() + query_params.append(f"fileName={quote(value, safe='')}") + if view is not None: + value = str(view) + if isinstance(view, bool): + value = value.lower() + query_params.append(f"view={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_table_views( + self, + dataset: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get list views + + Gets views from a SharePoint list. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTableViews`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/views" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def extract_folder( + self, + dataset: str, + source: str, + destination: str, + *, + overwrite: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Extract folder + + Extracts an archive file into a SharePoint folder (example: .zip). + + Swagger operation ID: `ExtractFolderV2`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + source: Path to the source file. + destination: Path to the destination folder. + overwrite: Whether or not to overwrite the destination file if it + exists. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/extractFolderV2" + ) + query_params = [] + query_params.append("queryParametersSingleEncoded=" + quote("true", safe='')) + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(destination) + if isinstance(destination, bool): + value = value.lower() + query_params.append(f"destination={quote(value, safe='')}") + if overwrite is not None: + value = str(overwrite) + if isinstance(overwrite, bool): + value = value.lower() + query_params.append(f"overwrite={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_data_sets( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get datasets + + Gets the most recently used SharePoint sites. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetDataSets`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/datasets" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_agreements_solution_templates( + self, + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Agreements Solution - Get Templates + + Gets templates from a Agreements Solution workspace. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAgreementsSolutionTemplates`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/agreements" + f"/templates" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_agreements_solution_template_fields( + self, + dataset: str, + template: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Agreements Solution - Get template fields + + Gets fields from template in a Agreements Solution workspace. + + Swagger operation ID: `GetAgreementsSolutionTemplateFields`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + template: Agreements Solution template. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/agreements" + f"/templates" + f"/{quote(quote(str(template), safe=''), safe='')}" + f"/fields" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tables_for_libraries( + self, + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get libraries + + Get libraries + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTablesForLibraries`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tablesfor" + f"/libraries" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_thumbnail_size_options( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get thumbnail size options + + Internal operation to get thumbnail size options. + + Swagger operation ID: `GetThumbnailSizeOptions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/getThumbnailSizeOptions" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_table( + self, + dataset: str, + table: str, + *, + view: Optional[str] = None, + content_type_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get list metadata + + Gets metadata from a SharePoint list. + + Swagger operation ID: `GetTable`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + view: Avoid column threshold issues by only using columns defined + in a view. + content_type_id: Contentype Id to filter columns by content type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/$metadata.json" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + ) + query_params = [] + if view is not None: + value = str(view) + if isinstance(view, bool): + value = value.lower() + query_params.append(f"view={quote(value, safe='')}") + if content_type_id is not None: + value = str(content_type_id) + if isinstance(content_type_id, bool): + value = value.lower() + query_params.append(f"contentTypeId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tables_for_lists_and_libraries( + self, + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get lists and libraries + + Get lists and libraries + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTablesForListsAndLibraries`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tablesfor" + f"/listsandlibraries" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_entities_for_user( + self, + dataset: str, + table: str, + *, + view: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Returns User fields for a list + + Returns User fields for a list. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetEntitiesForUser`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/entitiesfor" + f"/user" + ) + query_params = [] + if view is not None: + value = str(view) + if isinstance(view, bool): + value = value.lower() + query_params.append(f"view={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_table_forms( + self, + dataset: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get list forms + + Gets forms from a SharePoint list. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTableForms`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/forms" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_doc_gen_forms( + self, + dataset: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get document generation forms + + Gets published document generation forms from a SharePoint document + library. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetDocGenForms`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint document library name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/docgenforms" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_doc_gen_form_fields( + self, + dataset: str, + table: str, + form: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get document generation form fields + + Gets fields from a document generation form in a SharePoint list. + + Swagger operation ID: `GetDocGenFormFields`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + form: Form identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/docgenforms" + f"/{quote(quote(str(form), safe=''), safe='')}" + f"/fields" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_view_scope_options( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get SPViewScope options to use for folder querying behavior + + Default - Only query current folder (non-recursive). Return both Files + and Folders. RecursiveAll - Recursively query the folder. Return both + Files and Folders. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetViewScopeOptions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/getViewScopeOptions" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_tables_for_lightweight_approval( + self, + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get lists and libraries where lightweight approvals is enabled + + Get lists and libraries where lightweight approvals is enabled + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTablesForLightweightApproval`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tablesfor" + f"/lightweightapproval" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_approval_types( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get available approval request types + + Internal operation to get the available approval request types. + + Swagger operation ID: `GetApprovalTypes`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/getApprovalTypes" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_approval_schema( + self, + approval_type: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get the appropriate creation schema for the approval request type + + Internal operation to fetch the schema for approval request creation + based on the approval type. + + Swagger operation ID: `GetApprovalSchema`. + + Args: + approval_type: Type of approval request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/getApprovalSchema" + query_params = [] + value = str(approval_type) + if isinstance(approval_type, bool): + value = value.lower() + query_params.append(f"approvalType={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_item_changes_metadata( + self, + dataset: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get metadata about the return type of the GetItemChanges operation + + Get metadata about the return type of the GetItemChanges operation. + + Swagger operation ID: `GetItemChangesMetadata`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list or library name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/$metadata.json" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/changes" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tables_for_approval( + self, + dataset: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get libraries where Content Approval is supported + + Get libraries where Content Approval is supported + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTablesForApproval`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tablesfor" + f"/approval" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_day_of_week_options( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + When to send updates + + Internal operation to get day of week options. + + Swagger operation ID: `GetDayOfWeekOptions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/getDayOfWeekOptions" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_content_assembly_templates( + self, + dataset: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get document library templates + + Gets templates from a SharePoint document library. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetContentAssemblyTemplates`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint document library name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/templates" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_content_assembly_placeholders( + self, + dataset: str, + table: str, + template: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get placeholders from template + + Gets placeholders from template in a SharePoint document library. + + Swagger operation ID: `GetContentAssemblyPlaceholders`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint document library name. + template: Document template. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/{quote(quote(str(dataset), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/templates" + f"/{quote(quote(str(template), safe=''), safe='')}" + f"/placeholders" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/shifts.py b/src/azure/connectors/aio/shifts.py new file mode 100644 index 0000000..6958734 --- /dev/null +++ b/src/azure/connectors/aio/shifts.py @@ -0,0 +1,3141 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# ShiftsClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.shifts import ( + Activities, + CreateShiftRequest, + CreateTimeOffRequest, + DraftOpenShift, + DraftShift, + DraftTimeOff, + EditOpenShiftRequest, + GetAllTeamsResponse, + GetTimeOffReasonsResponse, + ListOfferShiftRequestsResponse, + ListOpenShiftChangeRequestsResponse, + ListOpenShiftsCrossTeamResponse, + ListOpenShiftsResponse, + ListSchedulingGroupsResponse, + ListShiftsCrossTeamResponse, + ListShiftsResponse, + ListSwapShiftsChangeRequestsResponse, + ListTimeOffRequestsResponse, + ListTimesOffCrossTeamResponse, + ListTimesOffResponse, + OfferShiftRequestApproveInput, + OfferShiftRequestApproveResponse, + OfferShiftRequestDeclineInput, + OfferShiftRequestDeclineResponse, + OfferShiftRequestResponse, + OpenShiftChangeRequestApproveInput, + OpenShiftChangeRequestApproveResponse, + OpenShiftChangeRequestDeclineInput, + OpenShiftChangeRequestDeclineResponse, + OpenShiftChangeRequestResponse, + OpenShiftResponse, + ScheduleResponse, + SchedulingGroupInfo, + SchedulingGroupResponse, + SharedOpenShift, + SharedShift, + SharedTimeOff, + ShiftResponse, + Subscription, + SwapShiftsChangeRequestApproveInput, + SwapShiftsChangeRequestApproveResponse, + SwapShiftsChangeRequestDeclineInput, + SwapShiftsChangeRequestDeclineResponse, + SwapShiftsChangeRequestResponse, + TeamInfo, + Theme, + TimeOffRequestApproveInput, + TimeOffRequestApproveResponse, + TimeOffRequestDeclineInput, + TimeOffRequestDeclineResponse, + TimeOffRequestResponse, + TimeOffResponse, + UserInfo, + WebHookRequest, + WebhookNotificationEntity, + WebhookPushResponse, + WebhookPushResponseResourceEntity, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "ShiftsClient", + "Activities", + "CreateShiftRequest", + "CreateTimeOffRequest", + "DraftOpenShift", + "DraftShift", + "DraftTimeOff", + "EditOpenShiftRequest", + "GetAllTeamsResponse", + "GetTimeOffReasonsResponse", + "ListOfferShiftRequestsResponse", + "ListOpenShiftChangeRequestsResponse", + "ListOpenShiftsCrossTeamResponse", + "ListOpenShiftsResponse", + "ListSchedulingGroupsResponse", + "ListShiftsCrossTeamResponse", + "ListShiftsResponse", + "ListSwapShiftsChangeRequestsResponse", + "ListTimeOffRequestsResponse", + "ListTimesOffCrossTeamResponse", + "ListTimesOffResponse", + "OfferShiftRequestApproveInput", + "OfferShiftRequestApproveResponse", + "OfferShiftRequestDeclineInput", + "OfferShiftRequestDeclineResponse", + "OfferShiftRequestResponse", + "OpenShiftChangeRequestApproveInput", + "OpenShiftChangeRequestApproveResponse", + "OpenShiftChangeRequestDeclineInput", + "OpenShiftChangeRequestDeclineResponse", + "OpenShiftChangeRequestResponse", + "OpenShiftResponse", + "ScheduleResponse", + "SchedulingGroupInfo", + "SchedulingGroupResponse", + "SharedOpenShift", + "SharedShift", + "SharedTimeOff", + "ShiftResponse", + "Subscription", + "SwapShiftsChangeRequestApproveInput", + "SwapShiftsChangeRequestApproveResponse", + "SwapShiftsChangeRequestDeclineInput", + "SwapShiftsChangeRequestDeclineResponse", + "SwapShiftsChangeRequestResponse", + "TeamInfo", + "Theme", + "TimeOffRequestApproveInput", + "TimeOffRequestApproveResponse", + "TimeOffRequestDeclineInput", + "TimeOffRequestDeclineResponse", + "TimeOffRequestResponse", + "TimeOffResponse", + "UserInfo", + "WebHookRequest", + "WebhookNotificationEntity", + "WebhookPushResponse", + "WebhookPushResponseResourceEntity", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class ShiftsClient(ConnectorClientBase): + """Typed client for shifts connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a ShiftsClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "shifts" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def get_schedule( + self, + team_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a Schedule's details + + This operation returns details of a Schedule using the Schedule's + unique ID. + + Swagger operation ID: `GetSchedule`. + + Args: + team_id: Add Team ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/teams/{quote(str(team_id), safe='')}/schedule" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_times_off( + self, + team_id: str, + *, + start_time: Optional[str] = None, + end_time: Optional[str] = None, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all Time Off instances in a team + + This operation returns all Time Off instances in a Schedule + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTimesOff`. + + Args: + team_id: Add Team ID. + start_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + end_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + top: Items per page (enable Pagination under .../Settings). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/teams/{quote(str(team_id), safe='')}/schedule/timesoff" + ) + query_params = [] + if start_time is not None: + value = str(start_time) + if isinstance(start_time, bool): + value = value.lower() + query_params.append(f"startTime={quote(value, safe='')}") + if end_time is not None: + value = str(end_time) + if isinstance(end_time, bool): + value = value.lower() + query_params.append(f"endTime={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_time_off( + self, + input: CreateTimeOffRequest | Mapping[str, Any], + team_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a new Time Off instance + + This operation creates a new Time Off instance and assigns it to a + member of the team + + Swagger operation ID: `CreateTimeOff`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/teams/{quote(str(team_id), safe='')}/schedule/timesoff" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_time_off( + self, + team_id: str, + time_off_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a Time Off instance + + This operation returns details for a Time Off using its unique ID. + + Swagger operation ID: `GetTimeOff`. + + Args: + team_id: Add Team ID. + time_off_id: The unique ID of the Time Off. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/timesoff" + f"/{quote(str(time_off_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_time_off( + self, + team_id: str, + time_off_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a Time Off instance + + This operation deletes a Time Off using its unique ID. + + Swagger operation ID: `DeleteTimeOff`. + + Args: + team_id: Add Team ID. + time_off_id: The unique ID of the Time Off. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/timesoff" + f"/{quote(str(time_off_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_shifts( + self, + team_id: str, + *, + start_time: Optional[str] = None, + end_time: Optional[str] = None, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all Shifts in a team + + This operation returns all Shifts assigned to members of a team + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListShifts`. + + Args: + team_id: Add Team ID. + start_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + end_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + top: Items per page (enable Pagination under .../Settings). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/teams/{quote(str(team_id), safe='')}/schedule/shifts" + ) + query_params = [] + if start_time is not None: + value = str(start_time) + if isinstance(start_time, bool): + value = value.lower() + query_params.append(f"startTime={quote(value, safe='')}") + if end_time is not None: + value = str(end_time) + if isinstance(end_time, bool): + value = value.lower() + query_params.append(f"endTime={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_shift( + self, + input: CreateShiftRequest | Mapping[str, Any], + team_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a new Shift + + This operation creates a new Shift and assigns it to a member of the + team + + Swagger operation ID: `CreateShift`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/teams/{quote(str(team_id), safe='')}/schedule/shifts" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_shift( + self, + team_id: str, + shift_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a Shift + + This operation returns details for a Shift using the Shift's unique ID. + + Swagger operation ID: `GetShift`. + + Args: + team_id: Add Team ID. + shift_id: The unique ID of the Shift. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/shifts" + f"/{quote(str(shift_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_shift( + self, + team_id: str, + shift_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a Shift + + This operation deletes a Shift using the Shift's unique ID. + + Swagger operation ID: `DeleteShift`. + + Args: + team_id: Add Team ID. + shift_id: The unique ID of the Shift. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/shifts" + f"/{quote(str(shift_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_open_shifts( + self, + team_id: str, + *, + start_time: Optional[str] = None, + end_time: Optional[str] = None, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all Open Shifts in a team + + This operation returns all Open Shifts in a team. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListOpenShifts`. + + Args: + team_id: Add Team ID. + start_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + end_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + top: Items per page (enable Pagination under .../Settings). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/teams/{quote(str(team_id), safe='')}/schedule/openShifts" + ) + query_params = [] + if start_time is not None: + value = str(start_time) + if isinstance(start_time, bool): + value = value.lower() + query_params.append(f"startTime={quote(value, safe='')}") + if end_time is not None: + value = str(end_time) + if isinstance(end_time, bool): + value = value.lower() + query_params.append(f"endTime={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_open_shift( + self, + input: EditOpenShiftRequest | Mapping[str, Any], + team_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a new Open Shift + + Create a new Open Shift in a Schedule. + + Swagger operation ID: `CreateOpenShift`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/teams/{quote(str(team_id), safe='')}/schedule/openShifts" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_open_shift( + self, + team_id: str, + open_shift_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get an Open Shift + + This operation returns details for an Open Shift. + + Swagger operation ID: `GetOpenShift`. + + Args: + team_id: Add Team ID. + open_shift_id: The unique ID of the Open Shift. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/openShifts" + f"/{quote(str(open_shift_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_open_shift( + self, + input: EditOpenShiftRequest | Mapping[str, Any], + team_id: str, + open_shift_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update an Open Shift + + Update an Open Shift in a Schedule. + + Swagger operation ID: `UpdateOpenShift`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + open_shift_id: The unique ID of the Open Shift. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/openShifts" + f"/{quote(str(open_shift_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_open_shift( + self, + team_id: str, + open_shift_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete an Open Shift + + This operation deletes an Open Shift. + + Swagger operation ID: `DeleteOpenShift`. + + Args: + team_id: Add Team ID. + open_shift_id: The unique ID of the Open Shift. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/openShifts" + f"/{quote(str(open_shift_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_time_off_reasons( + self, + team_id: str, + *, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all Time Off Reasons in a team + + This operation returns the list of Time Off Reasons associated with a + team. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTimeOffReasons`. + + Args: + team_id: Add Team ID. + top: Items per page (enable Pagination under .../Settings). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/timeOffReasons" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_scheduling_groups( + self, + team_id: str, + *, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all Scheduling Groups in a team + + This operation returns all Scheduling Groups in a Schedule. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListSchedulingGroups`. + + Args: + team_id: Add Team ID. + top: Items per page (enable Pagination under .../Settings). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/schedulinggroups" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_scheduling_group( + self, + team_id: str, + scheduling_group_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a Scheduling Group + + This operation returns details for a Scheduling Group using its unique + ID. + + Swagger operation ID: `GetSchedulingGroup`. + + Args: + team_id: Add Team ID. + scheduling_group_id: The unique ID of the Scheduling Group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/schedulinggroups" + f"/{quote(str(scheduling_group_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_time_off_requests( + self, + team_id: str, + *, + top: Optional[int] = None, + state: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all Time Off requests in a team + + This operation returns all Time Off requests in a Schedule. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTimeOffRequests`. + + Args: + team_id: Add Team ID. + top: Items per page (enable Pagination under .../Settings). + state: Request state filter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/timeOffRequests" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if state is not None: + value = str(state) + if isinstance(state, bool): + value = value.lower() + query_params.append(f"state={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_time_off_shift_request( + self, + team_id: str, + time_off_request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a Time Off request + + This operation returns a Time Off request by ID. + + Swagger operation ID: `GetTimeOffShiftRequest`. + + Args: + team_id: Add Team ID. + time_off_request_id: The unique ID of the Time Off request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/timeOffRequests" + f"/{quote(str(time_off_request_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def time_off_request_approve( + self, + input: TimeOffRequestApproveInput | Mapping[str, Any], + team_id: str, + time_off_request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Approve a Time Off request + + This operation allows managers to approve a Time Off request. + + Swagger operation ID: `TimeOffRequestApprove`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + time_off_request_id: The unique ID of the Time Off request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/timeOffRequests" + f"/{quote(str(time_off_request_id), safe='')}" + f"/approve" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def time_off_request_decline( + self, + input: TimeOffRequestDeclineInput | Mapping[str, Any], + team_id: str, + time_off_request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Decline a Time Off request + + This operation allows managers to decline a Time Off request. + + Swagger operation ID: `TimeOffRequestDecline`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + time_off_request_id: The unique ID of the Time Off request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/timeOffRequests" + f"/{quote(str(time_off_request_id), safe='')}" + f"/decline" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_offer_shift_requests( + self, + team_id: str, + *, + top: Optional[int] = None, + state: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all Offer Shift requests in a team + + This operation returns all Offer Shift requests in a Schedule. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListOfferShiftRequests`. + + Args: + team_id: Add Team ID. + top: Items per page (enable Pagination under .../Settings). + state: Request state filter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/offerShiftRequests" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if state is not None: + value = str(state) + if isinstance(state, bool): + value = value.lower() + query_params.append(f"state={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_offer_shift_request( + self, + team_id: str, + offer_shift_request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get an Offer Shift request + + This operation returns an Offer Shift request by ID. + + Swagger operation ID: `GetOfferShiftRequest`. + + Args: + team_id: Add Team ID. + offer_shift_request_id: The unique ID of the Offer Shift request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/offerShiftRequests" + f"/{quote(str(offer_shift_request_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def offer_shift_request_approve( + self, + input: OfferShiftRequestApproveInput | Mapping[str, Any], + team_id: str, + offer_shift_request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Approve an Offer Shift request + + This operation allows recipients/managers to approve an Offer Shift + request. + + Swagger operation ID: `OfferShiftRequestApprove`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + offer_shift_request_id: The unique ID of the Offer Shift request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/offerShiftRequests" + f"/{quote(str(offer_shift_request_id), safe='')}" + f"/approve" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def offer_shift_request_decline( + self, + input: OfferShiftRequestDeclineInput | Mapping[str, Any], + team_id: str, + offer_shift_request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Decline an Offer Shift request + + This operation allows users to decline an Offer Shift request. + + Swagger operation ID: `OfferShiftRequestDecline`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + offer_shift_request_id: The unique ID of the Offer Shift request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/offerShiftRequests" + f"/{quote(str(offer_shift_request_id), safe='')}" + f"/decline" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_swap_shifts_change_requests( + self, + team_id: str, + *, + top: Optional[int] = None, + state: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all Swap Shifts requests in a team + + This operation returns all Swap Shifts requests in a Schedule. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListSwapShiftsChangeRequests`. + + Args: + team_id: Add Team ID. + top: Items per page (enable Pagination under .../Settings). + state: Request state filter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/swapShiftsChangeRequests" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if state is not None: + value = str(state) + if isinstance(state, bool): + value = value.lower() + query_params.append(f"state={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_swap_shifts_change_request( + self, + team_id: str, + swap_shifts_change_request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a Swap Shifts request + + This operation returns a Swap Shifts request by ID. + + Swagger operation ID: `GetSwapShiftsChangeRequest`. + + Args: + team_id: Add Team ID. + swap_shifts_change_request_id: The unique ID of the request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/swapShiftsChangeRequests" + f"/{quote(str(swap_shifts_change_request_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def swap_shifts_change_request_approve( + self, + input: SwapShiftsChangeRequestApproveInput | Mapping[str, Any], + team_id: str, + swap_shifts_change_request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Approve a Swap Shifts request + + This operation allows a user to approve a Swap Shifts request. + + Swagger operation ID: `SwapShiftsChangeRequestApprove`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + swap_shifts_change_request_id: The unique ID of the request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/swapShiftsChangeRequests" + f"/{quote(str(swap_shifts_change_request_id), safe='')}" + f"/approve" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def swap_shifts_change_request_decline( + self, + input: SwapShiftsChangeRequestDeclineInput | Mapping[str, Any], + team_id: str, + swap_shifts_change_request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Decline a Swap Shifts request + + This operation allows users to decline a Swap Shifts request. + + Swagger operation ID: `SwapShiftsChangeRequestDecline`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + swap_shifts_change_request_id: The unique ID of the request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/swapShiftsChangeRequests" + f"/{quote(str(swap_shifts_change_request_id), safe='')}" + f"/decline" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_open_shift_change_requests( + self, + team_id: str, + *, + top: Optional[int] = None, + state: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all Open Shift requests in a team + + This operation returns all Open Shift change requests in a Schedule. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListOpenShiftChangeRequests`. + + Args: + team_id: Add Team ID. + top: Items per page (enable Pagination under .../Settings). + state: Request state filter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/openShiftChangeRequests" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if state is not None: + value = str(state) + if isinstance(state, bool): + value = value.lower() + query_params.append(f"state={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_open_shift_change_request( + self, + team_id: str, + open_shift_change_request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get an Open Shift request + + This operation returns an Open Shift change request by ID. + + Swagger operation ID: `GetOpenShiftChangeRequest`. + + Args: + team_id: Add Team ID. + open_shift_change_request_id: The unique ID of the request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/openShiftChangeRequests" + f"/{quote(str(open_shift_change_request_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def open_shift_change_request_approve( + self, + input: OpenShiftChangeRequestApproveInput | Mapping[str, Any], + team_id: str, + open_shift_change_request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Approve an Open Shift request + + This operation allows managers to approve an Open Shift request. + + Swagger operation ID: `OpenShiftChangeRequestApprove`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + open_shift_change_request_id: The unique ID of the request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/openShiftChangeRequests" + f"/{quote(str(open_shift_change_request_id), safe='')}" + f"/approve" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def open_shift_change_request_decline( + self, + input: OpenShiftChangeRequestDeclineInput | Mapping[str, Any], + team_id: str, + open_shift_change_request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Decline an Open Shift request + + This operation allows managers to decline an Open Shift request. + + Swagger operation ID: `OpenShiftChangeRequestDecline`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + open_shift_change_request_id: The unique ID of the request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/schedule" + f"/openShiftChangeRequests" + f"/{quote(str(open_shift_change_request_id), safe='')}" + f"/decline" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_open_shifts_cross_team( + self, + *, + start_time: Optional[str] = None, + end_time: Optional[str] = None, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all Open Shifts from my teams + + This operation returns Open Shifts that need to be filled from all your + teams. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListOpenShiftsCrossTeam`. + + Args: + start_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + end_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + top: Items per page (enable Pagination under .../Settings). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/beta/me/joinedTeams/getOpenShifts" + ) + query_params = [] + if start_time is not None: + value = str(start_time) + if isinstance(start_time, bool): + value = value.lower() + query_params.append(f"startTime={quote(value, safe='')}") + if end_time is not None: + value = str(end_time) + if isinstance(end_time, bool): + value = value.lower() + query_params.append(f"endTime={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_shifts_cross_team( + self, + *, + start_time: Optional[str] = None, + end_time: Optional[str] = None, + assigned_to_user_name: Optional[str] = None, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all Shifts from my teams + + This operation returns assigned Shifts from all your teams. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListShiftsCrossTeam`. + + Args: + start_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + end_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + assigned_to_user_name: Assigned to user with name. + top: Items per page (enable Pagination under .../Settings). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/beta/me/joinedTeams/getShifts" + ) + query_params = [] + if start_time is not None: + value = str(start_time) + if isinstance(start_time, bool): + value = value.lower() + query_params.append(f"startTime={quote(value, safe='')}") + if end_time is not None: + value = str(end_time) + if isinstance(end_time, bool): + value = value.lower() + query_params.append(f"endTime={quote(value, safe='')}") + if assigned_to_user_name is not None: + value = str(assigned_to_user_name) + if isinstance(assigned_to_user_name, bool): + value = value.lower() + query_params.append(f"assignedToUserName={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_times_off_cross_team( + self, + *, + start_time: Optional[str] = None, + end_time: Optional[str] = None, + assigned_to_user_name: Optional[str] = None, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all Times Off from my teams + + This operation returns times when people are off from all your teams. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTimesOffCrossTeam`. + + Args: + start_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + end_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + assigned_to_user_name: Assigned to user with name. + top: How many times off to fetch. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/beta/me/joinedTeams/getTimesOff" + ) + query_params = [] + if start_time is not None: + value = str(start_time) + if isinstance(start_time, bool): + value = value.lower() + query_params.append(f"startTime={quote(value, safe='')}") + if end_time is not None: + value = str(end_time) + if isinstance(end_time, bool): + value = value.lower() + query_params.append(f"endTime={quote(value, safe='')}") + if assigned_to_user_name is not None: + value = str(assigned_to_user_name) + if isinstance(assigned_to_user_name, bool): + value = value.lower() + query_params.append(f"assignedToUserName={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_all_teams( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List teams + + This operation retrieves a list of all the Teams (Office 365 Groups) + you are a member of. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAllTeams`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/me/joinedTeams" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/signinghub.py b/src/azure/connectors/aio/signinghub.py new file mode 100644 index 0000000..091445a --- /dev/null +++ b/src/azure/connectors/aio/signinghub.py @@ -0,0 +1,6356 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# SigninghubClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.signinghub import ( + AccessAuthentication, + AccessDurationByDate, + AccessDurationByDateResponse, + AccessDurationByDays, + AccessDurationByDaysResponse, + AccessResponse, + AccessSecurityPasswordResponse, + AccessSecuritySmsOtpResponse, + AccessSecurityTOTPResponse, + AccessUpdateRequest, + AddAttachmentResponse, + AddDocumentPackageRequest, + AddFieldResponse, + AddPackageResponse, + AddQrCodeResponse, + ApiBulkSignAction, + ApplyTemplateRequest, + ApproveRequest, + AssignFieldRequest, + AttachmentDownloadAttachmentResponse, + AttachmentFieldResponse, + AttachmentPermissionRequest, + AttachmentPermissionResponse, + Authentication, + AuthenticationPassword, + AuthenticationRequest, + AuthenticationResponse, + AuthenticationSigningResponse, + AuthenticationSigningSmsOtp, + AuthenticationSigningSmsOtpResponse, + AuthenticationSmsOtp, + AutoPlaceFieldRequest, + AutoPlaceFieldsResponse, + BulkSignActionDocumentModel, + BulkSignActionFieldModel, + BulkSignAuthentication, + BulkSignPackagesStatus, + BulkSignRequest, + BulkSignResponse, + BulkSignStatusRequest, + BulkSignStatusResponse, + CertifyPermission, + CertifyPermissionResponse, + CertifyPolicyRequest, + CertifyPolicyResponse, + CertifyResponse, + ChangeServicePlanRequest, + CheckBoxFieldRequest, + CheckBoxFormFillingRequest, + CheckboxFieldResponse, + CollaboratorGroupResponse, + CollaboratorPlaceholderResponse, + CollaboratorResponse, + CollaboratorRole, + CommentFieldRecipientResponse, + CommentFieldResponse, + ContactResponse, + ContactSortBy, + DeclineByDetails, + DeclineRequest, + DeleteDocumentFieldRequest, + DeliveryMethod, + DetailedResponse, + DigitalSignatureFieldRequest, + DigitalSignatureFieldResponse, + DocumentCertifyResponse, + DocumentDetails, + DocumentDetailsResponse, + DocumentLogsActions, + DocumentLogsActionsInformation, + DocumentOwnedBy, + DocumentOwner, + DocumentPackageStatus, + DocumentResponse, + DocumentTemplateResponse, + DocumentType, + DocumentsDownloadDocumentBytesResponse, + DocumentsTemplateResponse, + DropDownFormFillingRequest, + DropdownFieldResponse, + DurationByDate, + DurationByDateResponse, + DurationByDays, + DurationByDaysResponse, + ECCLevelAPI, + EciModeAPI, + ElectronicSealRecipient, + ElectronicSignatureFieldResponse, + EmailDeletedDocument, + EmptyResponse, + EnterpriseAccessResponse, + EnterpriseAccessSecuritySmsOtpResponse, + EnterpriseAuthenticationResponse, + EnterpriseAuthenticationSigningResponse, + EnterpriseAuthenticationSigningSmsOtpResponse, + EnterpriseTemplateResponse, + EnterpriseTemplateRole, + ErrorWithDescriptionResponse, + FieldAuthentication, + FieldDimension, + FieldDimenssionResponse, + FieldResponse, + FieldType, + FieldValidationValue, + FieldValidationValueRule, + FieldsAutoAssignFieldInput, + FieldsResponse, + FolderItemSortBy, + Font, + FontResponse, + FormFillingRequest, + GetAttachmentResponse, + GetPackageDetailsResponse, + GetPackagesResponse, + GroupMemberResponse, + HandSignature, + HandSignatureFieldResponse, + InPersonFieldRequest, + InPersonFieldResponse, + InitialFieldRequest, + InitialFieldResponse, + InitialFillingRequest, + LegalNoticeResponse, + ListBoxFieldResponse, + ListBoxFormFillingRequest, + MoveToRequest, + NextSignerEmail, + NotifyInactiveDeleteUser, + NotifyUnUsedDeleteDocument, + PackageDownloadPackageBytesResponse, + PageResponse, + PermissionAccessDuration, + PermissionAccessDurationResponse, + PermissionLegalNotice, + PermissionLegalNoticeResponse, + PlaceholderRequest, + PostProcessRecipientRequest, + PostProcessRecipientResponse, + PostProcessResponse, + PostProcessUpdateRequest, + QrCodeColor, + QrCodeLogo, + QrCodeOptions, + QrCodeRequest, + QrCodeResponse, + RadioBoxFieldRequest, + RadioFieldResponse, + RadioFormFillingRequest, + RecipientAccessDurationDetails, + RecipientDeclineDetails, + ReminderRepeat, + ReminderResponse, + RenameDocumentPackageRequest, + RenameDocumentRequest, + RepeatRequest, + Response, + ServicePlanAuthenticationProfile, + ServicePlanAutoDeleteDocument, + ServicePlanAutoDeleteUser, + ServicePlanCapacity, + ServicePlanCapacityRequest, + ServicePlanCertifyOption, + ServicePlanElectronicSealServer, + ServicePlanEmailOtp, + ServicePlanEvidenceReport, + ServicePlanLevelOfAssurance, + ServicePlanOneTimePassword, + ServicePlanProfile, + ServicePlanSigningServer, + ServicePlanSmsNotification, + ServicePlanSmsOtp, + ServicePlanSmtpServer, + SignDocumentRequest, + SignDocumentResponse, + SignatureFieldAuthentication, + SignatureFieldAuthenticationOtp, + SignatureFieldAuthenticationTotp, + SignatureFieldResponse, + SigningAuthentication, + SigningServerCapacity, + SigningServerCsp, + SigningServerSignatureAppearance, + StartWorkflowResponse, + TemplateDocumentResponse, + TemplateResponse, + TemplateSmartFormResponse, + TemplateSortBy, + TextBoxFieldRequest, + TextFieldResponse, + TextFormFillingRequest, + TextboxType, + TotpPermissionResponse, + UniqueIdentifierFieldResponse, + UpdateCertifyPolicyRequest, + UpdateCheckBoxFieldRequest, + UpdateCollaboratorResponse, + UpdateDigitalSignatureFieldRequest, + UpdateInPersonFieldRequest, + UpdateInitialFieldRequest, + UpdateQrCodeRequest, + UpdateQrCodeResponse, + UpdateRadioBoxFieldRequest, + UpdateReminderRequest, + UpdateTextBoxFieldRequest, + UpdateWorkSpaceRequest, + UploadDocument, + UploadDocumentLibraryCertifyResponse, + UploadDocumentLibraryResponse, + UploadDocumentLibraryTemplateResponse, + UploadDocumentMetaInfoDetail, + ValidationRule, + VerificationResponse, + WorflowGroupRequest, + WorflowUserRequest, + WorkSpaceMembers, + WorkSpaceOwner, + WorkSpaceResponse, + WorkflowCollaboratorRole, + WorkflowDetailUpdateRequest, + WorkflowDetailsResponse, + WorkflowDocumentsResponse, + WorkflowEvidenceReportDownloadBytesResponse, + WorkflowGatekeeperResponse, + WorkflowGatekeeperUserResponse, + WorkflowHistoryResponse, + WorkflowMode, + WorkflowModes, + WorkflowPermission, + WorkflowPermissionResponse, + WorkflowPermissionsUpdateRequest, + WorkflowPlaceholderUpdateRequest, + WorkflowRecipient, + WorkflowResponse, + WorkflowType, + WorkflowUserReorderRequest, + WorkflowUserResponse, + WorkflowUserUpdateRequest, + WorkflowWorkflowAddGroupInput, + WorkflowWorkflowAddPlaceholderInput, + WorkflowWorkflowAddUserInput, +) + +__all__ = [ + "SigninghubClient", + "AccessAuthentication", + "AccessDurationByDate", + "AccessDurationByDateResponse", + "AccessDurationByDays", + "AccessDurationByDaysResponse", + "AccessResponse", + "AccessSecurityPasswordResponse", + "AccessSecuritySmsOtpResponse", + "AccessSecurityTOTPResponse", + "AccessUpdateRequest", + "AddAttachmentResponse", + "AddDocumentPackageRequest", + "AddFieldResponse", + "AddPackageResponse", + "AddQrCodeResponse", + "ApiBulkSignAction", + "ApplyTemplateRequest", + "ApproveRequest", + "AssignFieldRequest", + "AttachmentDownloadAttachmentResponse", + "AttachmentFieldResponse", + "AttachmentPermissionRequest", + "AttachmentPermissionResponse", + "Authentication", + "AuthenticationPassword", + "AuthenticationRequest", + "AuthenticationResponse", + "AuthenticationSigningResponse", + "AuthenticationSigningSmsOtp", + "AuthenticationSigningSmsOtpResponse", + "AuthenticationSmsOtp", + "AutoPlaceFieldRequest", + "AutoPlaceFieldsResponse", + "BulkSignActionDocumentModel", + "BulkSignActionFieldModel", + "BulkSignAuthentication", + "BulkSignPackagesStatus", + "BulkSignRequest", + "BulkSignResponse", + "BulkSignStatusRequest", + "BulkSignStatusResponse", + "CertifyPermission", + "CertifyPermissionResponse", + "CertifyPolicyRequest", + "CertifyPolicyResponse", + "CertifyResponse", + "ChangeServicePlanRequest", + "CheckBoxFieldRequest", + "CheckBoxFormFillingRequest", + "CheckboxFieldResponse", + "CollaboratorGroupResponse", + "CollaboratorPlaceholderResponse", + "CollaboratorResponse", + "CollaboratorRole", + "CommentFieldRecipientResponse", + "CommentFieldResponse", + "ContactResponse", + "ContactSortBy", + "DeclineByDetails", + "DeclineRequest", + "DeleteDocumentFieldRequest", + "DeliveryMethod", + "DetailedResponse", + "DigitalSignatureFieldRequest", + "DigitalSignatureFieldResponse", + "DocumentCertifyResponse", + "DocumentDetails", + "DocumentDetailsResponse", + "DocumentLogsActions", + "DocumentLogsActionsInformation", + "DocumentOwnedBy", + "DocumentOwner", + "DocumentPackageStatus", + "DocumentResponse", + "DocumentTemplateResponse", + "DocumentType", + "DocumentsDownloadDocumentBytesResponse", + "DocumentsTemplateResponse", + "DropDownFormFillingRequest", + "DropdownFieldResponse", + "DurationByDate", + "DurationByDateResponse", + "DurationByDays", + "DurationByDaysResponse", + "ECCLevelAPI", + "EciModeAPI", + "ElectronicSealRecipient", + "ElectronicSignatureFieldResponse", + "EmailDeletedDocument", + "EmptyResponse", + "EnterpriseAccessResponse", + "EnterpriseAccessSecuritySmsOtpResponse", + "EnterpriseAuthenticationResponse", + "EnterpriseAuthenticationSigningResponse", + "EnterpriseAuthenticationSigningSmsOtpResponse", + "EnterpriseTemplateResponse", + "EnterpriseTemplateRole", + "ErrorWithDescriptionResponse", + "FieldAuthentication", + "FieldDimension", + "FieldDimenssionResponse", + "FieldResponse", + "FieldType", + "FieldValidationValue", + "FieldValidationValueRule", + "FieldsAutoAssignFieldInput", + "FieldsResponse", + "FolderItemSortBy", + "Font", + "FontResponse", + "FormFillingRequest", + "GetAttachmentResponse", + "GetPackageDetailsResponse", + "GetPackagesResponse", + "GroupMemberResponse", + "HandSignature", + "HandSignatureFieldResponse", + "InPersonFieldRequest", + "InPersonFieldResponse", + "InitialFieldRequest", + "InitialFieldResponse", + "InitialFillingRequest", + "LegalNoticeResponse", + "ListBoxFieldResponse", + "ListBoxFormFillingRequest", + "MoveToRequest", + "NextSignerEmail", + "NotifyInactiveDeleteUser", + "NotifyUnUsedDeleteDocument", + "PackageDownloadPackageBytesResponse", + "PageResponse", + "PermissionAccessDuration", + "PermissionAccessDurationResponse", + "PermissionLegalNotice", + "PermissionLegalNoticeResponse", + "PlaceholderRequest", + "PostProcessRecipientRequest", + "PostProcessRecipientResponse", + "PostProcessResponse", + "PostProcessUpdateRequest", + "QrCodeColor", + "QrCodeLogo", + "QrCodeOptions", + "QrCodeRequest", + "QrCodeResponse", + "RadioBoxFieldRequest", + "RadioFieldResponse", + "RadioFormFillingRequest", + "RecipientAccessDurationDetails", + "RecipientDeclineDetails", + "ReminderRepeat", + "ReminderResponse", + "RenameDocumentPackageRequest", + "RenameDocumentRequest", + "RepeatRequest", + "Response", + "ServicePlanAuthenticationProfile", + "ServicePlanAutoDeleteDocument", + "ServicePlanAutoDeleteUser", + "ServicePlanCapacity", + "ServicePlanCapacityRequest", + "ServicePlanCertifyOption", + "ServicePlanElectronicSealServer", + "ServicePlanEmailOtp", + "ServicePlanEvidenceReport", + "ServicePlanLevelOfAssurance", + "ServicePlanOneTimePassword", + "ServicePlanProfile", + "ServicePlanSigningServer", + "ServicePlanSmsNotification", + "ServicePlanSmsOtp", + "ServicePlanSmtpServer", + "SignDocumentRequest", + "SignDocumentResponse", + "SignatureFieldAuthentication", + "SignatureFieldAuthenticationOtp", + "SignatureFieldAuthenticationTotp", + "SignatureFieldResponse", + "SigningAuthentication", + "SigningServerCapacity", + "SigningServerCsp", + "SigningServerSignatureAppearance", + "StartWorkflowResponse", + "TemplateDocumentResponse", + "TemplateResponse", + "TemplateSmartFormResponse", + "TemplateSortBy", + "TextBoxFieldRequest", + "TextFieldResponse", + "TextFormFillingRequest", + "TextboxType", + "TotpPermissionResponse", + "UniqueIdentifierFieldResponse", + "UpdateCertifyPolicyRequest", + "UpdateCheckBoxFieldRequest", + "UpdateCollaboratorResponse", + "UpdateDigitalSignatureFieldRequest", + "UpdateInPersonFieldRequest", + "UpdateInitialFieldRequest", + "UpdateQrCodeRequest", + "UpdateQrCodeResponse", + "UpdateRadioBoxFieldRequest", + "UpdateReminderRequest", + "UpdateTextBoxFieldRequest", + "UpdateWorkSpaceRequest", + "UploadDocument", + "UploadDocumentLibraryCertifyResponse", + "UploadDocumentLibraryResponse", + "UploadDocumentLibraryTemplateResponse", + "UploadDocumentMetaInfoDetail", + "ValidationRule", + "VerificationResponse", + "WorflowGroupRequest", + "WorflowUserRequest", + "WorkSpaceMembers", + "WorkSpaceOwner", + "WorkSpaceResponse", + "WorkflowCollaboratorRole", + "WorkflowDetailUpdateRequest", + "WorkflowDetailsResponse", + "WorkflowDocumentsResponse", + "WorkflowEvidenceReportDownloadBytesResponse", + "WorkflowGatekeeperResponse", + "WorkflowGatekeeperUserResponse", + "WorkflowHistoryResponse", + "WorkflowMode", + "WorkflowModes", + "WorkflowPermission", + "WorkflowPermissionResponse", + "WorkflowPermissionsUpdateRequest", + "WorkflowPlaceholderUpdateRequest", + "WorkflowRecipient", + "WorkflowResponse", + "WorkflowType", + "WorkflowUserReorderRequest", + "WorkflowUserResponse", + "WorkflowUserUpdateRequest", + "WorkflowWorkflowAddGroupInput", + "WorkflowWorkflowAddPlaceholderInput", + "WorkflowWorkflowAddUserInput", +] + + +# Type Definitions + +# Client Class + +class SigninghubClient(ConnectorClientBase): + """Typed client for signinghub connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a SigninghubClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "signinghub" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def attachment_delete_attachment( + self, + package_id: int, + document_id: int, + attachment_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete Attachment + + Business applications can use this service API to delete the attachment + of a document. + + Swagger operation ID: `V4_Attachment_DeleteAttachment`. + + Args: + package_id: Package ID of the package to which the document is + added. + document_id: ID of the document to which the attachment is added. + attachment_id: ID of the attachment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/attachments" + f"/{quote(str(attachment_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def attachment_download_attachment( + self, + package_id: int, + document_id: int, + attachment_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Download Attachment + + Business applications can use this service API to download the + attachment of a document. + + Swagger operation ID: `V4_Attachment_DownloadAttachment`. + + Args: + package_id: Package ID of the package to which the document is + added. + document_id: ID of the document to which the attachment is added. + attachment_id: ID of the attachment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/attachments" + f"/{quote(str(attachment_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_attachment_get_attachments( + self, + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Attachments + + Business applications can use this service API to get the attachments + of a document. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `V4_Attachment_GetAttachments`. + + Args: + package_id: Package ID of the package to which the document is + added. + document_id: ID of the document to which the attachment is added. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/attachments" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def attachment_upload_attachment( + self, + input: bytes, + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Upload Attachment + + Business applications can use this service API to upload a attachment + in a document. + + Swagger operation ID: `V4_Attachment_UploadAttachment`. + + Args: + input: The binary request body. + package_id: Package ID of the package to which the document is + added. + document_id: ID of the document to which the attachment needs to be + add. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/attachments" + ) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def checkbox_add_check_box( + self, + input: CheckBoxFieldRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add CheckBox Field + + Business applications can use this service API to add a checkbox to a + document in a package. At least one user must exist in a workflow + before fields(input and signature) can be added to the document in this + way.The order number corresponds to the recipient in the + workflow.Therefore, this number must be equal or less than the total + number of users in the workflow. The below example assigns this new + signature field to the first person in the workflow. See [Add Users to + Workflow](#operation/Workflow_WorkflowAddUser) for more information. + Note if you have a document with a template applied, or have applied + one using the APIs, then the workflow will already contain users. If + width and height parameters are not provided, a default size of 10x10 + will be assigned. If either width or height (or both) is provided, the + system will compare these provided values with each other. The larger + value between width and height will be assigned to both dimensions. + + Swagger operation ID: `V4_Checkbox_AddCheckBox`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/checkbox" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def checkbox_update_check_box( + self, + input: UpdateCheckBoxFieldRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update CheckBox Field + + Business applications can use this service API to update a checkbox + field of a document in a package. Note all of the input parameters can + be changed.Where you wish to retain the current setting submit it in + the call unchanged.You can therefore use the same parameters as when + you added the input field, or the information as returned by [Get + Document Fields](#operation/Documents_GetDocumentFields).The latter can + be used when a template was applied or the document was created using + the GUI interface. It's width and height cannot be updated. They will + remain the same as when they were added. + + Swagger operation ID: `V4_Checkbox_UpdateCheckBox`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/checkbox" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_contacts_get( + self, + record_per_page: int, + page_no: int, + *, + sort_by: Optional[str] = None, + asc: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Contacts + + Business applications can use this service API to retieve contacts from + both personal and enterprise contacts for the current user. It is + possible to search based upon the criterion supplied under the + \"x-search-text\" header.Furthermore, it is possible to search a user's + specific contacts or that of the enterprise to which the user belongs. + The search response information contains the user email address and + respective user name. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `V4_Contacts_Get`. + + Args: + record_per_page: Total number of records to be retrieved in a page. + page_no: Page number to be retrieved. + sort_by: Sort the result by possible values are mentioned above. + asc: Order the result set by ascending or descending. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/settings" + f"/contacts" + f"/{quote(str(record_per_page), safe='')}" + f"/{quote(str(page_no), safe='')}" + ) + query_params = [] + if sort_by is not None: + value = str(sort_by) + if isinstance(sort_by, bool): + value = value.lower() + query_params.append(f"sort-by={quote(value, safe='')}") + if asc is not None: + value = str(asc) + if isinstance(asc, bool): + value = value.lower() + query_params.append(f"asc={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def documents_delete_document( + self, + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete Document + + Business applications can use this service API to delete a document in + a package. + + Swagger operation ID: `V4_Documents_DeleteDocument`. + + Args: + package_id: Package ID of the package to which the document is + added. + document_id: ID of the document to be deleted. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def documents_download_document_bytes( + self, + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Download Document + + Business applications can use this service API to download the document + bytes. The package ID and document ID is provided in the resource URL. + + Swagger operation ID: `V4_Documents_DownloadDocumentBytes`. + + Args: + package_id: Package ID of the package to which the document is + added. + document_id: The ID of the document to be downloaded. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def documents_get_certify_policy( + self, + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Certify Policy for a document + + Business applications can use this service API to get certify signature + settings of a document in a package. + + Swagger operation ID: `V4_Documents_GetCertifyPolicy`. + + Args: + package_id: Package ID of the package to which the document is + added. + document_id: The ID of the document to be downloaded. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/certify" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def documents_get_document_details( + self, + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Document Details + + Business applications can use this service API to get the document + details. The document ID is provided in the URL as \"{document_id}\". + + Swagger operation ID: `V4_Documents_GetDocumentDetails`. + + Args: + package_id: The Package ID of the package to which the document is + added. + document_id: The document ID for which the document details are + requested. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/details" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def documents_rename_document( + self, + input: RenameDocumentRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Rename Document + + Business applications can use this service API to rename a document in + a package. + + Swagger operation ID: `V4_Documents_RenameDocument`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID of the package to which the document is + added. + document_id: The ID of the document to on which the action is to be + performed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def documents_update_certify_policy( + self, + input: UpdateCertifyPolicyRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Certify Policy for a document + + Business applications can use this service API to update certify + signature settings for a document in a package. + + Swagger operation ID: `V4_Documents_UpdateCertifyPolicy`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID of the package to which the document is + added. + document_id: The ID of the document on which the action is to be + performed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/certify" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def documents_upload_from_library( + self, + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add or Update Document from Library + + Business applications can use this service API to add a document from + the user's library to a package. Package ID is provided in the URL, the + ID of the document should also be provided as \"document_id\" in the + resource URL to identify the library document to be copied. Note a + package must already exist before you can add a document using this + call. + + Swagger operation ID: `V4_Documents_UploadFromLibrary`. + + Args: + package_id: The Package ID of the package to which the document is + being added. + document_id: The library document ID that need to add/updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/library" + f"/{quote(str(document_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def documents_upload_stream( + self, + input: bytes, + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Upload Document + + Business applications can use this service API to add a document to a + document package linked to an enterprise user's account. The document + information is sent in the HTTP request header and document bytes are + sent in the HTTP request body. Note SigningHub will convert supported + document formats to PDF if the header \"x-convert-document\" is set to + a value of \"true\". The only case supported where this value is set to + \"false\" is to retain Word format and XML documents. SigningHub + supports a wide variety of document formats, each of which can be + converted to PDF format upon upload.Click here for the full list. Note + PDF documents are not altered upon upload to the system. Note a package + must already exist before you can add a document using this call. + + Swagger operation ID: `V4_Documents_UploadStream`. + + Args: + input: The binary request body. + package_id: Package ID of the package to which the document is + being added. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/documents" + ) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def enterprise_documents_get_enterprise_workflow_access( + self, + package_id: int, + order: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Workflow User Authentication (Document Opening) of Enterprise + Package + + Business applications can use this service API to get the access + security settings enabled for the package. Recipients for whom the + security is configured are identified by the order in the URL. Package + ID is also identified in the request URL. Recipients will not be able + to access document package outside the scope of this duration if the + access security is enabled. Document owner can also configure + authentication based security of the package for a recipient. + + Swagger operation ID: + `V4_EnterpriseDocuments_GetEnterpriseWorkflowAccess`. + + Args: + package_id: The package ID for which workflow access security and + authentication is to be updated. + order: Order of the recipient in the workflow for which the access + security and authentication is to be updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/enterprise" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/workflow" + f"/{quote(str(order), safe='')}" + f"/authentication" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def enterprise_documents_update_enterprise_workflow_access( + self, + input: AccessUpdateRequest | Mapping[str, Any], + package_id: int, + order: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Workflow User Authentication (Document Opening) of Enterprise + Package + + Business applications can use this service API to update the package + authentications and access duration for the recipients. This API can + also be used by the enterprise administrator or the enterprise user if + the \"scope\" variable was used in the authentication request + + Swagger operation ID: + `V4_EnterpriseDocuments_UpdateEnterpriseWorkflowAccess`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The package ID for which workflow access security and + authentication is to be updated. + order: Order of the recipient in the workflow for which the access + security and authentication is to be updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/enterprise" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/workflow" + f"/{quote(str(order), safe='')}" + f"/authentication" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def fields_auto_assign_field( + self, + input: FieldsAutoAssignFieldInput, + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Assign Document Field + + Business applications can use this service API to assign users to input + fields, e.g. signature fields, and hence define the signing order. The + fields must already be present in the document and the users must be + present in the workflow. The ID of the workflow document is provided in + the resource URL, along with the package identifier. When recipients + are in a workflow they are numbered, beginning at one and counting up + for each extra one.Therefore, if there are three users in a workflow + they are numbered \"1\", \"2\", and \"3\" respectfully.This API call + allows you to assign a user by their workflow order number, to an input + field on the document. + + Swagger operation ID: `V4_Fields_AutoAssignField`. + + Args: + input: The request body. + package_id: Package ID to which the document is added. + document_id: The document ID for which workflow user needs to be + updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/assign" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def fields_auto_place( + self, + input: AutoPlaceFieldRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + AutoPlace Fields + + Business applications can call this API to add signature or user + defined form fields to a document based upon the search criterion + supplied. The placement options are: to the left, to the right, top and + bottom. The document is search and all instances of the search criteria + met are processed. This allows you to add multiple fields with one + call. For example, upload a document and automatically place a + signature field to the right of all instances of the word \"Sign + here:\". This saves time and ensures no signatures are missed from the + workflow. The API call supports all types of fields; namely electronic, + digital, in-person, initials, and text field etc. In addition, the API + call supports the \"order\" variable.This means you can assign a set of + signature fields automatically to a single user.Hence, the call can be + repeated to place and assign signature fields to more than one user in + the workflow. At least one user must exist in a workflow before + signature fields can be added to the document in this way.The order + number corresponds to the recipient in the workflow. Therefore, this + number must be equal or less than the total number of users in the + workflow. The below example assigns this new signature field to the + first person in the workflow. This API call can be used multiple times + on the same document.The reason for doing so is to cater for multiple + signatories on a document.The recipient or signatory is identified by + the \"order\" variable passed in the call. See [Add Users to + Workflow](#operation/Workflow_WorkflowAddUser) for more information. + Note if you have a document with a template applied, or have applied + one using the APIs, then the workflow will already contain users. + + Swagger operation ID: `V4_Fields_AutoPlace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The ID of the package to which the document is added. + document_id: The ID of the document for which the fields are + requested. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/autoplace" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def fields_delete_document_field( + self, + input: DeleteDocumentFieldRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete Document Field + + Business applications can use this service API to delete a field of + document in a package. + + Swagger operation ID: `V4_Fields_DeleteDocumentField`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def fields_fill_form_fields( + self, + input: FormFillingRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Fill Form Fields + + Business applications can use this service API to fill one or more form + fields in a document by a specified user in the order. + + Swagger operation ID: `V4_Fields_FillFormFields`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The ID of the document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def fields_get_all_document_fields( + self, + package_id: int, + document_id: int, + page_no: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Document Fields + + Business applications can use this service API to get document fields + i.e., initials, in-persons, signature fields or form fields. + + Swagger operation ID: `V4_Fields_GetAllDocumentFields`. + + Args: + package_id: The ID of the package to which the document is added. + document_id: The ID of the document for which the fields are + requested. + page_no: Page no of the document for which the fields are + requested. If page number is not provided fields of whole + document are returned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/{quote(str(page_no), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def folder_move_package( + self, + input: MoveToRequest | Mapping[str, Any], + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Move Package to Custom or Shared Space folder + + Business applications can use this service API to move the document + package to a shared space or user's custom folder. + + Swagger operation ID: `V4_Folder_MovePackage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package id that need to move to folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/move_to" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def initials_add_initial( + self, + input: InitialFieldRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Initial Field + + Business applications can use this service API to add an initials field + to a document in a package. At least one user must exist in a workflow + before fields(input and signature) can be added to the document in this + way.The order number corresponds to the recipient in the + workflow.Therefore, this number must be equal or less than the total + number of users in the workflow. The below example assigns this new + signature field to the first person in the workflow. See [Add Users to + Workflow](#operation/Workflow_WorkflowAddUser) for more information. + Note if you have a document with a template applied, or have applied + one using the APIs, then the workflow will already contain users. + + Swagger operation ID: `V4_Initials_AddInitial`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/initials" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def initials_fill( + self, + input: InitialFillingRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Fill Initials + + Business applications can use this service API to fill an initials + field in a document by a specified user in the order. + + Swagger operation ID: `V4_Initials_Fill`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The ID of the document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/initial" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def initials_update_initial( + self, + input: UpdateInitialFieldRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Initial Field + + Business applications can use this service API to update an initials + field of a document in a package. Note all of the input parameters can + be changed.Where you wish to retain the current setting submit it in + the call unchanged. You can therefore use the same parameters as when + you added the input field, or the information as returned by [Get + Document Fields](#operation/Documents_GetDocumentFields).The latter can + be used when a template was applied or the document was created using + the GUI interface. + + Swagger operation ID: `V4_Initials_UpdateInitial`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/initials" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def in_person_add_in_person( + self, + input: InPersonFieldRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add In-person Field + + Business applications can use this service API to an add in-person + signature field to a document in a package. At least one user must + exist in a workflow before fields(input and signature) can be added to + the document in this way.The order number corresponds to the recipient + in the workflow.Therefore, this number must be equal or less than the + total number of users in the workflow. The below example assigns this + new signature field to the first person in the workflow. See [Add Users + to Workflow](#operation/Workflow_WorkflowAddUser) for more information. + Note if you have a document with a template applied, or have applied + one using the APIs, then the workflow will already contain users. In + order to host an in-person meeting a SigningHub user must be part of + the workflow.They must either be added with Role \"INPERSON_HOST\" or + \"SIGNER\". For the host option they do not require a signature or + input field on the document, and the in-person signature field can be + signed by the non-SigningHub registered user. Note this is a special + workflow scenario whereby it is expected that the SigningHub user and + recipient would be in the same location.This type of signature is not + intended for use whereby a document is shared with recipients over + email link in the normal loose integration method. + + Swagger operation ID: `V4_InPerson_AddInPerson`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/in_person_signature" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def in_person_update_in_person( + self, + input: UpdateInPersonFieldRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update In-person Field + + Business applications can use this service API to update an in-person + signature field of a document in a package. Note all of the input + parameters can be changed.Where you wish to retain the current setting + submit it in the call unchanged.You can therefore use the same + parameters as when you added the input field, or the information as + returned by [Get Document + Fields](#operation/Documents_GetDocumentFields).The latter can be used + when a template was applied or the document was created using the GUI + interface. + + Swagger operation ID: `V4_InPerson_UpdateInPerson`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/in_person_signature" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def package_add_package( + self, + input: AddDocumentPackageRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Package + + This service API is used to add/create a document package to hold one + or more documents. This package can then be used to add documents and + recipients in order to start a new workflow. As previously stated, this + call is mandatory if you wish to work with documents. A package must + exist before you can upload or add documents to SigningHub.. Even a + single document is a part of a package: a package containing one + document. Note: A package can be renamed if required once created. + + Swagger operation ID: `V4_Package_AddPackage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v4/packages" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def package_approve( + self, + input: ApproveRequest | Mapping[str, Any], + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Approve Document + + Business applications can use this service API to approve a document by + a specified user in the order. + + Swagger operation ID: `V4_Package_Approve`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The ID of the package to be approved. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/approve" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def package_decline( + self, + input: DeclineRequest | Mapping[str, Any], + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Decline Document + + Business applications can use this service API to decline a document by + a specified user in the order. + + Swagger operation ID: `V4_Package_Decline`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The ID of the package to be declined. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/decline" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def package_delete_package( + self, + package_id_bulk_action: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete Package + + Business applications can use this service API to delete a document + from the user inbox. The package ID is provided in the resource URL as + \"{package_id}\". If the document status is PENDING, then it is + automatically declined as result of delete operation. If the document + status is SHARED, then the document is automatically recalled and + workflow is stopped before the document is deleted. + + Swagger operation ID: `V4_Package_DeletePackage`. + + Args: + package_id_bulk_action: Package ID of the package which contains + the document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id_bulk_action), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def package_download_package_bytes( + self, + package_id_bulk_action: int, + *, + document_ids: Optional[List[int]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Download Package + + Business applications can use this service API to download the document + package in binary format. The package ID is provided in the resource + URL. If the package contains only one document, the download is the + binary PDF document. Alternatively, if the package has more than one + document, the download is the binary zip file of all documents. The + x-password and x-otp headers are optional. They are required if the + document owner set them during the workflow creation phase. + + Swagger operation ID: `V4_Package_DownloadPackageBytes`. + + Args: + package_id_bulk_action: The package ID to be downloaded. + document_ids: The Document IDs parameter is optional. If + x-combine-files is set to true, the documents will be merged + based on the mentioned documents of the package. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id_bulk_action), safe='')}" + ) + query_params = [] + item: object + if document_ids is not None: + if isinstance(document_ids, list): + joined_parts = [] + for item in document_ids: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"document-ids={quote(joined, safe='')}") + else: + value = str(document_ids) + if isinstance(document_ids, bool): + value = value.lower() + query_params.append(f"document-ids={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def package_finish( + self, + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Finish Processing + + Business applications can use this service API to finish the document + processing after signing all the signature fields. This method is + primarily used by native SigningHub mobile apps for iOS and Android, + and mobile web use cases. General business applications employing tight + integration into their respective portal do not need to call this + method. However, when using the Sign Document API (and hence the user + is not presented with a visual representation of the document they are + requested to sign) calling this API is required in order to ensure the + respective workflow continues or completes. For example, once all + signatures have been applied using the \"blind\" Sign Document API call + the document will not show as status \"Completed\" to the owner until + this API is invoked. The document owner will see a status of \"In + Progress\" until this API is called. Within native SigningHub mobile + apps and mobile web use cases, this call is necessary to ensure that + each user completes their respective actions with respect to + SigningHub.For example, after a signatory has signed a document in + SigningHub App, this method is invoked by the application to ensure the + workflow continues to process and the next signatory is notified, and + the document status is available via the configured call-back URL. + + Swagger operation ID: `V4_Package_Finish`. + + Args: + package_id: The ID of the package to be finished. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/finish" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def package_gatekeeper_approve( + self, + input: ApproveRequest | Mapping[str, Any], + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Gatekeeper Approve Document + + Business applications can use this service API to gatekeeper approve a + document by a specified user in the order. + + Swagger operation ID: `V4_Package_GatekeeperApprove`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The ID of the package to be approved. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/gatekeeper" + f"/approve" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def package_gatekeeper_decline( + self, + input: DeclineRequest | Mapping[str, Any], + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Gatekeeper Decline Document + + Business applications can use this service API to gatekeeper decline a + document by a specified user in the order. + + Swagger operation ID: `V4_Package_GatekeeperDecline`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The ID of the package to be declined. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/gatekeeper" + f"/decline" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_package_get_all_packages( + self, + document_status: str, + page_no: int, + record_per_page: int, + *, + package_name: Optional[str] = None, + package_id: Optional[int] = None, + recipient_from: Optional[str] = None, + recipient_to: Optional[str] = None, + document_id: Optional[int] = None, + expiry: Optional[int] = None, + modified_from: Optional[str] = None, + modified_to: Optional[str] = None, + size_from: Optional[int] = None, + size_to: Optional[int] = None, + certified_documents: Optional[bool] = None, + form_fields: Optional[bool] = None, + attachments: Optional[bool] = None, + document_type: Optional[str] = None, + sort_by: Optional[str] = None, + asc: Optional[bool] = None, + document_statuses: Optional[List[str]] = None, + owned_by: Optional[str] = None, + smart_form: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Packages + + Business applications can use this service API to get a list of + documents filtered by different statuses. Users can divide the records + into pages by providing a number of records per page. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `V4_Package_GetAllPackages`. + + Args: + document_status: Filter by document status possible values are ALL, + DRAFT, PENDING, SIGNED, DECLINED, INPROGRESS, EDITED, REVIEWED, + COMPLETED, EXPIRING_IN_SEVEN_DAYS. + page_no: Page number, according the division of records per page. + record_per_page: Number of records that are needed to be fetched in + one request. + package_name: Package Name. + package_id: Package Id. + recipient_from: From. + recipient_to: To. + document_id: Document Id. + expiry: Expiry (Days). + modified_from: From Modified Date. + modified_to: To Modified Date. + size_from: From Size (KB). + size_to: To Size (KB). + certified_documents: Only certified signed documents. + form_fields: Only documents that have form fields. + attachments: Only documents that have attachments. + document_type: Document Type like XML, PDF, DOCX etc. + sort_by: Sort the resultant records as per your choice. + asc: Sorted the resultant records by ascending or descending order. + document_statuses: Document Type. + owned_by: Owned By filter possible values are ME_OTHERS, ME, + OTHERS. + smart_form: Smart form name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(document_status), safe='')}" + f"/{quote(str(page_no), safe='')}" + f"/{quote(str(record_per_page), safe='')}" + ) + query_params = [] + item: object + if package_name is not None: + value = str(package_name) + if isinstance(package_name, bool): + value = value.lower() + query_params.append(f"package-name={quote(value, safe='')}") + if package_id is not None: + value = str(package_id) + if isinstance(package_id, bool): + value = value.lower() + query_params.append(f"package-id={quote(value, safe='')}") + if recipient_from is not None: + value = str(recipient_from) + if isinstance(recipient_from, bool): + value = value.lower() + query_params.append(f"recipient-from={quote(value, safe='')}") + if recipient_to is not None: + value = str(recipient_to) + if isinstance(recipient_to, bool): + value = value.lower() + query_params.append(f"recipient-to={quote(value, safe='')}") + if document_id is not None: + value = str(document_id) + if isinstance(document_id, bool): + value = value.lower() + query_params.append(f"document-id={quote(value, safe='')}") + if expiry is not None: + value = str(expiry) + if isinstance(expiry, bool): + value = value.lower() + query_params.append(f"expiry={quote(value, safe='')}") + if modified_from is not None: + value = str(modified_from) + if isinstance(modified_from, bool): + value = value.lower() + query_params.append(f"modified-from={quote(value, safe='')}") + if modified_to is not None: + value = str(modified_to) + if isinstance(modified_to, bool): + value = value.lower() + query_params.append(f"modified-to={quote(value, safe='')}") + if size_from is not None: + value = str(size_from) + if isinstance(size_from, bool): + value = value.lower() + query_params.append(f"size-from={quote(value, safe='')}") + if size_to is not None: + value = str(size_to) + if isinstance(size_to, bool): + value = value.lower() + query_params.append(f"size-to={quote(value, safe='')}") + if certified_documents is not None: + value = str(certified_documents) + if isinstance(certified_documents, bool): + value = value.lower() + query_params.append(f"certified-documents={quote(value, safe='')}") + if form_fields is not None: + value = str(form_fields) + if isinstance(form_fields, bool): + value = value.lower() + query_params.append(f"form-fields={quote(value, safe='')}") + if attachments is not None: + value = str(attachments) + if isinstance(attachments, bool): + value = value.lower() + query_params.append(f"attachments={quote(value, safe='')}") + if document_type is not None: + value = str(document_type) + if isinstance(document_type, bool): + value = value.lower() + query_params.append(f"document-type={quote(value, safe='')}") + if sort_by is not None: + value = str(sort_by) + if isinstance(sort_by, bool): + value = value.lower() + query_params.append(f"sort-by={quote(value, safe='')}") + if asc is not None: + value = str(asc) + if isinstance(asc, bool): + value = value.lower() + query_params.append(f"asc={quote(value, safe='')}") + if document_statuses is not None: + if isinstance(document_statuses, list): + joined_parts = [] + for item in document_statuses: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"document-statuses={quote(joined, safe='')}") + else: + value = str(document_statuses) + if isinstance(document_statuses, bool): + value = value.lower() + query_params.append(f"document-statuses={quote(value, safe='')}") + if owned_by is not None: + value = str(owned_by) + if isinstance(owned_by, bool): + value = value.lower() + query_params.append(f"owned-by={quote(value, safe='')}") + if smart_form is not None: + value = str(smart_form) + if isinstance(smart_form, bool): + value = value.lower() + query_params.append(f"smart-form={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def package_get_package_details( + self, + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Package Details + + Business applications can use this service API to get the details of an + package. This API can also be used by the business application to + perform action on behalf of the enterprise user via \"Scope + Authentication\". + + Swagger operation ID: `V4_Package_GetPackageDetails`. + + Args: + package_id: Package ID of the document package. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/details" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def package_rename_package( + self, + input: RenameDocumentPackageRequest | Mapping[str, Any], + package_id_bulk_action: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Rename Package + + This service API is used to rename a document package. The document + package is identified by its unique identifier in the URL of the call. + + Swagger operation ID: `V4_Package_RenamePackage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id_bulk_action: Package ID to change the name of. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id_bulk_action), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def package_submit( + self, + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Submit Document + + One of the SigningHub roles is called \"Editor\". This allows a + recipient to edit input fields on a document, but does not require a + signature. Once completed the recipient submits their changes. The + button used in the GUI is called \"Submit\". This is the equivalent + operation for an editor to submit their changes via an API call. Click + [SigningHub + Roles](http://manuals.ascertia.com/SigningHubv7/default.aspx#pageid=1056) + for a description of all available workflow recipient roles. + + Swagger operation ID: `V4_Package_Submit`. + + Args: + package_id: The SigningHub package ID that contains the document to + be submitted. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/submit" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def qr_add_qr_code( + self, + input: QrCodeRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add QR Code + + Business applications can use this service API to add a QR Code to a + document in a package. + + Swagger operation ID: `V4_QR_AddQRCode`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/qrcode" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def qr_update_qr_code( + self, + input: UpdateQrCodeRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update QR Code + + Business applications can use this service API to update a QR Code of a + document in a package. + + Swagger operation ID: `V4_QR_UpdateQRCode`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/qrcode" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def radio_add_radio_box( + self, + input: RadioBoxFieldRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add RadioBox Field + + Business applications can use this service API to add a checkbox to a + document in a package. At least one user must exist in a workflow + before fields(input and signature) can be added to the document in this + way.The order number corresponds to the recipient in the + workflow.Therefore, this number must be equal or less than the total + number of users in the workflow. The below example assigns this new + signature field to the first person in the workflow. See [Add Users to + Workflow](#operation/Workflow_WorkflowAddUser) for more information. + Note if you have a document with a template applied, or have applied + one using the APIs, then the workflow will already contain users. If + width and height parameters are not provided, a default size of 10x10 + will be assigned. If either width or height (or both) is provided, the + system will compare these provided values with each other. The larger + value between width and height will be assigned to both dimensions. + + Swagger operation ID: `V4_Radio_AddRadioBox`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/radio" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def radio_update_radio_box( + self, + input: UpdateRadioBoxFieldRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update RadioBox Field + + Business applications can use this service API to update a radio button + of a document in a package. Note all of the input parameters can be + changed.Where you wish to retain the current setting submit it in the + call unchanged.You can therefore use the same parameters as when you + added the input field, or the information as returned by [Get Document + Fields](#operation/Documents_GetDocumentFields).The latter can be used + when a template was applied or the document was created using the GUI + interface. It's width and height cannot be updated. They will remain + the same as when they were added. + + Swagger operation ID: `V4_Radio_UpdateRadioBox`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/radio" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_settings_get_templates( + self, + record_per_page: int, + page_no: int, + *, + sort_by: Optional[str] = None, + asc: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Templates + + Business applications can use this service API to get list of templates + for the current user. It is possible to search based upon the criterion + supplied under the \"x-search-text\" header.Furthermore, it is possible + to search a user's personal templates or the enterprise templates as + allowed against their user role by their enterprise admin. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `V4_Settings_GetTemplates`. + + Args: + record_per_page: Total number of records to be retrieved in a page. + page_no: Page number to be retrieved. + sort_by: Sort by column. Possible Values are CREATED_ON and NAME. + Default is sort by CREATED_ON. + asc: The resulting list order. Default resulting list will be + descending. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/settings" + f"/templates" + f"/{quote(str(record_per_page), safe='')}" + f"/{quote(str(page_no), safe='')}" + ) + query_params = [] + if sort_by is not None: + value = str(sort_by) + if isinstance(sort_by, bool): + value = value.lower() + query_params.append(f"sort-by={quote(value, safe='')}") + if asc is not None: + value = str(asc) + if isinstance(asc, bool): + value = value.lower() + query_params.append(f"asc={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def signature_add_signature( + self, + input: DigitalSignatureFieldRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Digital Signature Field + + Business applications can use this service API to add a digital + signature field to a document in a package. At least one user must + exist in a workflow before fields(input and signature) can be added to + the document in this way.The order number corresponds to the recipient + in the workflow.Therefore, this number must be equal or less than the + total number of users in the workflow. The below example assigns this + new signature field to the first person in the workflow. See [Add Users + to Workflow](#operation/Workflow_WorkflowAddUser) for more + information.Note if you have a document with a template applied, or + have applied one using the APIs, then the workflow will already contain + users. + + Swagger operation ID: `V4_Signature_AddSignature`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The package ID for which workflow details need to be + updated. + document_id: The document ID where the field is to be added. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/signature" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def signature_update_signature( + self, + input: UpdateDigitalSignatureFieldRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Digital Signature Field + + Business applications can use this service API to update a digital + signature field of a document in a package. Note all of the input + parameters can be changed.Where you wish to retain the current setting + submit it in the call unchanged.You can therefore use the same + parameters as when you added the input field, or the information as + returned by [Get Document + Fields](#operation/Documents_GetDocumentFields).The latter can be used + when a template was applied or the document was created using the GUI + interface. + + Swagger operation ID: `V4_Signature_UpdateSignature`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/signature" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def signing_bulk_sign_documents( + self, + input: BulkSignRequest | Mapping[str, Any], + package_id_bulk_action: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Bulk Sign Packages + + Business applications can use this API to sign/share/sign and share + multiple documents (both electronic and digital) without displaying the + documents to the end user. This API needs information from the business + application about document packages and the details of signatures, + in-person and initials fields. On the successful completion of bulk + signing transaction, the API will return the statuses and transaction + ids of the document packages. Unlike the Sign Document API, this API + not only signs a document package but also marks it as approved and + reviewed based on whether the recipient is a Signer, Editor or + Reviewer. Any document package for which the status returns as + COMPLETED has been signed, approved or reviewed by this API. Bulk + Signing works with all the signing-time authentication methods. If SIGN + is passed as bulk_action and package is in Draft state, Sign and Share + will be performed automatically. You must call this API after the [Pre + Bulk Sign Documents](#operation/V4_Documents_ValidateBulkSignPackages) + API. In case you need to make changes in any of the document before + signing, the [Fill Form Fields](#operation/V4_Documents_FillFormFields) + API should be called before calling the Pre Bulk Sign Document API. + Remember, any mandatory input fields on a document require completing + before this API will successfully complete; whereas, the auto-populated + fields (like Name, Email, Date, Job Title, etc.) will be automatically + filled. The signatory is identified by the access token presented in + the call. Therefore, [authentication](#tag/Authentication) of the + signatory is required prior to making this call. You cannot + authenticate as an Enterprise Admin with the scope variable, and sign a + document on behalf of a user. The access token must be issued to the + signatory as a result of direct authentication. Once document is + signed, the verification response can be seen from the [Bulk Signing + Status](#operation/V4_Documents_BulkSignStatus) API. First or Second + Factor OTP Usage for Authentication In case OTP authentication is + turned on for the server side signing operation, the client + applications will need to generate an OTP for the mobile number using + the [Bulk Sign Authentication via + OTP](#operation/V4_Documents_SendsOTP) API call. Respective business + applications must retrieve the OTP from the use and submit it when + making the API call. This is done using the \"x-otp\" header in the + request. + + Swagger operation ID: `V4_Signing_BulkSignDocuments`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id_bulk_action: Bulk action to be performed. Possible + values are: SIGN | SHARE. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id_bulk_action), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def signing_bulk_sign_status( + self, + input: BulkSignStatusRequest | Mapping[str, Any], + bulk_action: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Bulk Signing Status + + Business applications can use this API to get the status of a specific + bulk signing transaction along with the details of document packages + that were processed by the [Bulk Signing + Packages](#operation/V4_Documents_BulkSignDocuments) API. You must call + this API after the Bulk Signing Packages API. The signatory is + identified by the access token presented in the call. Therefore, + [authentication](#tag/Authentication) of the signatory is required + prior to making this call. You cannot authenticate as an Enterprise + Admin with the scope variable, and sign a document on behalf of a user. + The access token must be issued to the signatory as a result of direct + authentication. For RAS signing, the ACTION property will be + REMOTE_AUTHORIZATION_REQURIED and the STATUS property will be PENDING, + indicating that the request needs to be authorized using the mobile + device. If the signing process fails in some document due to different + levels of assurance configured and the user wants to re-initiate the + signing process to complete the signing process on failed documents, + the ACTION property will be REINITIATE_SIGNING_PROCESS, and the STATUS + property will be PENDING. + + Swagger operation ID: `V4_Signing_BulkSignStatus`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + bulk_action: Bulk action to be performed. Possible values are: SIGN + | SHARE. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(bulk_action), safe='')}/status" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def signing_sign_document( + self, + input: SignDocumentRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Sign Document + + Business applications can use this service API to sign a document (both + electronic and digital) without displaying the document to the end user + using SigningHub. For example, a business application may have another + method to display the document to the user, and only the signing + functionality of SigningHub is required, or for bulk operations it may + be justified to sign without requiring the user to view and approve + every document individually. If there are changes to be saved in the + document before signing, [Fill Form + Fields](#operation/Documents_FillFormFields) API should be called + before calling the Sign Document API. Note any mandatory input fields + on a document require completing before this API will successfully + complete. The signatory is identified by the access token presented in + the call.Therefore, [authentication](#tag/Authentication) of the + signatory is required prior to making this call.You cannot authenticate + as an Enterprise Admin with the scope variable, and sign a document on + behalf of a user.The access token must be issued to the signatory as a + result of direct authentication. When this call completes it is + important that if the signatory was the last signer for a document that + the [Finish Document](#operation/Documents_Finish) API call is + invoked.The reason is because without calling that API the document + will remain in a status of \"In Progress\" to the document owner. Once + the API has been called, the status will change to \"Completed\" for + the document owner. Once document is signed, the verification response + can be seen from [Get Document + Verification](#operation/Documents_GetDocumentPackageVerification) API. + First or Second Factor OTP Usage for Authentication If OTP + authentication is turned on for the server side signing operation, + client applications will need to generate a OTP for the mobile number + using [Signer Authentication via + OTP](#operation/Documents_SendOtpForField) API call. Respective + business applications must retrieve the OTP from the use and submit it + when making the API call. This is done using the \"x-otp\" header in + the request. + + Swagger operation ID: `V4_Signing_SignDocument`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The identifier of the package that contains the + document for signature. + document_id: Identifier of the document to be signed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/sign" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_template_get_enterprise_templates( + self, + record_per_page: int, + page_no: int, + *, + sort_by: Optional[str] = None, + asc: Optional[bool] = None, + id: Optional[List[int]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Enterprise Templates + + Business applications can use this service API to get list of + enterprise templates of the current user. This means the enterprise + administrator or the enterprise user if the \"scope\" variable was used + in the authentication request. It is possible to search based upon the + criterion supplied under the \"x-search-text\" header. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `V4_Template_GetEnterpriseTemplates`. + + Args: + record_per_page: Total number of records to be retrieved in a page. + page_no: Page number to be retrieved. + sort_by: Sort the result by possible values are mentioned above. + asc: Order the result set by ascending or descending. + id: Search by template ids. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/enterprise" + f"/templates" + f"/{quote(str(record_per_page), safe='')}" + f"/{quote(str(page_no), safe='')}" + ) + query_params = [] + item: object + if sort_by is not None: + value = str(sort_by) + if isinstance(sort_by, bool): + value = value.lower() + query_params.append(f"sort-by={quote(value, safe='')}") + if asc is not None: + value = str(asc) + if isinstance(asc, bool): + value = value.lower() + query_params.append(f"asc={quote(value, safe='')}") + if id is not None: + if isinstance(id, list): + joined_parts = [] + for item in id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"id={quote(joined, safe='')}") + else: + value = str(id) + if isinstance(id, bool): + value = value.lower() + query_params.append(f"id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def text_box_add_text_box( + self, + input: TextBoxFieldRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add TextBox Field + + Business applications can use this service API to add a text input + field to a document in a package. At least one user must exist in a + workflow before fields(input and signature) can be added to the + document in this way.The order number corresponds to the recipient in + the workflow.Therefore, this number must be equal or less than the + total number of users in the workflow. The below example assigns this + new signature field to the first person in the workflow. See [Add Users + to Workflow](#operation/Workflow_WorkflowAddUser) for more information. + Note if you have a document with a template applied, or have applied + one using the APIs, then the workflow will already contain users. + + Swagger operation ID: `V4_TextBox_AddTextBox`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/text" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def text_box_update_text_box( + self, + input: UpdateTextBoxFieldRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update TextBox Field + + Business applications can use this service API to update a text box of + a document in a package. Note all of the input parameters can be + changed.Where you wish to retain the current setting submit it in the + call unchanged. You can therefore use the same parameters as when you + added the input field, or the information as returned by [Get Document + Fields](#operation/Documents_GetDocumentFields). The latter can be used + when a template was applied or the document was created using the GUI + interface. + + Swagger operation ID: `V4_TextBox_UpdateTextBox`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/fields" + f"/text" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_apply_template( + self, + input: ApplyTemplateRequest | Mapping[str, Any], + package_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Apply Workflow Template + + Business applications can use this service API to apply a workflow + template to a document. The document ID on which template has to be + applied is provided in the resource URL. When document ID is set to 0 + then template will be applied to to all of the doucments in a pacakge. + While applying the template it is important to remember these two + important points: Point 1 - If the template being applied is created + using a PDF which already contained form fields then ensure that the + document on which this template is now being applied must contain these + form fields in advance and SigningHub will NOT create those form fields + via the template rather only apply the form data and assign to the + respective users. Point 2 - If the template being applied is created + where form fields are manually added (hence not present in the PDF + originally) via SigningHub e.g. signature field, initial, in-person + signature, check boxes, radio buttons, text fields etc. then on + applying such a template, these form fields will be created on the + target document even if these form fields were already present in the + document. + + Swagger operation ID: `V4_Workflow_ApplyTemplate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The Package ID of the package to which the template + needs to be applied. + document_id: The document ID on which the template needs to be + applied. If the value is set to 0, if template is to be applied + on all the documents in the package. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/template" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_evidence_report_download_bytes( + self, + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Process Evidence Report + + Business applications can use this service API to download the workflow + process evidence report of a document. + + Swagger operation ID: `V4_WorkflowEvidenceReport_DownloadBytes`. + + Args: + package_id: The ID of the document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/report" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_get_workflow_detail( + self, + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Workflow Details + + Business applications can use this service API to get workflow details + for the package. + + Swagger operation ID: `V4_Workflow_GetWorkflowDetail`. + + Args: + package_id: The ID of the package to be downloaded. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/workflow" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_get_workflow_history( + self, + package_id: int, + page_no: int, + records_per_page: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Workflow History + + Business applications can utilize this service API to retrieve the list + of actions performed on a document. The package ID is provided in the + resource URL. The search field (x-search-text header) is intended for + email, document name, action, infokey, and infovalue. + + Swagger operation ID: `V4_Workflow_GetWorkflowHistory`. + + Args: + package_id: The ID of the document for which the log is required. + page_no: Page number to be retrieved. + records_per_page: Total number of records to be retrieved in a + page. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/log" + f"/{quote(str(page_no), safe='')}" + f"/{quote(str(records_per_page), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_get_workflow_reminder( + self, + package_id: int, + order: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Workflow Reminder + + Business applications can use this service API to update the reminders + for the recipients that has already been added to a workflow. Normally + this call is useful after a template has been applied to a document and + business applications want to override the reminders settings within + the workflow. The ID of the workflow document is provided in the + resource URL, and the workflow recipient is identified by the order at + which it is added to the workflow. + + Swagger operation ID: `V4_Workflow_GetWorkflowReminder`. + + Args: + package_id: The package ID for which workflow reminders to be + updated. + order: The order of the user for which the workflow reminders to be + updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/workflow" + f"/{quote(str(order), safe='')}" + f"/reminders" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_workflow_get_workflow_users( + self, + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Workflow Users + + Business applications can use this service API to get workflow details + for the package. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `V4_Workflow_GetWorkflowUsers`. + + Args: + package_id: The ID of the package to be downloaded. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/workflow/users" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def workflow_mark_workflow_completed( + self, + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Complete Workflow in the Middle (Terminate Workflow) + + Business applications can mark the workflow completed even in the + middle of the workflow. Use this service API to change the status of + the workflow to completed. If there are recipients who have not signed + the document yet. Their signature will not be required any more and + they will not be able to see the document in their inbox any further. + Bearer token should belong to document owner or enterprise admin can + use scope variable to get the access token on behalf of document owner + to perform this action. + + Swagger operation ID: `V4_Workflow_MarkWorkflowCompleted`. + + Args: + package_id: The package ID from which the recipient is to be + deleted. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/complete" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_permission_get_workflow_permissions( + self, + package_id: int, + order: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Workflow User Permissions + + Business applications can use this service API to get document + permissions for a recipient. Recipient is identified by the order in + the workflow. The ID of the package is provided in the resource URL. + + Swagger operation ID: `V4_WorkflowPermission_GetWorkflowPermissions`. + + Args: + package_id: The document ID for which workflow user needs to be + updated. + order: The order of the user in workflow for which the permissions + are requested. By providing the value 0 in order, service would + return the permissions of most recently added collaborator in + the workflow. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/workflow" + f"/{quote(str(order), safe='')}" + f"/permissions" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_permission_update_workflow_permissions( + self, + input: WorkflowPermissionsUpdateRequest | Mapping[str, Any], + package_id: int, + order: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Workflow User Permissions + + Business applications can use this service API to update the workflow + permissions for a user that has already been added to a workflow. + Normally this call is useful after a template has been applied to a + document and business applications want to override the permissions + within the workflow. The ID of the document package is provided in the + resource URL, and the workflow user is identified by the order at which + it is added to the workflow. + + Swagger operation ID: + `V4_WorkflowPermission_UpdateWorkflowPermissions`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The package ID for which workflow permissions to be + updated. + order: The order of the recipient for which the workflow + permissions to be updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/workflow" + f"/{quote(str(order), safe='')}" + f"/permissions" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_recall_workflow( + self, + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Recall Document + + Business applications can use this service API to stop a workflow in + progress. The document ID is provided in the resource URL. After recall + the document status automatically changes to \"DRAFT\". + + Swagger operation ID: `V4_Workflow_RecallWorkflow`. + + Args: + package_id: The ID of the package to be recalled. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/workflow" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_start_workflow( + self, + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Share Document Package + + Business applications can use this service API to share a document + package with the signers and start a new workflow. The document should + already have been prepared by applying a template and optionally + updating the users and actions defined in template. The package ID to + be shared is provided in the resource URL. + + Swagger operation ID: `V4_Workflow_StartWorkflow`. + + Args: + package_id: The document package to be shared. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/workflow" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_update_workflow( + self, + input: WorkflowDetailUpdateRequest | Mapping[str, Any], + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Workflow Details + + Business applications can use this service API to update the workflow + details. Normally this call is useful after a template has been applied + to a document, but business applications wants to override the certify + permission or post processing details. The package ID is provided in + the resource URL. + + Swagger operation ID: `V4_Workflow_UpdateWorkflow`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The package ID for which workflow details need to be + updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/workflow" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_update_workflow_post_process( + self, + input: PostProcessUpdateRequest | Mapping[str, Any], + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Post Processing + + Business applications can use this service API to add placeholder to a + workflow a document in a package. + + Swagger operation ID: `V4_Workflow_UpdateWorkflowPostProcess`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: ID of the document package for which the post + processing is being updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/workflow" + f"/post_process" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_update_workflow_reminder( + self, + input: UpdateReminderRequest | Mapping[str, Any], + package_id: int, + order: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Workflow Reminders + + Business applications can use this service API to update the workflow + reminders for a recipient that has already been added to a workflow. + Normally this call is useful after a template has been applied to a + document and business applications want to override the reminders + settings within the workflow. The ID of the workflow document is + provided in the resource URL, and the workflow recipient is identified + by the order at which it is added to the workflow. + + Swagger operation ID: `V4_Workflow_UpdateWorkflowReminder`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The package ID for which workflow reminders to be + updated. + order: The order of the user for which the workflow reminders to be + updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/workflow" + f"/{quote(str(order), safe='')}" + f"/reminders" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_workflow_add_group( + self, + input: WorkflowWorkflowAddGroupInput, + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Groups to Workflow + + Business applications can use this service API to add groups as a + recipient to a workflow. A SigningHub group means any member of the + group can perform the action, i.e. sign, on behalf of all members of + the group. Note the group will be added as the last user/group in the + workflow.Hence further work may be required to remove a current + user/group, already present in the workflow. While XML type document + preparation, only supported role types are \"SIGNER\", \"REVIEWER\" and + \"CARBON_COPY\" + + Swagger operation ID: `V4_Workflow_WorkflowAddGroup`. + + Args: + input: The request body. + package_id: ID of the package for which the group is to be added. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/workflow/groups" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_workflow_add_placeholder( + self, + input: WorkflowWorkflowAddPlaceholderInput, + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Placeholder to Workflow + + Business applications can use this service API to add placeholder to a + workflow in a package. A place holder is required when you do not know + the identity of the intended recipient in a workflow. Note the + placeholder will be added as the last user in the workflow.Hence + further work may be required to remove a current user/group, already + present in the workflow. Adding a place holder allows you to proceed + and add signature and/or input fields to the document, which can then + be assigned to individual users at a later stage. While XML type + document preparation, only supported role types are \"SIGNER\", + \"REVIEWER\" and \"CARBON_COPY\" + + Swagger operation ID: `V4_Workflow_WorkflowAddPlaceholder`. + + Args: + input: The request body. + package_id: ID of the package for which the placeholder is to be + added. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/workflow" + f"/placeholder" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_workflow_add_user( + self, + input: WorkflowWorkflowAddUserInput, + package_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Users to Workflow + + Business applications can use this service API to add recipients to a + workflow. This call will only add a recipient to the workflow. That is, + no fields currently on the document will be automatically assigned to + the new recipient(s), nor will this create any new fields. Note the + recipient(s) will be added as the last person in the workflow.Hence + further work may be required to remove a current recipient(s) already + present in the workflow. At least one user must exist in a workflow + before fields (input and signature) can be added to the document. Note + the input accepts one or more users in a single call. In this specific + call the user is a known natural person. However, the same rules apply + to Groups and Placeholders. In either of these cases the recipient + becomes a Group of users whereby any member of the group can sign the + document, or a Placeholder.The latter case is used when you do not know + the identity of the intended signatory. Note SigningHub workflow + signing order starts at \"1\". Hence, adding a user to workflow with no + current recipient(s) begins a new signing order count.The + \"signing_order\" parameter is mandatory if the workflow type is + \"custom\". Important, using this API call may affect the workflow + type.If there are current recipients in a sequential workflow and a new + one is added with the same signing order as a current recipient, then + that part of the workflow changes automatically from sequential to + parallel.Hence, the workflow overall is now of type custom as opposed + to purely sequential. Adding a recipient with the same signing order as + two or parallel recipients does not change the workflow.There are + merely, three or more recipients at that particular point of the + workflow; all in parallel order. Note, while XML type document + preparation, only supported role types are \"SIGNER\", \"REVIEWER\" and + \"CARBON_COPY\" + + Swagger operation ID: `V4_Workflow_WorkflowAddUser`. + + Args: + input: The request body. + package_id: SigningHub package ID, which the recipients are to be + added to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/packages/{quote(str(package_id), safe='')}/workflow/users" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_workflow_delete_user( + self, + package_id: int, + order: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete Workflow User + + Business applications can use this service API to delete workflow + recipient. + + Swagger operation ID: `V4_Workflow_WorkflowDeleteUser`. + + Args: + package_id: The package ID from which the recipient is to be + deleted. + order: Order of the recipient in the workflow which is to be + deleted. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/workflow" + f"/{quote(str(order), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_workflow_update_placeholder( + self, + input: WorkflowPlaceholderUpdateRequest | Mapping[str, Any], + package_id: int, + order: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Placeholder + + Business applications can use this service API to update a placeholder + in the workflow. Normally this call is useful after a template has been + applied to a document and business applications wants to override the + details of a specific place holder within the workflow. The ID of the + workflow document is provided in the resource URL, and the workflow + place holder is identified by the order at which it is added to the + workflow. While XML type document preparation, only supported role + types are \"SIGNER\", \"REVIEWER\" and \"CARBON_COPY\" + + Swagger operation ID: `V4_Workflow_WorkflowUpdatePlaceholder`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: ID of the package for which the placeholder is to be + added. + order: Order of the recipient in the workflow. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/workflow" + f"/{quote(str(order), safe='')}" + f"/placeholder" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_workflow_user_update( + self, + input: WorkflowUserUpdateRequest | Mapping[str, Any], + package_id: int, + order: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Workflow User + + Business applications can use this service API to update the details of + a recipient, group or place holder who has already been added to a + workflow. Normally this call is useful after a template has been + applied to a document and business applications wants to override the + details of a specific user within the workflow. The ID of the workflow + document is provided in the resource URL, and the workflow recipient is + identified by the order at which it is added to the workflow. Note, + while XML type document preparation, only supports role types + \"SIGNER\", \"REVIEWER\" and \"CARBON_COPY\". + + Swagger operation ID: `V4_Workflow_WorkflowUserUpdate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The package ID for which workflow user needs to be + updated. + order: The order of the user in workflow. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/workflow" + f"/{quote(str(order), safe='')}" + f"/user" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def workflow_workflow_user_update_order( + self, + input: WorkflowUserReorderRequest | Mapping[str, Any], + package_id: int, + order: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Workflow Users Order + + Business applications can use this service API to update order of the + recipient in the workflow. + + Swagger operation ID: `V4_Workflow_WorkflowUserUpdateOrder`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: ID of the package to which the recipients are to be + added. + order: Existing order of the recipient which is to be updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4" + f"/packages" + f"/{quote(str(package_id), safe='')}" + f"/workflow" + f"/{quote(str(order), safe='')}" + f"/reorder" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def work_space_delete_shared_space( + self, + id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete Shared Space + + Business applications can use this service API to delete shared space. + The availability of deleting shared spaces is subject to the assigned + enterprise user role. To allow this provision Enterprise Admin will + enable the 'Manage Shared Space' option in Roles>Document Settings. + + Swagger operation ID: `V4_WorkSpace_DeleteSharedSpace`. + + Args: + id: Id of shared space that you want to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/shared_spaces/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def work_space_get_shared_space( + self, + id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Shared Space + + Business applications can use this service API to get a specific shared + space. This API returns information about shared space, its owner and + collaborator. + + Swagger operation ID: `V4_WorkSpace_GetSharedSpace`. + + Args: + id: Id of shared space that you want to get. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/shared_spaces/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def work_space_update_shared_space( + self, + input: UpdateWorkSpaceRequest | Mapping[str, Any], + id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Shared Space + + Business applications can use this service API to update shared space. + The availability of updating shared spaces is subject to the assigned + enterprise user role. To allow this provision Enterprise Admin will + enable the 'Manage Shared Space' option in Roles>Document Settings. + + Swagger operation ID: `V4_WorkSpace_UpdateSharedSpace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Id of shared space that you want to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v4/shared_spaces/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/slack.py b/src/azure/connectors/aio/slack.py new file mode 100644 index 0000000..f7e19c6 --- /dev/null +++ b/src/azure/connectors/aio/slack.py @@ -0,0 +1,477 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# SlackClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.slack import ( + Channel, + CreateChannelResponse, + JoinChannelResponse, + ListChannelsResponse, + PostMessageRequest, + PostMessageResponse, + SetDNDResponse, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "SlackClient", + "Channel", + "CreateChannelResponse", + "JoinChannelResponse", + "ListChannelsResponse", + "PostMessageRequest", + "PostMessageResponse", + "SetDNDResponse", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class SlackClient(ConnectorClientBase): + """Typed client for slack connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a SlackClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "slack" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def set_dnd( + self, + *, + num_minutes: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Set do not disturb + + Set the do not disturb status for the user. + + Swagger operation ID: `SetDND`. + + Args: + num_minutes: The number of minutes to set do not disturb. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/dnd.setSnooze" + query_params = [] + if num_minutes is not None: + value = str(num_minutes) + if isinstance(num_minutes, bool): + value = value.lower() + query_params.append(f"num_minutes={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_channel( + self, + *, + name: Optional[str] = None, + is_private: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a channel + + Create a channel in slack. + + Swagger operation ID: `CreateChannel_V2`. + + Args: + name: The name of the new channel. + is_private: Channel is private or not. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/conversations.create" + query_params = [] + if name is not None: + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + if is_private is not None: + value = str(is_private) + if isinstance(is_private, bool): + value = value.lower() + query_params.append(f"is_private={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def join_channel( + self, + *, + channel: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Join a public channel + + Join a public channel in slack. + + Swagger operation ID: `JoinChannel_V2`. + + Args: + channel: The name of the channel. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/conversations.join" + query_params = [] + if channel is not None: + value = str(channel) + if isinstance(channel, bool): + value = value.lower() + query_params.append(f"channel={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_channels( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List public channels (Pagination support) + + List the public channels in slack. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListChannels_V3`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v3/conversations.list" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def post_message( + self, + input: PostMessageRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Post message + + This operation is used to post a message to the specified channel. + + Swagger operation ID: `PostMessage_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/chat.postMessage" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/smtp.py b/src/azure/connectors/aio/smtp.py new file mode 100644 index 0000000..caa6683 --- /dev/null +++ b/src/azure/connectors/aio/smtp.py @@ -0,0 +1,146 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# SmtpClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, +) + +from azure.connectors.smtp import ( + Attachment, + Email, +) + +__all__ = [ + "SmtpClient", + "Attachment", + "Email", +] + + +# Type Definitions + +# Client Class + +class SmtpClient(ConnectorClientBase): + """Typed client for smtp connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a SmtpClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "smtp" + + async def send_email( + self, + input: Email | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Send Email + + This operation sends an email to one or more recipients. + + Swagger operation ID: `SendEmailV3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/SendEmailV3" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) diff --git a/src/azure/connectors/aio/sql.py b/src/azure/connectors/aio/sql.py new file mode 100644 index 0000000..be18fb6 --- /dev/null +++ b/src/azure/connectors/aio/sql.py @@ -0,0 +1,2188 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# SqlClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.sql import ( + BlobDataSetsMetadata, + DataSet, + DataSetParameter, + DataSetsList, + DataSetsMetadata, + DataWithSensitivityLabelInfo, + Database, + DatabasesList, + DynamicTree, + DynamicTreeOpenBrowse, + DynamicTreeSettings, + DynamicValues, + ExecutePassThroughNativeQueryResponse, + ExecuteProcedureInput, + ExecuteProcedureResponse, + GetItemResponse, + GetItemsResponse, + GetTablesResponse, + Item, + ItemsList, + NoNaturalKeyColumnConnectorMetadata, + ODataServersList, + ObjectEntity, + PQMetadata, + PQMetadataValue, + PQRows, + PassThroughNativeQuery, + PassThroughNativeQueryBody, + PassThroughNativeQueryMetadata, + PassThroughNativeQueryResult, + PassThroughPQBody, + PassThroughPQResult, + PatchItemInput, + PatchItemResponse, + PostItemInput, + PostItemResponse, + Procedure, + ProcedureMetadata, + ProcedureResult, + ProceduresList, + SensitivityLabelMetadata, + Server, + SqlItem, + SqlItemsList, + SqlPassThroughNativeQueryBody, + SqlPassThroughNativeQueryResult, + Table, + TableCapabilitiesMetadata, + TableCountRestrictionsMetadata, + TableFilterRestrictionsMetadata, + TableMetadata, + TableSelectRestrictionsMetadata, + TableSortRestrictionsMetadata, + TablesList, + TabularDataSetsMetadata, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "SqlClient", + "BlobDataSetsMetadata", + "DataSet", + "DataSetParameter", + "DataSetsList", + "DataSetsMetadata", + "DataWithSensitivityLabelInfo", + "Database", + "DatabasesList", + "DynamicTree", + "DynamicTreeOpenBrowse", + "DynamicTreeSettings", + "DynamicValues", + "ExecutePassThroughNativeQueryResponse", + "ExecuteProcedureInput", + "ExecuteProcedureResponse", + "GetItemResponse", + "GetItemsResponse", + "GetTablesResponse", + "Item", + "ItemsList", + "NoNaturalKeyColumnConnectorMetadata", + "ODataServersList", + "ObjectEntity", + "PQMetadata", + "PQMetadataValue", + "PQRows", + "PassThroughNativeQuery", + "PassThroughNativeQueryBody", + "PassThroughNativeQueryMetadata", + "PassThroughNativeQueryResult", + "PassThroughPQBody", + "PassThroughPQResult", + "PatchItemInput", + "PatchItemResponse", + "PostItemInput", + "PostItemResponse", + "Procedure", + "ProcedureMetadata", + "ProcedureResult", + "ProceduresList", + "SensitivityLabelMetadata", + "Server", + "SqlItem", + "SqlItemsList", + "SqlPassThroughNativeQueryBody", + "SqlPassThroughNativeQueryResult", + "Table", + "TableCapabilitiesMetadata", + "TableCountRestrictionsMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TablesList", + "TabularDataSetsMetadata", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class SqlClient(ConnectorClientBase): + """Typed client for sql connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a SqlClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "sql" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def delete_item( + self, + server: str, + database: str, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete row + + This operation deletes a row from a table. + + Swagger operation ID: `DeleteItem_V2`. + + Args: + server: Name of SQL server. + database: Database name. + table: Name of table. + id: Unique identifier of the row to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def execute_pass_through_native_query( + self, + input: SqlPassThroughNativeQueryBody | Mapping[str, Any], + server: str, + database: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Execute a SQL query + + Execute a SQL query + + Swagger operation ID: `ExecutePassThroughNativeQuery_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/query" + f"/sql" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def execute_procedure( + self, + input: ExecuteProcedureInput | Mapping[str, Any], + server: str, + database: str, + procedure: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Execute stored procedure + + This operation runs a stored procedure. + + Swagger operation ID: `ExecuteProcedure_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + server: Name of SQL server. + database: Database name. + procedure: Name of stored procedure. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/procedures" + f"/{quote(quote(str(procedure), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_item( + self, + server: str, + database: str, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get row + + This operation gets a row from a table. + + Swagger operation ID: `GetItem_V2`. + + Args: + server: Name of SQL server. + database: Database name. + table: Name of SQL table. + id: Unique identifier of the row to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_items( + self, + server: str, + database: str, + table: str, + *, + apply: Optional[str] = None, + filter: Optional[str] = None, + orderby: Optional[str] = None, + skip: Optional[int] = None, + top: Optional[int] = None, + select: Optional[str] = None, + count: Optional[bool] = None, + extract_sensitivity_label: Optional[bool] = None, + purview_account_name: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get rows + + This operation gets rows from a table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItems_V2`. + + Args: + server: Name of SQL server. + database: Database name. + table: Name of SQL table. + apply: A sequence of OData aggregation transformations. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + skip: The number of entries to skip (default = 0). + top: Total number of entries to retrieve (default = all). + select: Specific fields to retrieve from entries (default = all). + count: Option to specify if only total entity count should be + returned in the query (default = false). + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + query_params = [] + if apply is not None: + value = str(apply) + if isinstance(apply, bool): + value = value.lower() + query_params.append(f"$apply={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if count is not None: + value = str(count) + if isinstance(count, bool): + value = value.lower() + query_params.append(f"$count={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if purview_account_name is not None: + value = str(purview_account_name) + if isinstance(purview_account_name, bool): + value = value.lower() + query_params.append(f"purviewAccountName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_tables( + self, + server: str, + database: str, + *, + extract_sensitivity_label: Optional[bool] = None, + purview_account_name: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get tables + + This operation gets tables from a database. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTables_V2`. + + Args: + server: Name of SQL server. + database: Database name. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/tables" + ) + query_params = [] + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if purview_account_name is not None: + value = str(purview_account_name) + if isinstance(purview_account_name, bool): + value = value.lower() + query_params.append(f"purviewAccountName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def patch_item( + self, + input: PatchItemInput | Mapping[str, Any], + server: str, + database: str, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update row + + This operation updates an existing row in a table. + + Swagger operation ID: `PatchItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + server: Name of SQL server. + database: Database name. + table: Name of table. + id: Unique identifier of the row to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def post_item( + self, + input: PostItemInput | Mapping[str, Any], + server: str, + database: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Insert row + + This operation inserts a new row into a table. + + Swagger operation ID: `PostItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + server: Name of SQL server. + database: Database name. + table: Name of table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_servers( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List the servers + + List the servers + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetServers`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/servers" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_databases( + self, + server: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List the databases + + List the databases + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetDatabases`. + + Args: + server: Server name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/databases" + query_params = [] + value = str(server) + if isinstance(server, bool): + value = value.lower() + query_params.append(f"server={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_tables_for_delete_item( + self, + server: str, + database: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + GetTablesForDeleteItem + + GetTablesForDeleteItem + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTablesForDeleteItem_V2`. + + Args: + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/tablesfor" + f"/deleteitem" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_pass_through_native_query_metadata( + self, + input: SqlPassThroughNativeQueryBody | Mapping[str, Any], + server: str, + database: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get pass-through native SQL query metadata + + Retrieves metadata for a pass-through native SQL query. + + Swagger operation ID: `GetPassThroughNativeQueryMetadata_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/$metadata.json" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/query" + f"/sql" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_procedures_v2( + self, + server: str, + database: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get stored procedures + + This operation gets stored procedures for a database. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetProcedures_V2`. + + Args: + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/procedures" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_procedure_v2( + self, + server: str, + database: str, + procedure: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get metadata of a Procedure + + Get metadata of a Procedure. + + Swagger operation ID: `GetProcedure_V2`. + + Args: + server: Name of SQL server. + database: Database name. + procedure: Procedure name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/$metadata.json" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/procedures" + f"/{quote(quote(str(procedure), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tables_for_get_item( + self, + server: str, + database: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + GetTablesForGetItem + + GetTablesForGetItem + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTablesForGetItem_V2`. + + Args: + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/tablesfor" + f"/getitem" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_table( + self, + server: str, + database: str, + table: str, + *, + extract_sensitivity_label: Optional[bool] = None, + purview_account_name: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get metadata of a table + + Get metadata of a table. + + Swagger operation ID: `GetTable_V2`. + + Args: + server: Name of SQL server. + database: Database name. + table: table name. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/$metadata.json" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + ) + query_params = [] + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if purview_account_name is not None: + value = str(purview_account_name) + if isinstance(purview_account_name, bool): + value = value.lower() + query_params.append(f"purviewAccountName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tables_for_get_on_new_items( + self, + server: str, + database: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + GetTablesForOnItemCreated + + GetTablesForOnItemCreated + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTablesForGetOnNewItems_V2`. + + Args: + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/tablesfor" + f"/getonnewitems" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_tables_for_get_on_updated_items( + self, + server: str, + database: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + GetTablesForOnItemUpdated + + GetTablesForOnItemUpdated + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTablesForGetOnUpdatedItems_V2`. + + Args: + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/tablesfor" + f"/getonupdateditems" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_tables_for_patch_item( + self, + server: str, + database: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + GetTablesForPatchItem + + GetTablesForPatchItem + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTablesForPatchItem_V2`. + + Args: + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/tablesfor" + f"/patchitem" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_table_for_patch( + self, + server: str, + database: str, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get metadata of a table for Patch operation + + Get metadata of a table for Patch operation. + + Swagger operation ID: `GetTableForPatch_V2`. + + Args: + server: Name of SQL server. + database: Database name. + table: table name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/$metadata.json" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/forPatchItem" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tables_for_post_item( + self, + server: str, + database: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + GetTablesForPostItem + + GetTablesForPostItem + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTablesForPostItem_V2`. + + Args: + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2" + f"/datasets" + f"/" + f"{quote(quote(str(server), safe=''), safe='')}" + f"," + f"{quote(quote(str(database), safe=''), safe='')}" + f"/tablesfor" + f"/postitem" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_procedure( + self, + procedure: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get procedure metadata + + This operation gets metadata for a stored procedure. + + Swagger operation ID: `GetProcedure`. + + Args: + procedure: Name of stored procedure. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/$metadata.json" + f"/datasets" + f"/default" + f"/procedures" + f"/{quote(quote(str(procedure), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_procedures( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get stored procedures + + This operation gets stored procedures for a database. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetProcedures`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/datasets/default/procedures" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/starmind.py b/src/azure/connectors/aio/starmind.py new file mode 100644 index 0000000..c2c1d22 --- /dev/null +++ b/src/azure/connectors/aio/starmind.py @@ -0,0 +1,458 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# StarmindClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping +from urllib.parse import quote +import json + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, +) + +from azure.connectors.starmind import ( + Attachment, + Comment, + ConceptLabelMatch, + ExpertConceptScores, + FindExpertsInput, + FindExpertsResponse, + FindQuestionsResponse, + GraphQLError, + GraphQLUserResponse, + KnowledgeSpace, + Language, + PostQuestionDraftInput, + PublishQuestionDraftResponse, + Question, + QuestionComplete, + Solution, + SolutionAuthorityApproval, + SolutionValidation, + User, + UserId, + UserLegacy, +) + +__all__ = [ + "StarmindClient", + "Attachment", + "Comment", + "ConceptLabelMatch", + "ExpertConceptScores", + "FindExpertsInput", + "FindExpertsResponse", + "FindQuestionsResponse", + "GraphQLError", + "GraphQLUserResponse", + "KnowledgeSpace", + "Language", + "PostQuestionDraftInput", + "PublishQuestionDraftResponse", + "Question", + "QuestionComplete", + "Solution", + "SolutionAuthorityApproval", + "SolutionValidation", + "User", + "UserId", + "UserLegacy", +] + + +# Type Definitions + +# Client Class + +class StarmindClient(ConnectorClientBase): + """Typed client for starmind connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a StarmindClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "starmind" + + async def find_experts( + self, + input: FindExpertsInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Find experts + + Finds experts based on the provided text_query. The search leverages + the knowledge graph to identify users with relevant expertise and + knowledge related to the query. Provide the optional language to + specify the preferred language for concept label filtering. This does + not affect the search matching itself; it only filters which expertise + we show from returned users by selecting concepts based on the primary + label in the chosen language. Returned concepts are deduplicated when + multiple concepts share the same primary label. + + Swagger operation ID: `FindExperts_V3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/v3/experts" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def find_questions( + self, + *, + query: Optional[str] = None, + limit: Optional[int] = None, + filter: Optional[str] = None, + sort: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Find questions + + Searches questions using optional `query`, `limit` (default 10), + `filter`, and `sort`; returns a paginated collection with question + `items`. By default, all published questions are returned, ordered by + their last activity (descending). A combination of filters, search + queries and ordering criteria can be applied to the result. + + Swagger operation ID: `FindQuestions_V3`. + + Args: + query: The question search query. + limit: Limit the number of returned questions. Defaults to 10. + filter: Filter the list of questions using a predefined filter. + sort: Specify the criteria the result is sorted by. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/v3/questions" + query_params = [] + if query is not None: + value = str(query) + if isinstance(query, bool): + value = value.lower() + query_params.append(f"query={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"filter={quote(value, safe='')}") + if sort is not None: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_user_by_id( + self, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get user by id + + Retrieves user information based on the provided user id. + + Swagger operation ID: `GetUserById_V3`. + + Args: + id: The unique global user identifier (UUID) as path parameter used + to reference the user across the Starmind platform. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v3/users/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def post_question_draft( + self, + input: PostQuestionDraftInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a question draft + + Creates a new question draft. The draft is not yet searchable or + answerable by others. After creation, publish the draft (via the + publish endpoint) to trigger expert search, make the question + discoverable, and allow other users to answer it. Providing the + optional description helps experts understand the question better and + increases the chances of getting high-quality answers. + + Swagger operation ID: `PostQuestionDraft_V3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/v3/questions" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def publish_question_draft( + self, + question_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Publish a question + + Publishes a question draft. Publishing the question triggers expert + search, makes the question discoverable, and allows other users to + answer it. Questions are always published anonymously. + + Swagger operation ID: `PublishQuestionDraft_V3`. + + Args: + question_id: The ID of the question draft to be published. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v3/questions/{quote(str(question_id), safe='')}/publish" + ) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/starrezrestv1.py b/src/azure/connectors/aio/starrezrestv1.py new file mode 100644 index 0000000..d76dc11 --- /dev/null +++ b/src/azure/connectors/aio/starrezrestv1.py @@ -0,0 +1,2180 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# Starrezrestv1Client.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.starrezrestv1 import ( + CreateBookingInput, + CreateBookingResponse, + CreateEntryApplicationInput, + CreateEntryApplicationResponse, + CreateEntryEnrollmentInput, + CreateEntryEnrollmentResponse, + CreateEntryInput, + CreateEntryResponse, + CreateRoomSpaceInput, + CreateRoomSpaceMaintenanceInput, + CreateRoomSpaceMaintenanceResponse, + CreateRoomSpaceResponse, + CreateTransactionInput, + CreateTransactionResponse, + DeleteResponse, + SelectBookingInput, + SelectEntryAddressInput, + SelectEntryApplicationInput, + SelectEntryCustomFieldInput, + SelectEntryDetailInput, + SelectEntryEnrollmentInput, + SelectEntryInput, + SelectRoomLocationInput, + SelectRoomSpaceInput, + SelectRoomSpaceMaintenanceInput, + SelectTermInput, + SelectTermSessionInput, + SelectTransactionInput, + UpdateBookingInput, + UpdateBookingResponse, + UpdateEntryAddressInput, + UpdateEntryAddressResponse, + UpdateEntryApplicationInput, + UpdateEntryApplicationResponse, + UpdateEntryCustomFieldInput, + UpdateEntryCustomFieldResponse, + UpdateEntryDetailInput, + UpdateEntryDetailResponse, + UpdateEntryEnrollmentInput, + UpdateEntryEnrollmentResponse, + UpdateEntryInput, + UpdateEntryResponse, + UpdateRoomSpaceMaintenanceInput, + UpdateRoomSpaceMaintenanceResponse, +) + +__all__ = [ + "Starrezrestv1Client", + "CreateBookingInput", + "CreateBookingResponse", + "CreateEntryApplicationInput", + "CreateEntryApplicationResponse", + "CreateEntryEnrollmentInput", + "CreateEntryEnrollmentResponse", + "CreateEntryInput", + "CreateEntryResponse", + "CreateRoomSpaceInput", + "CreateRoomSpaceMaintenanceInput", + "CreateRoomSpaceMaintenanceResponse", + "CreateRoomSpaceResponse", + "CreateTransactionInput", + "CreateTransactionResponse", + "DeleteResponse", + "SelectBookingInput", + "SelectEntryAddressInput", + "SelectEntryApplicationInput", + "SelectEntryCustomFieldInput", + "SelectEntryDetailInput", + "SelectEntryEnrollmentInput", + "SelectEntryInput", + "SelectRoomLocationInput", + "SelectRoomSpaceInput", + "SelectRoomSpaceMaintenanceInput", + "SelectTermInput", + "SelectTermSessionInput", + "SelectTransactionInput", + "UpdateBookingInput", + "UpdateBookingResponse", + "UpdateEntryAddressInput", + "UpdateEntryAddressResponse", + "UpdateEntryApplicationInput", + "UpdateEntryApplicationResponse", + "UpdateEntryCustomFieldInput", + "UpdateEntryCustomFieldResponse", + "UpdateEntryDetailInput", + "UpdateEntryDetailResponse", + "UpdateEntryEnrollmentInput", + "UpdateEntryEnrollmentResponse", + "UpdateEntryInput", + "UpdateEntryResponse", + "UpdateRoomSpaceMaintenanceInput", + "UpdateRoomSpaceMaintenanceResponse", +] + + +# Type Definitions + +# Client Class + +class Starrezrestv1Client(ConnectorClientBase): + """Typed client for starrezrestv1 connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a Starrezrestv1Client. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "starrezrestv1" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_select_entry( + self, + input: SelectEntryInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Entry + + Retrieves one or more records from the Entry table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SelectEntry`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/select/entry.json" + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_entry( + self, + input: CreateEntryInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Entry + + Creates a new record in the Entry table. + + Swagger operation ID: `CreateEntry`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/create/entry.json" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_entry( + self, + input: UpdateEntryInput | Mapping[str, Any], + entry_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Entry + + Updates an existing record in the Entry table. + + Swagger operation ID: `UpdateEntry`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entry_id: The ID of the Entry record to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/update/entry.json/{quote(str(entry_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete( + self, + table_name: str, + row_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete + + Deletes a record from the specified table. + + Swagger operation ID: `Delete`. + + Args: + table_name: Name of the table to delete record from. + row_id: Row ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/delete" + f"/{quote(str(table_name), safe='')}.json" + f"/{quote(str(row_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_select_entry_custom_field( + self, + input: SelectEntryCustomFieldInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Entry Custom Field + + Retrieves one or more records from the Entry Custom Field table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SelectEntryCustomField`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/select/EntryCustomField.json" + ) + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_entry_custom_field( + self, + input: UpdateEntryCustomFieldInput | Mapping[str, Any], + entry_custom_field_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Entry Custom Field + + Updates an existing record in the Entry Custom Field table. + + Swagger operation ID: `UpdateEntryCustomField`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entry_custom_field_id: The ID of the Entry Custom Field record to + update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/update" + f"/entryCustomField.json" + f"/{quote(str(entry_custom_field_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_select_term( + self, + input: SelectTermInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Term + + Retrieves one or more records from the Term table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SelectTerm`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/select/Term.json" + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_select_entry_address( + self, + input: SelectEntryAddressInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Entry Address + + Retrieves one or more records from the Entry Address table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SelectEntryAddress`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/select/EntryAddress.json" + ) + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_entry_address( + self, + input: UpdateEntryAddressInput | Mapping[str, Any], + entry_address_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Entry Address + + Updates an existing record in the Entry Address table. + + Swagger operation ID: `UpdateEntryAddress`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entry_address_id: The ID of the Entry Address record to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/update" + f"/entryAddress.json" + f"/{quote(str(entry_address_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_select_entry_application( + self, + input: SelectEntryApplicationInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Entry Application + + Retrieves one or more records from the Entry Application table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SelectEntryApplication`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/select/EntryApplication.json" + ) + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_entry_application( + self, + input: CreateEntryApplicationInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Entry Application + + Creates a new record in the Entry Application table. + + Swagger operation ID: `CreateEntryApplication`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/create/entryapplication.json" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_entry_application( + self, + input: UpdateEntryApplicationInput | Mapping[str, Any], + entry_application_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Entry Application + + Updates an existing record in the Entry Application table. + + Swagger operation ID: `UpdateEntryApplication`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entry_application_id: The ID of the Entry Application record to + update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/update" + f"/entryapplication.json" + f"/{quote(str(entry_application_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_select_term_session( + self, + input: SelectTermSessionInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Term Session + + Retrieves one or more records from the Term Session table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SelectTermSession`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/select/TermSession.json" + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_select_entry_detail( + self, + input: SelectEntryDetailInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Entry Detail + + Retrieves one or more records from the Entry Detail table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SelectEntryDetail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/select/EntryDetail.json" + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_entry_detail( + self, + input: UpdateEntryDetailInput | Mapping[str, Any], + entry_detail_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Entry Detail + + Updates an existing record in the Entry Detail table. + + Swagger operation ID: `UpdateEntryDetail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entry_detail_id: The ID of the Entry Detail record to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/update/entrydetail.json/{quote(str(entry_detail_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_select_entry_enrollment( + self, + input: SelectEntryEnrollmentInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Entry Enrollment + + Retrieves one or more records from the Entry Enrollment table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SelectEntryEnrollment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/select/EntryEnrollment.json" + ) + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_entry_enrollment( + self, + input: CreateEntryEnrollmentInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Entry Enrollment + + Creates a new record in the Entry Enrollment table. + + Swagger operation ID: `CreateEntryEnrollment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/create/entryenrollment.json" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_entry_enrollment( + self, + input: UpdateEntryEnrollmentInput | Mapping[str, Any], + entry_enrollment_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Entry Enrollment + + Updates an existing record in the Entry Enrollment table. + + Swagger operation ID: `UpdateEntryEnrollment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entry_enrollment_id: The ID of the Entry Enrollment record to + update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/update" + f"/entryenrollment.json" + f"/{quote(str(entry_enrollment_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_select_booking( + self, + input: SelectBookingInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Booking + + Retrieves one or more records from the Booking table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SelectBooking`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/select/Booking.json" + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_booking( + self, + input: CreateBookingInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Booking + + Creates a new record in the Booking table. + + Swagger operation ID: `CreateBooking`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/create/booking.json" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_booking( + self, + input: UpdateBookingInput | Mapping[str, Any], + booking_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Booking + + Updates an existing record in the Booking table. + + Swagger operation ID: `UpdateBooking`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + booking_id: The ID of the Booking record to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/update/booking.json/{quote(str(booking_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_select_room_space( + self, + input: SelectRoomSpaceInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Room Space + + Retrieves one or more records from the Room Space table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SelectRoomSpace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/select/RoomSpace.json" + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_room_space( + self, + input: CreateRoomSpaceInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Room Space + + Creates a new record in the Room Space table. + + Swagger operation ID: `CreateRoomSpace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/create/roomspace.json" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_select_room_location( + self, + input: SelectRoomLocationInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Room Location + + Retrieves one or more records from the Room Location table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SelectRoomLocation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/select/RoomLocation.json" + ) + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_select_transaction( + self, + input: SelectTransactionInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Transaction + + Retrieves one or more records from the Transaction table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SelectTransaction`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/select/Transaction.json" + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_transaction( + self, + input: CreateTransactionInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Transaction + + Creates a new record in the Transaction table. + + Swagger operation ID: `CreateTransaction`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/create/transaction.json" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_select_room_space_maintenance( + self, + input: SelectRoomSpaceMaintenanceInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Room Space Maintenance + + Retrieves one or more records from the Room Space Maintenance table. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SelectRoomSpaceMaintenance`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/select/RoomSpaceMaintenance.json" + ) + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_room_space_maintenance( + self, + input: CreateRoomSpaceMaintenanceInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Room Space Maintenance + + Creates a new record in the Room Space Maintenance table. + + Swagger operation ID: `CreateRoomSpaceMaintenance`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/create/roomspacemaintenance.json" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_room_space_maintenance( + self, + input: UpdateRoomSpaceMaintenanceInput | Mapping[str, Any], + room_space_maintenance_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update Room Space Maintenance + + Updates an existing record in the Room Space Maintenance table. + + Swagger operation ID: `UpdateRoomSpaceMaintenance`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + room_space_maintenance_id: The ID of the Room Space Maintenance + record to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/update" + f"/roomspacemaintenance.json" + f"/{quote(str(room_space_maintenance_id), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/tallyfy.py b/src/azure/connectors/aio/tallyfy.py new file mode 100644 index 0000000..33bb06b --- /dev/null +++ b/src/azure/connectors/aio/tallyfy.py @@ -0,0 +1,1359 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# TallyfyClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.tallyfy import ( + AccessToken, + AccountInput, + AccountsInput, + AddTagInput, + Address, + AlertIssues, + Asset, + AssetSubject, + BillInput, + Branding, + BrandingInput, + Capture, + CaptureInput, + CheckUrlInput, + Checklist, + ChecklistInput, + Client, + Comment, + CommentOn, + CommentTaskInput, + CommentTaskResponse, + CompletedOneOffTaskInput, + CompletedOneOffTaskResponse, + CompletedProcessTask, + CompletedProcessTaskInput, + CompletedProcessTaskResponse, + CreateChecklistInput, + CreateCommentInput, + CreateGroupInput, + CreateGuestsTasksComment, + CreateRoleInput, + CreateRunInput, + CreateRunResponse, + CreateStandaloneTaskInput, + CreateStepInput, + CreateTagInput, + CreateTaskInput, + CreateTaskResponse, + Date, + DueDateInput, + EditStepTypeInput, + EditStepTypeResponse, + EditTaskDeadlineInput, + EditTaskDeadlineResponse, + Error, + File, + GenericObject, + GetOrganizationUsersResponse, + GetUserOrganizationsResponse, + GetUserTasksResponse, + Group, + IntegrationS3Input, + InviteInput, + InviteUserToOrganizationInput, + InviteUserToOrganizationResponse, + LoginInput, + Message, + Organization, + OrganizationInput, + OrganizationSettings, + OwnerInput, + Pagination, + Passwordreset, + Passwordreseterro, + PowerbuilderInput, + Preference, + PreferenceInput, + PrerunData, + RegisterInput, + RemoveAssigneeResponse, + RemoveGuestResponse, + ReopenOneOffTaskResponse, + ReopenProcessTaskResponse, + RequestDate, + ResetPasswordInput, + Role, + Run, + RunAlerts, + RunCollaborators, + RunMetaInput, + RunRatingsInput, + RunView, + RunViewInput, + Section, + SectionCreateInput, + SectionInput, + StandaloneTask, + Step, + StepCondition, + StepConditionTerm, + StepDeadline, + StepMeta, + StepOwner, + SubcriptionInput, + Tag, + TaskGuest, + TaskMeta, + TaskMetaInput, + TaskObject, + TasksList, + TasksListMeta, + Thread, + ThreadInput, + ThreadResolveInput, + UpdateGuestsTasksInput, + UpdateStandaloneTaskInput, + UpdateTaskInput, + User, +) + +__all__ = [ + "TallyfyClient", + "AccessToken", + "AccountInput", + "AccountsInput", + "AddTagInput", + "Address", + "AlertIssues", + "Asset", + "AssetSubject", + "BillInput", + "Branding", + "BrandingInput", + "Capture", + "CaptureInput", + "CheckUrlInput", + "Checklist", + "ChecklistInput", + "Client", + "Comment", + "CommentOn", + "CommentTaskInput", + "CommentTaskResponse", + "CompletedOneOffTaskInput", + "CompletedOneOffTaskResponse", + "CompletedProcessTask", + "CompletedProcessTaskInput", + "CompletedProcessTaskResponse", + "CreateChecklistInput", + "CreateCommentInput", + "CreateGroupInput", + "CreateGuestsTasksComment", + "CreateRoleInput", + "CreateRunInput", + "CreateRunResponse", + "CreateStandaloneTaskInput", + "CreateStepInput", + "CreateTagInput", + "CreateTaskInput", + "CreateTaskResponse", + "Date", + "DueDateInput", + "EditStepTypeInput", + "EditStepTypeResponse", + "EditTaskDeadlineInput", + "EditTaskDeadlineResponse", + "Error", + "File", + "GenericObject", + "GetOrganizationUsersResponse", + "GetUserOrganizationsResponse", + "GetUserTasksResponse", + "Group", + "IntegrationS3Input", + "InviteInput", + "InviteUserToOrganizationInput", + "InviteUserToOrganizationResponse", + "LoginInput", + "Message", + "Organization", + "OrganizationInput", + "OrganizationSettings", + "OwnerInput", + "Pagination", + "Passwordreset", + "Passwordreseterro", + "PowerbuilderInput", + "Preference", + "PreferenceInput", + "PrerunData", + "RegisterInput", + "RemoveAssigneeResponse", + "RemoveGuestResponse", + "ReopenOneOffTaskResponse", + "ReopenProcessTaskResponse", + "RequestDate", + "ResetPasswordInput", + "Role", + "Run", + "RunAlerts", + "RunCollaborators", + "RunMetaInput", + "RunRatingsInput", + "RunView", + "RunViewInput", + "Section", + "SectionCreateInput", + "SectionInput", + "StandaloneTask", + "Step", + "StepCondition", + "StepConditionTerm", + "StepDeadline", + "StepMeta", + "StepOwner", + "SubcriptionInput", + "Tag", + "TaskGuest", + "TaskMeta", + "TaskMetaInput", + "TaskObject", + "TasksList", + "TasksListMeta", + "Thread", + "ThreadInput", + "ThreadResolveInput", + "UpdateGuestsTasksInput", + "UpdateStandaloneTaskInput", + "UpdateTaskInput", + "User", +] + + +# Type Definitions + +# Client Class + +class TallyfyClient(ConnectorClientBase): + """Typed client for tallyfy connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a TallyfyClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "tallyfy" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def get_user_tasks( + self, + org: str, + user_id: int, + *, + q: Optional[str] = None, + status: Optional[str] = None, + sort: Optional[str] = None, + tag: Optional[str] = None, + page: Optional[int] = None, + per_page: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a member's tasks + + Get all tasks that belong to a specific member + + Swagger operation ID: `Get_User_Tasks`. + + Args: + org: Organization Id. + user_id: Member Id. + q: Search Tasks by their Process name. + status: You can search all Tasks by status. + sort: Add minus sign (-) before sort value if you want to sort + records in descending order. Ex: sort=-improvements. + tag: Search Tasks by Tag name. + page: Which results page to retrieve. Default is 1. + per_page: How many Tasks per page. Default is 10. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/organizations" + f"/{quote(str(org), safe='')}" + f"/users" + f"/{quote(str(user_id), safe='')}" + f"/tasks" + ) + query_params = [] + if q is not None: + value = str(q) + if isinstance(q, bool): + value = value.lower() + query_params.append(f"q={quote(value, safe='')}") + if status is not None: + value = str(status) + if isinstance(status, bool): + value = value.lower() + query_params.append(f"status={quote(value, safe='')}") + if sort is not None: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if tag is not None: + value = str(tag) + if isinstance(tag, bool): + value = value.lower() + query_params.append(f"tag={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if per_page is not None: + value = str(per_page) + if isinstance(per_page, bool): + value = value.lower() + query_params.append(f"per_page={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def invite_user_to_organization( + self, + input: InviteUserToOrganizationInput | Mapping[str, Any], + org: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Invite a new member to your organization + + Invite a new member to your organization + + Swagger operation ID: `Invite_User_To_Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/organizations/{quote(str(org), safe='')}/users/invite" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_run( + self, + input: CreateRunInput | Mapping[str, Any], + org: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Launch a Process + + Launch a process using a blueprint + + Swagger operation ID: `Create_Run`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/organizations/{quote(str(org), safe='')}/runs" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def completed_one_off_task( + self, + input: CompletedOneOffTaskInput | Mapping[str, Any], + org: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Complete One Off Task + + Complete one off task + + Swagger operation ID: `Completed_One_Off_Task`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/organizations/{quote(str(org), safe='')}/completed-tasks" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def reopen_one_off_task( + self, + org: str, + task: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Reopen One Off Task + + Reopen one off task + + Swagger operation ID: `Reopen_One_Off_Task`. + + Args: + org: Organization Id. + task: Task Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/organizations" + f"/{quote(str(org), safe='')}" + f"/completed-tasks" + f"/{quote(str(task), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def completed_process_task( + self, + input: CompletedProcessTaskInput | Mapping[str, Any], + org: str, + run: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Complete process task + + Complete process task + + Swagger operation ID: `Completed_Process_Task`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + run: Run Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/organizations" + f"/{quote(str(org), safe='')}" + f"/runs" + f"/{quote(str(run), safe='')}" + f"/completed-tasks" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def reopen_process_task( + self, + org: str, + run: str, + task: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Reopen process Task + + Reopen process task + + Swagger operation ID: `Reopen_Process_Task`. + + Args: + org: Organization Id. + run: Run Id. + task: Task Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/organizations" + f"/{quote(str(org), safe='')}" + f"/runs" + f"/{quote(str(run), safe='')}" + f"/completed-tasks" + f"/{quote(str(task), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def comment_task( + self, + input: CommentTaskInput | Mapping[str, Any], + org: str, + task: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add comment, report issue, resolve issue on a task + + task deadline, in date-time format + + Swagger operation ID: `Comment_Task`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + task: Task Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/organizations" + f"/{quote(str(org), safe='')}" + f"/tasks" + f"/{quote(str(task), safe='')}" + f"/comment" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_task( + self, + input: CreateTaskInput | Mapping[str, Any], + org: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a task + + Create Task + + Swagger operation ID: `Create_Task`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/processes" + f"/micro-functions" + f"/organizations" + f"/{quote(str(org), safe='')}" + f"/tasks" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_task_deadline( + self, + input: EditTaskDeadlineInput | Mapping[str, Any], + org: str, + task: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Edit task deadline + + Edit deadline of a task + + Swagger operation ID: `Edit_Task_Deadline`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + task: Task id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/processes" + f"/micro-functions" + f"/organizations" + f"/{quote(str(org), safe='')}" + f"/tasks" + f"/{quote(str(task), safe='')}" + f"/edit-deadline" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def remove_guest( + self, + org: str, + task: str, + guest: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Remove guest assigned + + Remove guest of a task + + Swagger operation ID: `Remove_Guest`. + + Args: + org: Organization Id. + task: Task id. + guest: Guest email. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/processes" + f"/micro-functions" + f"/organizations" + f"/{quote(str(org), safe='')}" + f"/tasks" + f"/{quote(str(task), safe='')}" + f"/remove-guest" + f"/{quote(str(guest), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def remove_assignee( + self, + org: str, + task: str, + member: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Remove assignee + + Remove assignee of a task + + Swagger operation ID: `Remove_Assignee`. + + Args: + org: Organization Id. + task: Task id. + member: Member id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/processes" + f"/micro-functions" + f"/organizations" + f"/{quote(str(org), safe='')}" + f"/tasks" + f"/{quote(str(task), safe='')}" + f"/remove-assignee" + f"/{quote(str(member), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def edit_step_type( + self, + input: EditStepTypeInput | Mapping[str, Any], + org: str, + blueprint: str, + step: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Edit step type + + Edit step type + + Swagger operation ID: `Edit_Step_Type`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + blueprint: Blueprint id. + step: Step id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/processes" + f"/micro-functions" + f"/organizations" + f"/{quote(str(org), safe='')}" + f"/blueprints" + f"/{quote(str(blueprint), safe='')}" + f"/steps" + f"/{quote(str(step), safe='')}" + f"/edit-step-type" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_user_organizations( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get user's organizations + + Get user's organizations + + Swagger operation ID: `Get_User_Organizations`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/me/organizations" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_organization_users( + self, + org: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get organization's users + + Get all users belonging to an organization + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Get_Organization_Users`. + + Args: + org: Organization Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/organizations/{quote(str(org), safe='')}/users" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("data", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/teams.py b/src/azure/connectors/aio/teams.py new file mode 100644 index 0000000..c4e4057 --- /dev/null +++ b/src/azure/connectors/aio/teams.py @@ -0,0 +1,6419 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# TeamsClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core import MatchConditions +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.teams import ( + Activities, + AddMemberToChannelInput, + AddMemberToChatInput, + AddMemberToTagInput, + AddMemberToTagResponseSchema, + AddMemberToTeamInput, + AddSectionItemInput, + AiInsightActionItem, + AiInsightCollectionResponse, + AiInsightDetailResponse, + AiInsightMeetingNote, + AiInsightMeetingNoteSubpoint, + AiInsightMentionEvent, + AiInsightResponse, + AiInsightViewpoint, + AiInsightWebhookResponseSchema, + ArchiveChannelInput, + AssociatedTeamInfo, + AsyncOperationResponse, + AtMentionBotResponse, + AtMentionTagResponse, + AtMentionUser, + BotIdForChat, + BotMentionRequest, + CallEventWebhookResponseSchema, + CallRecordingCollectionResponse, + CallRecordingResponse, + CallTranscriptCollectionResponse, + CallTranscriptResponse, + CardResponseTriggerMetadata, + ChannelIdForTeam, + ChannelIds, + ChannelWithOwnerTeamId, + ChatId, + ChatMessage, + ChatMessageList, + ChatMessageWebhookResponseSchema, + ComposeMessageTriggerMetadata, + ConnectorMetadata, + CreateATeamInput, + CreateATeamResponse, + CreateChannelInput, + CreateChannelResponse, + CreateSectionInput, + CreateTagInput, + CreateTagResponseSchema, + DiscoverySettings, + DraftOpenShift, + DraftShift, + DynamicAiInsightTriggerRequest, + DynamicAtMentionWebhookTriggerResponseSchema, + DynamicCallEventTriggerRequest, + DynamicCardResponseTriggerResult, + DynamicChannelAdaptiveCardRequest, + DynamicChannelFlowContinuationSubscriptionResult, + DynamicChannelNotificationRequest, + DynamicComposeMessageTriggerResult, + DynamicGatherInputSubscriptionResult, + DynamicGetMessageDetailsResponseSchema, + DynamicGetMessageDetailsSchema, + DynamicKeywordWebhookTriggerResponseSchema, + DynamicListMembersSchema, + DynamicNewMessageWebhookTriggerResponseSchema, + DynamicPostCardAndWaitRequest, + DynamicPostCardRequest, + DynamicPostConversationNotificationRequest, + DynamicPostFeedNotificationRequest, + DynamicPostGatherInputToConversationResponse, + DynamicPostMessageRequest, + DynamicPostToConversationResponse, + DynamicRecordingTriggerRequest, + DynamicReplyCardRequest, + DynamicReplyMessageRequest, + DynamicResponseSchema, + DynamicSelectedMessageTriggerResult, + DynamicTranscriptTriggerRequest, + DynamicUpdateCardRequest, + DynamicUserAdaptiveCardRequest, + DynamicUserFlowContinuationSubscriptionResult, + DynamicUserMessageWithOptionsSubscriptionRequest, + DynamicUserMessageWithOptionsSubscriptionResult, + DynamicUserNotificationRequest, + DynamicWebhookTriggerRequestSchema, + EditOpenShiftRequest, + FunSettings, + GetAllAssociatedTeamsResponse, + GetAllChannelsForTeamResponse, + GetAllTeamsResponse, + GetChannelResponse, + GetChannelsForGroupResponse, + GetChatsResponse, + GetFlowContinuationSubscriptionWithPosterOutputMetadataInput, + GetMessageDetailsSchema, + GetMessageLocationsResponse, + GetMessagesFromConversationResponse, + GetOnlineMeetingResponse, + GetTagMembersResponseSchema, + GetTagsResponseSchema, + GetTeamResponse, + GetTimeOffReasonsResponse, + GuestSettings, + LastModifiedBy, + ListMembersResponseSchema, + ListMembersSchema, + ListRepliesResponseSchema, + ListSectionItemsResponse, + ListSectionsResponse, + MemberSettings, + MessageId, + MessageReactionWebhookResponseSchema, + MessagingSettings, + MoveSectionItemInput, + NewChat, + NewChatResponse, + NewMeeting, + NewMeetingResponse, + ObjectEntity, + ObjectWithoutType, + OfferShiftRequestResponse, + OnGroupMemberChangeResponse, + OpenShiftChangeRequestResponse, + OpenShiftResponse, + PostCardAndWaitForResponseInput, + PostCardAndWaitSchema, + PostCardSchema, + PostFeedSchema, + PostMessageSchema, + PostMessageToSelfRequest, + PostToConversationResponse, + RecordingWebhookResponseSchema, + ScheduleResponse, + SchedulingGroupResponse, + SectionItemConflictError, + SectionItemResponse, + SectionResponse, + SelectedMessageTriggerMetadata, + SharedOpenShift, + SharedShift, + ShiftResponse, + SingleTagMemberTriggerRequest, + SingleTagTriggerRequest, + SwapShiftsChangeRequestResponse, + TagMemberWebhookResponseSchema, + TagWebhookResponseSchema, + TeamsIdentitySet, + ThemeEditor, + TimeOffRequestResponse, + TranscriptWebhookResponseSchema, + UnifiedActionSchema, + UpdateChannelPropertiesInput, + UpdateSectionInput, + UpdateTagInput, + VirtualAgentBots, + WebhookChatMessageTriggerInput, + WebhookRequest, + WebhookTriggerSchema, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "TeamsClient", + "Activities", + "AddMemberToChannelInput", + "AddMemberToChatInput", + "AddMemberToTagInput", + "AddMemberToTagResponseSchema", + "AddMemberToTeamInput", + "AddSectionItemInput", + "AiInsightActionItem", + "AiInsightCollectionResponse", + "AiInsightDetailResponse", + "AiInsightMeetingNote", + "AiInsightMeetingNoteSubpoint", + "AiInsightMentionEvent", + "AiInsightResponse", + "AiInsightViewpoint", + "AiInsightWebhookResponseSchema", + "ArchiveChannelInput", + "AssociatedTeamInfo", + "AsyncOperationResponse", + "AtMentionBotResponse", + "AtMentionTagResponse", + "AtMentionUser", + "BotIdForChat", + "BotMentionRequest", + "CallEventWebhookResponseSchema", + "CallRecordingCollectionResponse", + "CallRecordingResponse", + "CallTranscriptCollectionResponse", + "CallTranscriptResponse", + "CardResponseTriggerMetadata", + "ChannelIdForTeam", + "ChannelIds", + "ChannelWithOwnerTeamId", + "ChatId", + "ChatMessage", + "ChatMessageList", + "ChatMessageWebhookResponseSchema", + "ComposeMessageTriggerMetadata", + "ConnectorMetadata", + "CreateATeamInput", + "CreateATeamResponse", + "CreateChannelInput", + "CreateChannelResponse", + "CreateSectionInput", + "CreateTagInput", + "CreateTagResponseSchema", + "DiscoverySettings", + "DraftOpenShift", + "DraftShift", + "DynamicAiInsightTriggerRequest", + "DynamicAtMentionWebhookTriggerResponseSchema", + "DynamicCallEventTriggerRequest", + "DynamicCardResponseTriggerResult", + "DynamicChannelAdaptiveCardRequest", + "DynamicChannelFlowContinuationSubscriptionResult", + "DynamicChannelNotificationRequest", + "DynamicComposeMessageTriggerResult", + "DynamicGatherInputSubscriptionResult", + "DynamicGetMessageDetailsResponseSchema", + "DynamicGetMessageDetailsSchema", + "DynamicKeywordWebhookTriggerResponseSchema", + "DynamicListMembersSchema", + "DynamicNewMessageWebhookTriggerResponseSchema", + "DynamicPostCardAndWaitRequest", + "DynamicPostCardRequest", + "DynamicPostConversationNotificationRequest", + "DynamicPostFeedNotificationRequest", + "DynamicPostGatherInputToConversationResponse", + "DynamicPostMessageRequest", + "DynamicPostToConversationResponse", + "DynamicRecordingTriggerRequest", + "DynamicReplyCardRequest", + "DynamicReplyMessageRequest", + "DynamicResponseSchema", + "DynamicSelectedMessageTriggerResult", + "DynamicTranscriptTriggerRequest", + "DynamicUpdateCardRequest", + "DynamicUserAdaptiveCardRequest", + "DynamicUserFlowContinuationSubscriptionResult", + "DynamicUserMessageWithOptionsSubscriptionRequest", + "DynamicUserMessageWithOptionsSubscriptionResult", + "DynamicUserNotificationRequest", + "DynamicWebhookTriggerRequestSchema", + "EditOpenShiftRequest", + "FunSettings", + "GetAllAssociatedTeamsResponse", + "GetAllChannelsForTeamResponse", + "GetAllTeamsResponse", + "GetChannelResponse", + "GetChannelsForGroupResponse", + "GetChatsResponse", + "GetFlowContinuationSubscriptionWithPosterOutputMetadataInput", + "GetMessageDetailsSchema", + "GetMessageLocationsResponse", + "GetMessagesFromConversationResponse", + "GetOnlineMeetingResponse", + "GetTagMembersResponseSchema", + "GetTagsResponseSchema", + "GetTeamResponse", + "GetTimeOffReasonsResponse", + "GuestSettings", + "LastModifiedBy", + "ListMembersResponseSchema", + "ListMembersSchema", + "ListRepliesResponseSchema", + "ListSectionItemsResponse", + "ListSectionsResponse", + "MemberSettings", + "MessageId", + "MessageReactionWebhookResponseSchema", + "MessagingSettings", + "MoveSectionItemInput", + "NewChat", + "NewChatResponse", + "NewMeeting", + "NewMeetingResponse", + "ObjectEntity", + "ObjectWithoutType", + "OfferShiftRequestResponse", + "OnGroupMemberChangeResponse", + "OpenShiftChangeRequestResponse", + "OpenShiftResponse", + "PostCardAndWaitForResponseInput", + "PostCardAndWaitSchema", + "PostCardSchema", + "PostFeedSchema", + "PostMessageSchema", + "PostMessageToSelfRequest", + "PostToConversationResponse", + "RecordingWebhookResponseSchema", + "ScheduleResponse", + "SchedulingGroupResponse", + "SectionItemConflictError", + "SectionItemResponse", + "SectionResponse", + "SelectedMessageTriggerMetadata", + "SharedOpenShift", + "SharedShift", + "ShiftResponse", + "SingleTagMemberTriggerRequest", + "SingleTagTriggerRequest", + "SwapShiftsChangeRequestResponse", + "TagMemberWebhookResponseSchema", + "TagWebhookResponseSchema", + "TeamsIdentitySet", + "ThemeEditor", + "TimeOffRequestResponse", + "TranscriptWebhookResponseSchema", + "UnifiedActionSchema", + "UpdateChannelPropertiesInput", + "UpdateSectionInput", + "UpdateTagInput", + "VirtualAgentBots", + "WebhookChatMessageTriggerInput", + "WebhookRequest", + "WebhookTriggerSchema", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class TeamsClient(ConnectorClientBase): + """Typed client for teams connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a TeamsClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "teams" + + @staticmethod + def _prepare_match_headers( + headers: Optional[Mapping[str, str]], + etag: Optional[str], + match_condition: Optional[MatchConditions], + *, + if_match_required: bool, + ) -> Optional[Mapping[str, str]]: + request_headers = dict(headers) if headers is not None else {} + existing_if_match = next( + (name for name in request_headers if name.lower() == "if-match"), + None, + ) + if etag is None and match_condition is None: + if if_match_required and existing_if_match is None: + request_headers["If-Match"] = "*" + return request_headers or None + + if existing_if_match is not None: + del request_headers[existing_if_match] + if match_condition is None: + assert etag is not None + request_headers["If-Match"] = etag + elif match_condition == MatchConditions.IfNotModified: + if etag is None: + raise ValueError( + "etag is required for MatchConditions.IfNotModified." + ) + request_headers["If-Match"] = etag + elif match_condition == MatchConditions.Unconditionally: + request_headers["If-Match"] = "*" + else: + raise ValueError( + "If-Match operations support only IfNotModified or Unconditionally." + ) + return request_headers or None + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_teams_meeting( + self, + input: NewMeeting | Mapping[str, Any], + calendarid: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a Teams meeting + + Create a meeting with a link at the bottom of the invite to join the + meeting online on Microsoft Teams. + + Swagger operation ID: `CreateTeamsMeeting`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + calendarid: Select a value. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/me/calendars/{quote(str(calendarid), safe='')}/events" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_all_teams( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List joined teams + + Lists all the teams in Microsoft Teams that you are a member of + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAllTeams`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/beta/me/joinedTeams" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_all_associated_teams( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List associated teams + + Lists all the teams you are a direct member of, or are a member of a + shared channel that is hosted inside the team. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAllAssociatedTeams`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1.0/me/teamwork/associatedTeams" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_channels_for_group( + self, + group_id: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List channels + + Lists all the channels for a specific team + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetChannelsForGroup`. + + Args: + group_id: Select team. + filter: An OData filter query to restrict the entries returned + (e.g. membershipType eq 'standard'). + orderby: An OData orderBy query option for specifying the order of + entries (e.g., displayName asc). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/beta/groups/{quote(str(group_id), safe='')}/channels" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_channel( + self, + input: CreateChannelInput | Mapping[str, Any], + group_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a channel + + Create a new channel within a specified team + + Swagger operation ID: `CreateChannel`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Select team. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/beta/groups/{quote(str(group_id), safe='')}/channels" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_channel( + self, + group_id: str, + channel_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get details for a specific channel in a team + + Get the channel details + + Swagger operation ID: `GetChannel`. + + Args: + group_id: Select team. + channel_id: Channel ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/beta" + f"/teams" + f"/{quote(str(group_id), safe='')}" + f"/channels" + f"/{quote(str(channel_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_channel_properties( + self, + input: UpdateChannelPropertiesInput | Mapping[str, Any], + group_id: str, + channel_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Update channel + + Updates the properties of a channel in a specific team. Only the + properties you provide are changed; omitted properties are left + unchanged. For shared channels, the team ID must refer to the host + team, which is the team that owns the shared channel. + + Swagger operation ID: `UpdateChannelProperties`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Select team. + channel_id: Channel ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/beta" + f"/teams" + f"/{quote(str(group_id), safe='')}" + f"/channels" + f"/{quote(str(channel_id), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + async def archive_channel( + self, + input: ArchiveChannelInput | Mapping[str, Any], + group_id: str, + channel_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Archive a channel + + Archive a channel in a team. When a channel is archived, users can't + send new messages or react to existing messages in the channel, edit + the channel settings, or make other changes to the channel. Archiving + is an asynchronous operation. + + Swagger operation ID: `ArchiveChannel`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Select team. + channel_id: Channel ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(group_id), safe='')}" + f"/channels" + f"/{quote(str(channel_id), safe='')}" + f"/archive" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_all_channels_for_team( + self, + group_id: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all channels + + Lists all the channels for a specific team, including channels that are + shared with the team + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAllChannelsForTeam`. + + Args: + group_id: Select team. + filter: An OData filter query to restrict the entries returned + (e.g. membershipType eq 'standard'). + orderby: An OData orderBy query option for specifying the order of + entries (e.g., displayName asc). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/beta/teams/{quote(str(group_id), safe='')}/allChannels" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_chats( + self, + chat_type: str, + topic: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List chats + + Lists recent chats you are a part of + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetChats`. + + Args: + chat_type: Filter by type. + topic: Filter by whether or not the topic name is defined. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/actions" + f"/listchats" + f"/chattypes" + f"/{quote(str(chat_type), safe='')}" + f"/topic" + f"/{quote(str(topic), safe='')}" + f"/expandmembers" + f"/false" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def post_feed_notification( + self, + input: DynamicPostFeedNotificationRequest | Mapping[str, Any], + poster: str, + notification_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Post a feed notification + + Posts a notification to a user's activity feed linking to a chat or + team. + + Swagger operation ID: `PostFeedNotification`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + poster: Select an option. + notification_type: Choose notification type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/feednotification" + f"/poster" + f"/{quote(str(poster), safe='')}" + f"/notificationType" + f"/{quote(str(notification_type), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def at_mention_tag( + self, + group_id: str, + tag_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get an @mention token for a team tag + + Creates a token that can be inserted into a message or adaptive card + sent as a user in a channel to @mention a team tag. + + Swagger operation ID: `AtMentionTag`. + + Args: + group_id: Select team. + tag_id: Select tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/beta" + f"/teams" + f"/{quote(str(group_id), safe='')}" + f"/tags" + f"/{quote(str(tag_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_messages_from_channel( + self, + group_id: str, + channel_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get messages in a channel + + Gets messages from a channel in a specific team. For shared channels, + the team ID must refer to the host team, which is the team that owns + the shared channel. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMessagesFromChannel`. + + Args: + group_id: Select team. + channel_id: Channel ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/beta" + f"/teams" + f"/{quote(str(group_id), safe='')}" + f"/channels" + f"/{quote(str(channel_id), safe='')}" + f"/messages" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_message_details( + self, + input: DynamicGetMessageDetailsSchema | Mapping[str, Any], + message_id: str, + thread_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get message details + + Gets the details of a message in a chat or a channel. + + Swagger operation ID: `GetMessageDetails`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Message ID. + thread_type: Choose message type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/beta" + f"/teams" + f"/messages" + f"/{quote(str(message_id), safe='')}" + f"/messageType" + f"/{quote(str(thread_type), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_replies_to_message( + self, + group_id: str, + channel_id: str, + message_id: str, + *, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List replies of a channel message + + List replies to a message in a channel in a specific team. For shared + channels, the team ID must refer to the host team, which is the team + that owns the shared channel. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListRepliesToMessage`. + + Args: + group_id: Select team. + channel_id: Channel ID. + message_id: Message ID. + top: The number of latest replies to return. The default value is + 20. The supported value is between 1 and 50. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(group_id), safe='')}" + f"/channels" + f"/{quote(str(channel_id), safe='')}" + f"/messages" + f"/{quote(str(message_id), safe='')}" + f"/replies" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_members( + self, + input: DynamicListMembersSchema | Mapping[str, Any], + thread_type: str, + *, + filter: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List chat or channel members + + List direct members of a group chat or a channel + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListMembers`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + thread_type: Choose message type. + filter: An OData filter query to restrict the entries returned + (e.g. membershipType eq 'standard'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/listmembers" + f"/threadType" + f"/{quote(str(thread_type), safe='')}" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = input + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def subscribe_user_message_with_options( + self, + input: DynamicUserMessageWithOptionsSubscriptionRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Post a choice of options as the Flow bot to a user + + Send a set of options to a Microsoft Teams user, that they must respond + to before the flow will continue. This action will pause the flow until + the user response to the options + + Swagger operation ID: `SubscribeUserMessageWithOptions`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/actions" + f"/messagewithoptions" + f"/recipienttypes" + f"/user" + f"/$subscriptions" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_team( + self, + team_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a team + + Gets the details for a team in Microsoft Teams. + + Swagger operation ID: `GetTeam`. + + Args: + team_id: Select team. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/beta/teams/{quote(str(team_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def at_mention_user( + self, + user_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get an @mention token for a user + + Creates a token that can be inserted into a message or adaptive card to + @mention a user. + + Swagger operation ID: `AtMentionUser`. + + Args: + user_id: Specify a user principal or user ID to @mention. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/users/{quote(str(user_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_chat( + self, + input: NewChat | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a chat + + Creates a one on one or group chat + + Swagger operation ID: `CreateChat`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/beta/chats" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_messages_from_chat( + self, + chat_id: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get messages in a chat + + Retrieves messages from a one on one or group chat + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMessagesFromChat`. + + Args: + chat_id: The chat's unique identifier. + filter: An OData filter query to restrict the entries returned + (e.g. membershipType eq 'standard'). + orderby: An OData orderBy query option for specifying the order of + entries (e.g., displayName asc). + top: An OData top query option for specifying the maximum number of + entries returned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/beta/chats/{quote(str(chat_id), safe='')}/messages" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def post_message_to_self( + self, + input: PostMessageToSelfRequest | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Post a message to myself + + Sends a message to the signed-in user's own Notes chat in Microsoft + Teams. + + Swagger operation ID: `PostMessageToSelf`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1.0/chats/48:notes/messages" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_a_team( + self, + input: CreateATeamInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a team + + Creates a new team in Microsoft Teams + + Swagger operation ID: `CreateATeam`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/beta/teams" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_team_members( + self, + team_id: str, + *, + filter: Optional[str] = None, + top: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List team members + + Lists the members of a team in Microsoft Teams + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTeamMembers`. + + Args: + team_id: Select team. + filter: An OData filter query to restrict the entries returned + (e.g. membershipType eq 'standard'). + top: An OData top query option for specifying the maximum number of + entries returned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/teams/{quote(str(team_id), safe='')}/members" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def add_member_to_team( + self, + input: AddMemberToTeamInput | Mapping[str, Any], + team_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add a member to a team + + Adds a member to a team in Microsoft Teams + + Swagger operation ID: `AddMemberToTeam`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Select team. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/teams/{quote(str(team_id), safe='')}/members" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def remove_member_from_team( + self, + team_id: str, + membership_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Remove a member from a team + + Removes a member from a team in Microsoft Teams + + Swagger operation ID: `RemoveMemberFromTeam`. + + Args: + team_id: Select team. + membership_id: The membership ID of the member to remove from the + team. Use the 'List team members' action to look up the + membership ID for a user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(team_id), safe='')}" + f"/members" + f"/{quote(str(membership_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_member_to_channel( + self, + input: AddMemberToChannelInput | Mapping[str, Any], + group_id: str, + channel_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add a member to a channel + + Adds a member to a channel in Microsoft Teams. The channel must be a + private or shared channel. + + Swagger operation ID: `AddMemberToChannel`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Select team. + channel_id: Channel ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(group_id), safe='')}" + f"/channels" + f"/{quote(str(channel_id), safe='')}" + f"/members" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def remove_member_from_channel( + self, + group_id: str, + channel_id: str, + membership_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Remove a direct member from a channel + + Removes a direct member from a channel in Microsoft Teams. The channel + must be a private or shared channel. + + Swagger operation ID: `RemoveMemberFromChannel`. + + Args: + group_id: Select team. + channel_id: Channel ID. + membership_id: The membership ID of the direct member to remove + from the channel. Use the 'List chat or channel members' action + with thread type 'Channel' to look up the membership ID for a + user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(group_id), safe='')}" + f"/channels" + f"/{quote(str(channel_id), safe='')}" + f"/members" + f"/{quote(str(membership_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def post_message_to_conversation( + self, + input: DynamicPostMessageRequest | Mapping[str, Any], + poster: str, + location: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Post message in a chat or channel + + Posts a message to a chat or a channel + + Swagger operation ID: `PostMessageToConversation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + poster: Select an option. + location: Select an option. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/beta" + f"/teams" + f"/conversation" + f"/message" + f"/poster" + f"/{quote(str(poster), safe='')}" + f"/location" + f"/{quote(str(location), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def reply_with_message_to_conversation( + self, + input: DynamicReplyMessageRequest | Mapping[str, Any], + poster: str, + location: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Reply with a message in a channel + + Replies with a message to a channel's message + + Swagger operation ID: `ReplyWithMessageToConversation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + poster: Select an option. + location: Select an option. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/conversation" + f"/replyWithMessage" + f"/poster" + f"/{quote(str(poster), safe='')}" + f"/location" + f"/{quote(str(location), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def post_card_to_conversation( + self, + input: DynamicPostCardRequest | Mapping[str, Any], + poster: str, + location: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Post card in a chat or channel + + Posts a card to a chat or a channel + + Swagger operation ID: `PostCardToConversation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + poster: Select an option. + location: Select an option. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/conversation" + f"/adaptivecard" + f"/poster" + f"/{quote(str(poster), safe='')}" + f"/location" + f"/{quote(str(location), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def post_card_and_wait_for_response( + self, + input: PostCardAndWaitForResponseInput | Mapping[str, Any], + poster: str, + location: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Post adaptive card and wait for a response + + Posts an adaptive card to a chat or a channel and waits for a response + from any user. This will pause the flow until any user responds. + + Swagger operation ID: `PostCardAndWaitForResponse`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + poster: Select an option. + location: Select an option. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/conversation" + f"/gatherinput" + f"/poster" + f"/{quote(str(poster), safe='')}" + f"/location" + f"/{quote(str(location), safe='')}" + f"/$subscriptions" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def reply_with_card_to_conversation( + self, + input: DynamicReplyCardRequest | Mapping[str, Any], + poster: str, + location: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Reply with an adaptive card in a channel + + Replies with an adaptive card to a channel's message + + Swagger operation ID: `ReplyWithCardToConversation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + poster: Select an option. + location: Select an option. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/conversation" + f"/replyWithAdaptivecard" + f"/poster" + f"/{quote(str(poster), safe='')}" + f"/location" + f"/{quote(str(location), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_card_in_conversation( + self, + input: DynamicUpdateCardRequest | Mapping[str, Any], + poster: str, + location: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update an adaptive card in a chat or channel + + Updates an existing adaptive card + + Swagger operation ID: `UpdateCardInConversation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + poster: Select an option. + location: Select an option. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/conversation" + f"/updateAdaptivecard" + f"/poster" + f"/{quote(str(poster), safe='')}" + f"/location" + f"/{quote(str(location), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def http_request( + self, + input: bytes, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send a Microsoft Graph HTTP request + + Construct a Microsoft Graph REST API request to invoke against the + Microsoft Teams endpoints. These segments are supported: 1st segment: + /teams, /me, /users 2nd segment: channels, chats, installedApps, + messages, pinnedMessages, onlineMeetings. Learn more: + https://docs.microsoft.com/en-us/graph/use-the-api + + Swagger operation ID: `HttpRequest`. + + Args: + input: The binary request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/httprequest" + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_member_to_chat( + self, + input: AddMemberToChatInput | Mapping[str, Any], + chat_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Add a user to a chat + + Adds a user to a chat in Microsoft Teams. + + Swagger operation ID: `AddMemberToChat`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + chat_id: The chat's unique identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/chats/{quote(str(chat_id), safe='')}/members" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def remove_member_from_chat( + self, + chat_id: str, + membership_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Remove a member from a chat + + Removes a member from a chat in Microsoft Teams. Only group chats + support member removal. + + Swagger operation ID: `RemoveMemberFromChat`. + + Args: + chat_id: The chat's unique identifier. + membership_id: The membership ID of the member to remove from the + chat. Use the 'List chat or channel members' action with thread + type 'Group chat' to look up the membership ID for a user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/chats" + f"/{quote(str(chat_id), safe='')}" + f"/members" + f"/{quote(str(membership_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_online_meeting( + self, + lookup_type: str, + lookup_value: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get an online meeting + + Retrieves the properties and relationships of an online meeting. You + can look up a meeting by meeting ID, join web URL, or join meeting ID. + + Swagger operation ID: `GetOnlineMeeting`. + + Args: + lookup_type: Select how to identify the meeting. + lookup_value: The value corresponding to the selected lookup type + (meeting ID, join web URL, or join meeting ID). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1.0/me/onlineMeetings/lookup" + ) + query_params = [] + value = str(lookup_type) + if isinstance(lookup_type, bool): + value = value.lower() + query_params.append(f"lookupType={quote(value, safe='')}") + value = str(lookup_value) + if isinstance(lookup_value, bool): + value = value.lower() + query_params.append(f"lookupValue={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_meeting_transcripts( + self, + meeting_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List meeting transcripts + + Lists all transcripts for an online meeting + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListMeetingTranscripts`. + + Args: + meeting_id: The online meeting ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/me" + f"/onlineMeetings" + f"/{quote(str(meeting_id), safe='')}" + f"/transcripts" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_meeting_transcript( + self, + meeting_id: str, + transcript_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get meeting transcript + + Gets a specific transcript for an online meeting + + Swagger operation ID: `GetMeetingTranscript`. + + Args: + meeting_id: The online meeting ID. + transcript_id: The transcript ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/me" + f"/onlineMeetings" + f"/{quote(str(meeting_id), safe='')}" + f"/transcripts" + f"/{quote(str(transcript_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_meeting_transcript_content( + self, + meeting_id: str, + transcript_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get meeting transcript content + + Gets the content of a meeting transcript + + Swagger operation ID: `GetMeetingTranscriptContent`. + + Args: + meeting_id: The online meeting ID. + transcript_id: The transcript ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/me" + f"/onlineMeetings" + f"/{quote(str(meeting_id), safe='')}" + f"/transcripts" + f"/{quote(str(transcript_id), safe='')}" + f"/content" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_meeting_recordings( + self, + meeting_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List meeting recordings + + Lists all recordings for an online meeting + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListMeetingRecordings`. + + Args: + meeting_id: The online meeting ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/me" + f"/onlineMeetings" + f"/{quote(str(meeting_id), safe='')}" + f"/recordings" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_meeting_recording( + self, + meeting_id: str, + recording_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get meeting recording + + Gets a specific recording for an online meeting + + Swagger operation ID: `GetMeetingRecording`. + + Args: + meeting_id: The online meeting ID. + recording_id: The recording ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/me" + f"/onlineMeetings" + f"/{quote(str(meeting_id), safe='')}" + f"/recordings" + f"/{quote(str(recording_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_meeting_recording_content( + self, + meeting_id: str, + recording_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get meeting recording content + + Gets the content stream of a meeting recording + + Swagger operation ID: `GetMeetingRecordingContent`. + + Args: + meeting_id: The online meeting ID. + recording_id: The recording ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/me" + f"/onlineMeetings" + f"/{quote(str(meeting_id), safe='')}" + f"/recordings" + f"/{quote(str(recording_id), safe='')}" + f"/content" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + def list_sections( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List sections + + Lists the current user's teamwork sections + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListSections`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/beta/me/teamwork/sections" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_section( + self, + input: CreateSectionInput | Mapping[str, Any], + *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a section + + Creates a new teamwork section for the current user + + Swagger operation ID: `CreateSection`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + + request_url = ( + f"{self._connection_runtime_url}/beta/me/teamwork/sections" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_section( + self, + section_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a section + + Gets a specific teamwork section by ID + + Swagger operation ID: `GetSection`. + + Args: + section_id: The section ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/beta/me/teamwork/sections/{quote(str(section_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_section( + self, + input: UpdateSectionInput | Mapping[str, Any], + section_id: str, + *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a section + + Updates a teamwork section for the current user + + Swagger operation ID: `UpdateSection`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + section_id: The section ID. + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + + request_url = ( + f"{self._connection_runtime_url}" + f"/beta/me/teamwork/sections/{quote(str(section_id), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_section( + self, + section_id: str, + *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a section + + Deletes a teamwork section for the current user + + Swagger operation ID: `DeleteSection`. + + Args: + section_id: The section ID. + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + + request_url = ( + f"{self._connection_runtime_url}" + f"/beta/me/teamwork/sections/{quote(str(section_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_section_items( + self, + section_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List section items + + Lists the items (chats, channels, meetings, communities) in a teamwork + section. Each item belongs to exactly one section at a time. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListSectionItems`. + + Args: + section_id: The section ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/beta" + f"/me" + f"/teamwork" + f"/sections" + f"/{quote(str(section_id), safe='')}" + f"/items" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def add_section_item( + self, + input: AddSectionItemInput | Mapping[str, Any], + section_id: str, + *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add an item to a section + + Adds an item (chat, channel, meeting, or community) currently in a + system-defined section to a user-defined teamwork section. Use Move + Section Item to relocate items already in another user-defined section. + + Swagger operation ID: `AddSectionItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + section_id: The section ID. + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + + request_url = ( + f"{self._connection_runtime_url}" + f"/beta" + f"/me" + f"/teamwork" + f"/sections" + f"/{quote(str(section_id), safe='')}" + f"/items" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def remove_section_item( + self, + section_id: str, + section_item_id: str, + *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Remove an item from a section + + Removes an item from a user-defined teamwork section. The underlying + chat, channel, meeting, or community is not deleted; the item returns + to its default system-defined section. + + Swagger operation ID: `RemoveSectionItem`. + + Args: + section_id: The section ID. + section_item_id: The section item ID (the conversation ID of the + underlying chat, channel, meeting, or community). + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + + request_url = ( + f"{self._connection_runtime_url}" + f"/beta" + f"/me" + f"/teamwork" + f"/sections" + f"/{quote(str(section_id), safe='')}" + f"/items" + f"/{quote(str(section_item_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def move_section_item( + self, + input: MoveSectionItemInput | Mapping[str, Any], + section_id: str, + section_item_id: str, + *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Move a section item + + Atomically moves an item from one user-defined teamwork section to + another user-defined section. Each item can belong to only one section + at a time. This action removes the item from its current section and + adds it to the target section. + + Swagger operation ID: `MoveSectionItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + section_id: The section ID. + section_item_id: The section item ID (the conversation ID of the + underlying chat, channel, meeting, or community). + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + + request_url = ( + f"{self._connection_runtime_url}" + f"/beta" + f"/me" + f"/teamwork" + f"/sections" + f"/{quote(str(section_id), safe='')}" + f"/items" + f"/{quote(str(section_item_id), safe='')}" + f"/move" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tags( + self, + group_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all tags for a team + + Lists the team's tags + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTags`. + + Args: + group_id: Select team. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/teams/{quote(str(group_id), safe='')}/tags" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_tag( + self, + input: CreateTagInput | Mapping[str, Any], + group_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a tag for a team + + Creates a tag in a team + + Swagger operation ID: `CreateTag`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Select team. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/teams/{quote(str(group_id), safe='')}/tags" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_tag( + self, + group_id: str, + tag_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a team tag + + Gets a specific tag by ID from a team + + Swagger operation ID: `GetTag`. + + Args: + group_id: Select team. + tag_id: Select tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(group_id), safe='')}" + f"/tags" + f"/{quote(str(tag_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_tag( + self, + input: UpdateTagInput | Mapping[str, Any], + group_id: str, + tag_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a team tag + + Updates the display name of a tag in a team + + Swagger operation ID: `UpdateTag`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Select team. + tag_id: Select tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(group_id), safe='')}" + f"/tags" + f"/{quote(str(tag_id), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_tag( + self, + group_id: str, + tag_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a team tag + + Deletes a tag from a team + + Swagger operation ID: `DeleteTag`. + + Args: + group_id: Select team. + tag_id: Select tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(group_id), safe='')}" + f"/tags" + f"/{quote(str(tag_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def add_member_to_tag( + self, + input: AddMemberToTagInput | Mapping[str, Any], + group_id: str, + tag_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add a member to a team tag + + Adds a user to a team tag + + Swagger operation ID: `AddMemberToTag`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Select team. + tag_id: Select tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(group_id), safe='')}" + f"/tags" + f"/{quote(str(tag_id), safe='')}" + f"/members" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tag_members( + self, + group_id: str, + tag_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List the members of a team tag + + Lists the members of a team tag + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTagMembers`. + + Args: + group_id: Select team. + tag_id: Select tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(group_id), safe='')}" + f"/tags" + f"/{quote(str(tag_id), safe='')}" + f"/members" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def delete_tag_member( + self, + group_id: str, + tag_id: str, + tag_member_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a member from a team tag + + Deletes a member from a team tag + + Swagger operation ID: `DeleteTagMember`. + + Args: + group_id: Select team. + tag_id: Select tag. + tag_member_id: ID of the member to remove from the tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/teams" + f"/{quote(str(group_id), safe='')}" + f"/tags" + f"/{quote(str(tag_id), safe='')}" + f"/members" + f"/{quote(str(tag_member_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_call_recordings( + self, + call_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List call recordings + + Lists all recordings for an ad-hoc call + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListCallRecordings`. + + Args: + call_id: The call ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/me/adhocCalls/{quote(str(call_id), safe='')}/recordings" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_call_recording( + self, + call_id: str, + recording_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get call recording + + Gets a specific recording for an ad-hoc call + + Swagger operation ID: `GetCallRecording`. + + Args: + call_id: The call ID. + recording_id: The recording ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/me" + f"/adhocCalls" + f"/{quote(str(call_id), safe='')}" + f"/recordings" + f"/{quote(str(recording_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_call_recording_content( + self, + call_id: str, + recording_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Get call recording content + + Gets the content of a call recording + + Swagger operation ID: `GetCallRecordingContent`. + + Args: + call_id: The call ID. + recording_id: The recording ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/me" + f"/adhocCalls" + f"/{quote(str(call_id), safe='')}" + f"/recordings" + f"/{quote(str(recording_id), safe='')}" + f"/content" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + def list_call_transcripts( + self, + call_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List call transcripts + + Lists all transcripts for an ad-hoc call + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListCallTranscripts`. + + Args: + call_id: The call ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/me/adhocCalls/{quote(str(call_id), safe='')}/transcripts" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_call_transcript( + self, + call_id: str, + transcript_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get call transcript + + Gets a specific transcript for an ad-hoc call + + Swagger operation ID: `GetCallTranscript`. + + Args: + call_id: The call ID. + transcript_id: The transcript ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/me" + f"/adhocCalls" + f"/{quote(str(call_id), safe='')}" + f"/transcripts" + f"/{quote(str(transcript_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_call_transcript_content( + self, + call_id: str, + transcript_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get call transcript content + + Gets the content of a call transcript + + Swagger operation ID: `GetCallTranscriptContent`. + + Args: + call_id: The call ID. + transcript_id: The transcript ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/me" + f"/adhocCalls" + f"/{quote(str(call_id), safe='')}" + f"/transcripts" + f"/{quote(str(transcript_id), safe='')}" + f"/content" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_all_adhoc_call_recordings( + self, + *, + start_date_time: Optional[str] = None, + end_date_time: Optional[str] = None, + top: Optional[int] = None, + skiptoken: Optional[str] = None, + deltatoken: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get all ad-hoc call recordings + + Gets all recordings from ad-hoc calls for the signed-in user + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAllAdhocCallRecordings`. + + Args: + start_date_time: The start date and time to filter recordings. + end_date_time: The end date and time to filter recordings. + top: The number of recordings to return. + skiptoken: The skip token for pagination. + deltatoken: The delta token for tracking changes. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/me/adhocCalls/getAllRecordings" + ) + query_params = [] + if start_date_time is not None: + value = str(start_date_time) + if isinstance(start_date_time, bool): + value = value.lower() + query_params.append(f"startDateTime={quote(value, safe='')}") + if end_date_time is not None: + value = str(end_date_time) + if isinstance(end_date_time, bool): + value = value.lower() + query_params.append(f"endDateTime={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skiptoken is not None: + value = str(skiptoken) + if isinstance(skiptoken, bool): + value = value.lower() + query_params.append(f"$skiptoken={quote(value, safe='')}") + if deltatoken is not None: + value = str(deltatoken) + if isinstance(deltatoken, bool): + value = value.lower() + query_params.append(f"$deltatoken={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_all_adhoc_call_transcripts( + self, + *, + start_date_time: Optional[str] = None, + end_date_time: Optional[str] = None, + top: Optional[int] = None, + skiptoken: Optional[str] = None, + deltatoken: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get all ad-hoc call transcripts + + Gets all transcripts from ad-hoc calls for the signed-in user + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAllAdhocCallTranscripts`. + + Args: + start_date_time: The start date and time to filter transcripts. + end_date_time: The end date and time to filter transcripts. + top: The number of transcripts to return. + skiptoken: The skip token for pagination. + deltatoken: The delta token for tracking changes. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0/me/adhocCalls/getAllTranscripts" + ) + query_params = [] + if start_date_time is not None: + value = str(start_date_time) + if isinstance(start_date_time, bool): + value = value.lower() + query_params.append(f"startDateTime={quote(value, safe='')}") + if end_date_time is not None: + value = str(end_date_time) + if isinstance(end_date_time, bool): + value = value.lower() + query_params.append(f"endDateTime={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skiptoken is not None: + value = str(skiptoken) + if isinstance(skiptoken, bool): + value = value.lower() + query_params.append(f"$skiptoken={quote(value, safe='')}") + if deltatoken is not None: + value = str(deltatoken) + if isinstance(deltatoken, bool): + value = value.lower() + query_params.append(f"$deltatoken={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_ai_insights( + self, + meeting_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List AI insights + + Lists AI-generated insights for an online meeting. Requires Microsoft + 365 Copilot license. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListAiInsights`. + + Args: + meeting_id: The online meeting ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/copilot" + f"/me" + f"/onlineMeetings" + f"/{quote(str(meeting_id), safe='')}" + f"/aiInsights" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_ai_insight( + self, + meeting_id: str, + ai_insight_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get AI insight + + Gets a specific AI-generated insight for an online meeting. Requires + Microsoft 365 Copilot license. + + Swagger operation ID: `GetAiInsight`. + + Args: + meeting_id: The online meeting ID. + ai_insight_id: The AI insight ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1.0" + f"/copilot" + f"/me" + f"/onlineMeetings" + f"/{quote(str(meeting_id), safe='')}" + f"/aiInsights" + f"/{quote(str(ai_insight_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_message_locations( + self, + message_type: str, + poster: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Conversation location for where to post + + Returns a list of locations to post a message or reply based on who the + user is posting as + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMessageLocations`. + + Args: + message_type: Message Type. + poster: Select an option. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/messageType" + f"/{quote(str(message_type), safe='')}" + f"/poster" + f"/{quote(str(poster), safe='')}" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("locations", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_message_details_input_schema( + self, + thread_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get message details response schema + + Get the schema information for get message details response + + Swagger operation ID: `GetMessageDetailsInputSchema`. + + Args: + thread_type: Choose message type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/getmessagedetailsinputschema" + f"/threadType" + f"/{quote(str(thread_type), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_message_details_response_schema( + self, + thread_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get message details input metadata + + Get the schema information for message inputs + + Swagger operation ID: `GetMessageDetailsResponseSchema`. + + Args: + thread_type: Choose message type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/getmessagedetailsresponseschema" + f"/threadType" + f"/{quote(str(thread_type), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def list_members_input_schema( + self, + thread_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + List members input schema + + Get the schema information for list members input based on thread type + + Swagger operation ID: `ListMembersInputSchema`. + + Args: + thread_type: Choose message type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/listmembersinputschema" + f"/threadType" + f"/{quote(str(thread_type), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_feed_notification_input_schema( + self, + poster: str, + notification_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get feed notification input metadata + + Get the schema information for feed notification + + Swagger operation ID: `GetFeedNotificationInputSchema`. + + Args: + poster: Select an option. + notification_type: Choose notification type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/getfeednotificationinputschema" + f"/poster" + f"/{quote(str(poster), safe='')}" + f"/notificationType" + f"/{quote(str(notification_type), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_unified_action_schema( + self, + action_type: str, + poster: str, + recipient_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get unified action input metadata + + Get the schema information for unified actions + + Swagger operation ID: `GetUnifiedActionSchema`. + + Args: + action_type: Unified Action. + poster: Select an option. + recipient_type: Type of the recipient of the action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/actions" + f"/{quote(str(action_type), safe='')}" + f"/posters" + f"/{quote(str(poster), safe='')}" + f"/recipienttypes" + f"/{quote(str(recipient_type), safe='')}" + f"/schema" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_message_with_options_subscription_input_metadata( + self, + recipient_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get message with options subscription input metadata + + Get the schema information for the message with options subscription + inputs + + Swagger operation ID: `GetMessageWithOptionsSubscriptionInputMetadata`. + + Args: + recipient_type: Type of the recipient of the action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/actions" + f"/messagewithoptions" + f"/recipienttypes" + f"/{quote(str(recipient_type), safe='')}" + f"/$metadata.json" + f"/subscriptioninputs" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_message_with_options_subscription_output_metadata( + self, + recipient_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get message with options subscription output metadata + + Get the schema information for the message with options subscription + outputs + + Swagger operation ID: + `GetMessageWithOptionsSubscriptionOutputMetadata`. + + Args: + recipient_type: Type of the recipient of the action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/actions" + f"/messagewithoptions" + f"/recipienttypes" + f"/{quote(str(recipient_type), safe='')}" + f"/$metadata.json" + f"/subscriptionoutputs" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_webhook_trigger_request_schema( + self, + thread_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Input schema for webhook trigger + + Gets the input schema for webhook trigger + + Swagger operation ID: `GetWebhookTriggerRequestSchema`. + + Args: + thread_type: Choose message type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/webhookTrigger" + f"/inputSchema" + f"/threadType" + f"/{quote(str(thread_type), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_webhook_trigger_response_schema( + self, + trigger_type: str, + thread_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Response schema for webhook trigger + + Gets the response schema for webhook trigger + + Swagger operation ID: `GetWebhookTriggerResponseSchema`. + + Args: + trigger_type: Trigger type. + thread_type: Choose message type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/webhookTrigger" + f"/triggerType" + f"/{quote(str(trigger_type), safe='')}" + f"/responseSchema" + f"/threadType" + f"/{quote(str(thread_type), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_post_to_conversation_response_schema( + self, + action_type: str, + poster: str, + recipient_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get response schema + + Get the schema information for unified action responses + + Swagger operation ID: `GetPostToConversationResponseSchema`. + + Args: + action_type: Unified Action. + poster: Select an option. + recipient_type: Type of the recipient of the action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/actions" + f"/{quote(str(action_type), safe='')}" + f"/posters" + f"/{quote(str(poster), safe='')}" + f"/recipienttypes" + f"/{quote(str(recipient_type), safe='')}" + f"/response" + f"/schema" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_flow_continuation_subscription_with_poster_output_metadata( + self, + input: GetFlowContinuationSubscriptionWithPosterOutputMetadataInput, + poster: str, + recipient_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get flow continuation subscription output metadata + + Get the schema information for the flow continuation subscription + outputs + + Swagger operation ID: + `GetFlowContinuationSubscriptionWithPosterOutputMetadata`. + + Args: + input: The request body. + poster: Select an option. + recipient_type: Type of the recipient of the action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/flowbot" + f"/actions" + f"/flowcontinuation" + f"/posters" + f"/{quote(str(poster), safe='')}" + f"/recipienttypes" + f"/{quote(str(recipient_type), safe='')}" + f"/$metadata.json" + f"/subscriptionoutputs" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_subscription_scope_schema( + self, + scope_type: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get subscription scope input schema + + Returns the input schema for a subscription trigger based on the + selected scope type. + + Swagger operation ID: `GetSubscriptionScopeSchema`. + + Args: + scope_type: The selected scope type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/internalparameters" + f"/triggers" + f"/subscriptionscope" + f"/{quote(str(scope_type), safe='')}" + f"/schema" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/textrequest.py b/src/azure/connectors/aio/textrequest.py new file mode 100644 index 0000000..adcc56b --- /dev/null +++ b/src/azure/connectors/aio/textrequest.py @@ -0,0 +1,2538 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# TextrequestClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.textrequest import ( + BulkUpdateContactsInput, + CancelPaymentResponse, + CreateContactInput, + CreateContactResponse, + CreateDashboardInput, + CreateDashboardResponse, + CreateGroupInput, + CreateGroupResponse, + CreatePaymentInput, + CreatePaymentResponse, + GetContactByPhoneNumberResponse, + GetContactsResponse, + GetConversationsResponse, + GetDashboardResponse, + GetDashboardsResponse, + GetGroupByIdResponse, + GetGroupsResponse, + GetMessagesByContactPhoneResponse, + GetPaymentResponse, + GetPaymentsResponse, + GetTagsResponse, + MarkPaymentPaidResponse, + SendMessageByPhoneNumberInput, + SendMessageByPhoneNumberResponse, + SendPaymentReminderResponse, + TextingWebhookInput, + TextingWebhookResponse, + UpdateDashboardsNameInput, + UpdateDashboardsNameResponse, + UpdateGroupInput, + UpdateGroupResponse, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "TextrequestClient", + "BulkUpdateContactsInput", + "CancelPaymentResponse", + "CreateContactInput", + "CreateContactResponse", + "CreateDashboardInput", + "CreateDashboardResponse", + "CreateGroupInput", + "CreateGroupResponse", + "CreatePaymentInput", + "CreatePaymentResponse", + "GetContactByPhoneNumberResponse", + "GetContactsResponse", + "GetConversationsResponse", + "GetDashboardResponse", + "GetDashboardsResponse", + "GetGroupByIdResponse", + "GetGroupsResponse", + "GetMessagesByContactPhoneResponse", + "GetPaymentResponse", + "GetPaymentsResponse", + "GetTagsResponse", + "MarkPaymentPaidResponse", + "SendMessageByPhoneNumberInput", + "SendMessageByPhoneNumberResponse", + "SendPaymentReminderResponse", + "TextingWebhookInput", + "TextingWebhookResponse", + "UpdateDashboardsNameInput", + "UpdateDashboardsNameResponse", + "UpdateGroupInput", + "UpdateGroupResponse", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class TextrequestClient(ConnectorClientBase): + """Typed client for textrequest connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a TextrequestClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "textrequest" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_messages_by_contact_phone( + self, + dashboard_id: int, + phone_number: str, + page: int, + page_size: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get a conversation's messages by a contact's phone number + + Get the conversation between the specified dashboard and phone number. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMessagesByContactPhone`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + phone_number: Phone number of the contact to get messages for. + page: The page of entities to get. When getting values, there is a + max size per page, defined by page_size. If page is greater + than the last page, an empty array will be returned. + page_size: The size of each page to get. When getting values, this + is a max size per page, with accessing subsequent pages done by + the page parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards" + f"/{quote(str(dashboard_id), safe='')}" + f"/contacts" + f"/{quote(str(phone_number), safe='')}" + f"/messages" + ) + query_params = [] + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + value = str(page_size) + if isinstance(page_size, bool): + value = value.lower() + query_params.append(f"page_size={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def send_message_by_phone_number( + self, + input: SendMessageByPhoneNumberInput | Mapping[str, Any], + dashboard_id: int, + phone_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send a message to the contact with the given phone number + + Sends a message (starting a new conversation if the given phone number + has no message history). + + Swagger operation ID: `SendMessageByPhoneNumber`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + phone_number: Phone number of the contact to send a message to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards" + f"/{quote(str(dashboard_id), safe='')}" + f"/contacts" + f"/{quote(str(phone_number), safe='')}" + f"/messages" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def archive_conversation( + self, + dashboard_id: int, + phone_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Archive a Conversation + + Archives a conversation, removing it from the results of all + conversation retrieval endpoints. A conversation will be automatically + unarchived if the customer sends a text to your Text Request number, or + if you send the customer a text from your Text Request number. + Archiving conversations is a good way to remove clutter from customers + you don't plan on talking to in the future. Note that if a customer + texts in \"STOP\" to prevent you from sending them any further SMS + messages, the conversation is automatically archived. + + Swagger operation ID: `ArchiveConversation`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + phone_number: Phone number of the conversation to archive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards" + f"/{quote(str(dashboard_id), safe='')}" + f"/contacts" + f"/{quote(str(phone_number), safe='')}" + f"/conversations" + f"/archive" + ) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def unarchive_conversation( + self, + dashboard_id: int, + phone_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Unarchive a Conversation + + Unarchives a conversation. Once a conversation is unarchived, it will + once again appear in the queue. it will also appear in conversations + returned by the /conversations endpoint. If a conversation is already + unarchived, this method has no effect. + + Swagger operation ID: `UnarchiveConversation`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + phone_number: Phone number of the conversation to archive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards" + f"/{quote(str(dashboard_id), safe='')}" + f"/contacts" + f"/{quote(str(phone_number), safe='')}" + f"/conversations" + f"/unarchive" + ) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_contact_by_phone_number( + self, + dashboard_id: int, + phone_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Gets the contact with the specified phone number + + Gets the contact with the specified phone number + + Swagger operation ID: `GetContactByPhoneNumber`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + phone_number: Phone number of the contact to get. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards" + f"/{quote(str(dashboard_id), safe='')}" + f"/contacts" + f"/{quote(str(phone_number), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_contact( + self, + dashboard_id: int, + phone_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Deletes the contact with the specified phone number + + Deletes the contact with the specified phone number + + Swagger operation ID: `DeleteContact`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + phone_number: Phone number of the contact to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards" + f"/{quote(str(dashboard_id), safe='')}" + f"/contacts" + f"/{quote(str(phone_number), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_contact( + self, + input: CreateContactInput | Mapping[str, Any], + dashboard_id: int, + phone_number: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create or update a contact + + Creates or updates a contact (depending on whether one already exists + with the given phone number). + + Swagger operation ID: `CreateContact`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + phone_number: Phone number of the contact to create or update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards" + f"/{quote(str(dashboard_id), safe='')}" + f"/contacts" + f"/{quote(str(phone_number), safe='')}" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_contacts( + self, + dashboard_id: int, + page: int, + page_size: int, + *, + contact_phone_number: Optional[str] = None, + last_message_timestamp_before_utc: Optional[str] = None, + last_message_timestamp_after_utc: Optional[str] = None, + contact_created_before: Optional[str] = None, + contact_created_after: Optional[str] = None, + is_resolved: Optional[bool] = None, + is_blocked: Optional[bool] = None, + is_archived: Optional[bool] = None, + is_suppressed: Optional[bool] = None, + has_opted_out: Optional[bool] = None, + last_message_sent_before: Optional[str] = None, + last_message_sent_after: Optional[str] = None, + last_message_received_before: Optional[str] = None, + last_message_received_after: Optional[str] = None, + tags: Optional[str] = None, + groups: Optional[str] = None, + custom_field_id1: Optional[str] = None, + custom_field_value1: Optional[str] = None, + custom_field_id2: Optional[str] = None, + custom_field_value2: Optional[str] = None, + custom_field_id3: Optional[str] = None, + custom_field_value3: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get all contacts that match the specified filtering criterion + + Gets all contacts that match the specified filtering criterion. Only + the dashboard specified will be searched; there is no account level + search for a number available. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetContacts`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + page: The page of entities to get. When getting values, there is a + max size per page, defined by page_size. If page is greater + than the last page, an empty array will be returned. + page_size: The size of each page to get. When getting values, this + is a max size per page, with accessing subsequent pages done by + the page parameter. + contact_phone_number: Phone number to filter contacts by. + last_message_timestamp_before_utc: Cutoff time for searching + contacts by the last message sent or received. No contacts who + sent messages after this time will be shown. + last_message_timestamp_after_utc: Cutoff time for searching + contacts by the last message sent or received. No contacts + whose last sent message is before this time will be shown. + contact_created_before: Cutoff time for searching contacts by when + they were created. No contacts created after this time will be + shown. + contact_created_after: Cutoff time for searching contacts by when + they were created. No contacts created before this time will be + shown. + is_resolved: Whether to search for contacts whose conversations + have been resolved. + is_blocked: Whether to search for contacts who have been blocked. + is_archived: Whether to search for contacts who have been archived. + is_suppressed: Whether to search for contacts who have been + suppressed. + has_opted_out: Whether to search for contacts who have opted out of + receiving texts. + last_message_sent_before: Cutoff time for searching contacts by + when the last message was sent to the customer. No contacts who + sent messages after this time will be shown. Uses timestamp as + local time. To filter by time stamp in UTC time, use + last_message_sent_before_utc. + last_message_sent_after: Cutoff time for searching contacts by when + the last message was sent to the customer. No contacts whose + last sent message is before this time will be shown. Uses + timestamp as local time. To filter by time stamp in UTC time, + use last_message_sent_after_utc. + last_message_received_before: Cutoff time for searching contacts by + the last message received from the customer. No contacts who + received messages after this time will be shown. Uses timestamp + as local time. To filter by time stamp in UTC time, use + last_message_sent_before_utc. + last_message_received_after: Cutoff time for searching contacts by + the last message received from the customer. No contacts whose + last sent message is before this time will be shown. Uses + timestamp as local time. To filter by time stamp in UTC time, + use last_message_sent_before_utc. + tags: Comma-separated list of guids referring to tags to filter + contacts by. + groups: Comma-separated list of integer ids referring to groups to + filter contacts by. + custom_field_id1: Guid referring to custom field to filter contacts + by. + custom_field_value1: Value referring to custom field to filter + contacts by. + custom_field_id2: Guid referring to second custom field to filter + contacts by. + custom_field_value2: Value referring to second custom field to + filter contacts by. + custom_field_id3: Guid referring to third custom field to filter + contacts by. + custom_field_value3: Value referring to third custom field to + filter contacts by. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards/{quote(str(dashboard_id), safe='')}/contacts" + ) + query_params = [] + if contact_phone_number is not None: + value = str(contact_phone_number) + if isinstance(contact_phone_number, bool): + value = value.lower() + query_params.append(f"contact_phone_number={quote(value, safe='')}") + if last_message_timestamp_before_utc is not None: + value = str(last_message_timestamp_before_utc) + if isinstance(last_message_timestamp_before_utc, bool): + value = value.lower() + query_params.append(f"last_message_timestamp_before_utc={quote(value, safe='')}") + if last_message_timestamp_after_utc is not None: + value = str(last_message_timestamp_after_utc) + if isinstance(last_message_timestamp_after_utc, bool): + value = value.lower() + query_params.append(f"last_message_timestamp_after_utc={quote(value, safe='')}") + if contact_created_before is not None: + value = str(contact_created_before) + if isinstance(contact_created_before, bool): + value = value.lower() + query_params.append(f"contact_created_before={quote(value, safe='')}") + if contact_created_after is not None: + value = str(contact_created_after) + if isinstance(contact_created_after, bool): + value = value.lower() + query_params.append(f"contact_created_after={quote(value, safe='')}") + if is_resolved is not None: + value = str(is_resolved) + if isinstance(is_resolved, bool): + value = value.lower() + query_params.append(f"is_resolved={quote(value, safe='')}") + if is_blocked is not None: + value = str(is_blocked) + if isinstance(is_blocked, bool): + value = value.lower() + query_params.append(f"is_blocked={quote(value, safe='')}") + if is_archived is not None: + value = str(is_archived) + if isinstance(is_archived, bool): + value = value.lower() + query_params.append(f"is_archived={quote(value, safe='')}") + if is_suppressed is not None: + value = str(is_suppressed) + if isinstance(is_suppressed, bool): + value = value.lower() + query_params.append(f"is_suppressed={quote(value, safe='')}") + if has_opted_out is not None: + value = str(has_opted_out) + if isinstance(has_opted_out, bool): + value = value.lower() + query_params.append(f"has_opted_out={quote(value, safe='')}") + if last_message_sent_before is not None: + value = str(last_message_sent_before) + if isinstance(last_message_sent_before, bool): + value = value.lower() + query_params.append(f"last_message_sent_before={quote(value, safe='')}") + if last_message_sent_after is not None: + value = str(last_message_sent_after) + if isinstance(last_message_sent_after, bool): + value = value.lower() + query_params.append(f"last_message_sent_after={quote(value, safe='')}") + if last_message_received_before is not None: + value = str(last_message_received_before) + if isinstance(last_message_received_before, bool): + value = value.lower() + query_params.append(f"last_message_received_before={quote(value, safe='')}") + if last_message_received_after is not None: + value = str(last_message_received_after) + if isinstance(last_message_received_after, bool): + value = value.lower() + query_params.append(f"last_message_received_after={quote(value, safe='')}") + if tags is not None: + value = str(tags) + if isinstance(tags, bool): + value = value.lower() + query_params.append(f"tags={quote(value, safe='')}") + if groups is not None: + value = str(groups) + if isinstance(groups, bool): + value = value.lower() + query_params.append(f"groups={quote(value, safe='')}") + if custom_field_id1 is not None: + value = str(custom_field_id1) + if isinstance(custom_field_id1, bool): + value = value.lower() + query_params.append(f"custom_field_id_1={quote(value, safe='')}") + if custom_field_value1 is not None: + value = str(custom_field_value1) + if isinstance(custom_field_value1, bool): + value = value.lower() + query_params.append(f"custom_field_value_1={quote(value, safe='')}") + if custom_field_id2 is not None: + value = str(custom_field_id2) + if isinstance(custom_field_id2, bool): + value = value.lower() + query_params.append(f"custom_field_id_2={quote(value, safe='')}") + if custom_field_value2 is not None: + value = str(custom_field_value2) + if isinstance(custom_field_value2, bool): + value = value.lower() + query_params.append(f"custom_field_value_2={quote(value, safe='')}") + if custom_field_id3 is not None: + value = str(custom_field_id3) + if isinstance(custom_field_id3, bool): + value = value.lower() + query_params.append(f"custom_field_id_3={quote(value, safe='')}") + if custom_field_value3 is not None: + value = str(custom_field_value3) + if isinstance(custom_field_value3, bool): + value = value.lower() + query_params.append(f"custom_field_value_3={quote(value, safe='')}") + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + value = str(page_size) + if isinstance(page_size, bool): + value = value.lower() + query_params.append(f"page_size={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def bulk_update_contacts( + self, + input: BulkUpdateContactsInput, + dashboard_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Bulk update contacts + + Only the dashboard specified will have contacts added; contacts are + organized by dashboard, and there is no account level search for a + number available. + + Swagger operation ID: `BulkUpdateContacts`. + + Args: + input: The request body. + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards/{quote(str(dashboard_id), safe='')}/contacts" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_group_by_id( + self, + dashboard_id: int, + group_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a group by its id + + Gets the group with the specified id. + + Swagger operation ID: `GetGroupById`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + group_id: The numerical id of the group to get. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards" + f"/{quote(str(dashboard_id), safe='')}" + f"/groups" + f"/{quote(str(group_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_group( + self, + dashboard_id: int, + group_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Deletes the group with the specified id + + Deletes the group with the specified id. This will succeed even if + there are contacts that are members of the group (the contacts will not + be deleted). + + Swagger operation ID: `DeleteGroup`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + group_id: The numerical id of the group to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards" + f"/{quote(str(dashboard_id), safe='')}" + f"/groups" + f"/{quote(str(group_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_group( + self, + input: UpdateGroupInput | Mapping[str, Any], + dashboard_id: int, + group_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Updates a group with the given id + + Updates a group's name using the group's numerical id. If the passed in + group id does not exist, the call will fail. + + Swagger operation ID: `UpdateGroup`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + group_id: The numerical id of the group to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards" + f"/{quote(str(dashboard_id), safe='')}" + f"/groups" + f"/{quote(str(group_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_groups( + self, + dashboard_id: int, + page: int, + page_size: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Gets all groups + + Gets all groups for the user's account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetGroups`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + page: The page of entities to get. When getting values, there is a + max size per page, defined by page_size. If page is greater + than the last page, an empty array will be returned. + page_size: The size of each page to get. When getting values, this + is a max size per page, with accessing subsequent pages done by + the page parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards/{quote(str(dashboard_id), safe='')}/groups" + ) + query_params = [] + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + value = str(page_size) + if isinstance(page_size, bool): + value = value.lower() + query_params.append(f"page_size={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_group( + self, + input: CreateGroupInput | Mapping[str, Any], + dashboard_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Creates a new group + + Creates a new group with the provided name. + + Swagger operation ID: `CreateGroup`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards/{quote(str(dashboard_id), safe='')}/groups" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_tags( + self, + dashboard_id: int, + page: int, + page_size: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Gets all tags + + Gets all the tags for this dashboard. Tags are unique between + dashboards. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTags`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + page: The page of entities to get. When getting values, there is a + max size per page, defined by page_size. If page is greater + than the last page, an empty array will be returned. + page_size: The size of each page to get. When getting values, this + is a max size per page, with accessing subsequent pages done by + the page parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards/{quote(str(dashboard_id), safe='')}/tags" + ) + query_params = [] + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + value = str(page_size) + if isinstance(page_size, bool): + value = value.lower() + query_params.append(f"page_size={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_custom_fields( + self, + dashboard_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Gets all custom fields + + Gets all custom fields for this dashboard. Custom fields are unique + between dashboards. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetCustomFields`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards/{quote(str(dashboard_id), safe='')}/fields" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_payment( + self, + dashboard_id: int, + payment_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Gets the payment with the specified id + + Gets the payment with the specified id. + + Swagger operation ID: `GetPayment`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + payment_id: The numerical id of the payment to get. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards" + f"/{quote(str(dashboard_id), safe='')}" + f"/payments" + f"/{quote(str(payment_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def mark_payment_paid( + self, + dashboard_id: int, + payment_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Mark a payment as paid + + Closes a payment as \"paid\". Use this endpoint for when the payment is + paid through a means other than the payment request portal. This will + close the payment and add its payment amount to your statistics. This + endpoint is not required for payments paid through the payments-portal + sent through Text Request; that will automatically mark a payment as + paid. + + Swagger operation ID: `MarkPaymentPaid`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + payment_id: The numerical id of the payment to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards" + f"/{quote(str(dashboard_id), safe='')}" + f"/payments" + f"/{quote(str(payment_id), safe='')}" + f"/mark_as_paid" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_payment_reminder( + self, + dashboard_id: int, + payment_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send a follow-up text reminding the user to pay the specified payment + + Sends a reminder to the contact to pay the specified payment. The + content of the message is auto-generated. To avoid spam, only one + reminder can be sent per payment + + Swagger operation ID: `SendPaymentReminder`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + payment_id: The numerical id of the payment to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards" + f"/{quote(str(dashboard_id), safe='')}" + f"/payments" + f"/{quote(str(payment_id), safe='')}" + f"/resend" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def cancel_payment( + self, + dashboard_id: int, + payment_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Cancels the specified payment + + Cancels the specified payment, texting the user that the payment has + been canceled. Payments cannot be edited, so canceling and issuing a + new payment is the best way to correct a payment. + + Swagger operation ID: `CancelPayment`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + payment_id: The numerical id of the payment to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards" + f"/{quote(str(dashboard_id), safe='')}" + f"/payments" + f"/{quote(str(payment_id), safe='')}" + f"/cancel" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_payments( + self, + dashboard_id: int, + page: int, + page_size: int, + *, + reference_number: Optional[str] = None, + phone_number: Optional[str] = None, + sort_type: Optional[str] = None, + sort_direction: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Gets all payments + + Gets all payments, including canceled and paid payments. These can be + filtered using the query parameters. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetPayments`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + page: The page of entities to get. When getting values, there is a + max size per page, defined by page_size. If page is greater + than the last page, an empty array will be returned. + page_size: The size of each page to get. When getting values, this + is a max size per page, with accessing subsequent pages done by + the page parameter. + reference_number: User-defined id defined when payments are created + that can be used to quickly find payments. Reference numbers + are not unique; many payments can have the same reference. + phone_number: Phone number of the contact this payment was sent to. + sort_type: Property to sort payments by. Can be \"amount\", + \"contact\", \"date\", \"status\". + sort_direction: Direction to sort payments in. Can be \"desc\" for + greatest to smallest, or \"asc\" for smallest to greatest. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards/{quote(str(dashboard_id), safe='')}/payments" + ) + query_params = [] + if reference_number is not None: + value = str(reference_number) + if isinstance(reference_number, bool): + value = value.lower() + query_params.append(f"reference_number={quote(value, safe='')}") + if phone_number is not None: + value = str(phone_number) + if isinstance(phone_number, bool): + value = value.lower() + query_params.append(f"phone_number={quote(value, safe='')}") + if sort_type is not None: + value = str(sort_type) + if isinstance(sort_type, bool): + value = value.lower() + query_params.append(f"sort_type={quote(value, safe='')}") + if sort_direction is not None: + value = str(sort_direction) + if isinstance(sort_direction, bool): + value = value.lower() + query_params.append(f"sort_direction={quote(value, safe='')}") + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + value = str(page_size) + if isinstance(page_size, bool): + value = value.lower() + query_params.append(f"page_size={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_payment( + self, + input: CreatePaymentInput | Mapping[str, Any], + dashboard_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Creates a new payment + + Creates a new payment with the provided message to the provided + contact. + + Swagger operation ID: `CreatePayment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards/{quote(str(dashboard_id), safe='')}/payments" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_dashboard( + self, + dashboard_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get info on this specific dashboard + + Returns the name and phone of the dashboard. + + Swagger operation ID: `GetDashboard`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards/{quote(str(dashboard_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_dashboard( + self, + dashboard_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Deletes the specified dashboard + + Deletes the specified dashboard. + + Swagger operation ID: `DeleteDashboard`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards/{quote(str(dashboard_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_dashboards_name( + self, + input: UpdateDashboardsNameInput | Mapping[str, Any], + dashboard_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a specific dashboard's name + + Updates a dashboard. This does not change a dashboard's phone number. + If you want a new number with another dashboard's contacts, you will + have to create a new dashboard with a POST and add the contacts with a + bulk export/import. + + Swagger operation ID: `UpdateDashboardsName`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards/{quote(str(dashboard_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_conversations( + self, + dashboard_id: int, + *, + tags: Optional[str] = None, + show_unresolved_only: Optional[str] = None, + include_archived: Optional[str] = None, + search: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Gets all conversations for this dashboard + + Gets all conversations for this dashboard, and includes info on the + last message for each conversation. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetConversations`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + tags: Comma-separated list of guids referring to tags to filter + conversations by. + show_unresolved_only: Whether to only search for contacts whose + conversations have been resolved. If this is false, both + resolved and unresolved conversations will be shown. + include_archived: Whether to include conversations with contacts + that have been archived. + search: Search term for filtering conversations by phone number or + display name. If the search term is less than a full name or + phone number, the search will return all conversations that + partially match it. + page: The page of entities to get. When getting values, there is a + max size per page, defined by page_size. If page is greater + than the last page, an empty array will be returned. + page_size: The size of each page to get. When getting values, this + is a max size per page, with accessing subsequent pages done by + the page parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/dashboards/{quote(str(dashboard_id), safe='')}/conversations" + ) + query_params = [] + if tags is not None: + value = str(tags) + if isinstance(tags, bool): + value = value.lower() + query_params.append(f"tags={quote(value, safe='')}") + if show_unresolved_only is not None: + value = str(show_unresolved_only) + if isinstance(show_unresolved_only, bool): + value = value.lower() + query_params.append(f"show_unresolved_only={quote(value, safe='')}") + if include_archived is not None: + value = str(include_archived) + if isinstance(include_archived, bool): + value = value.lower() + query_params.append(f"include_archived={quote(value, safe='')}") + if search is not None: + value = str(search) + if isinstance(search, bool): + value = value.lower() + query_params.append(f"search={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if page_size is not None: + value = str(page_size) + if isinstance(page_size, bool): + value = value.lower() + query_params.append(f"page_size={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_dashboards( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get all dashboards in an account + + Gets all dashboards in an account. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetDashboards`. + + Args: + page: The page of entities to get. When getting values, there is a + max size per page, defined by page_size. If page is greater + than the last page, an empty array will be returned. + page_size: The size of each page to get. When getting values, this + is a max size per page, with accessing subsequent pages done by + the page parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/dashboards" + query_params = [] + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if page_size is not None: + value = str(page_size) + if isinstance(page_size, bool): + value = value.lower() + query_params.append(f"page_size={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_dashboard( + self, + input: CreateDashboardInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a new dashboard with the given name and phone number + + Creates a new dashboard in the account. Once the dashboard is created, + admins will be emailed about the change and can begin assigning users. + This endpoint can make a dashboard for any provisioned numbers. You can + search for provisioned numbers in a specific area code using GET + /dashboards/provisioning. If the phone number is already in use, a Bad + Request exception will be thrown. + + Swagger operation ID: `CreateDashboard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/dashboards" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/ticketmaster.py b/src/azure/connectors/aio/ticketmaster.py new file mode 100644 index 0000000..f19fcef --- /dev/null +++ b/src/azure/connectors/aio/ticketmaster.py @@ -0,0 +1,2277 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# TicketmasterClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, List, Any, Mapping +from urllib.parse import quote +import json + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, +) + +from azure.connectors.ticketmaster import ( + AttractionGetResponse, + AttractionsGetResponse, + ClassificationGetResponse, + ClassificationsGetResponse, + EventGetResponse, + EventImagesGetResponse, + EventsGetResponse, + GenreGetResponse, + SegmentGetResponse, + SubGenreGetResponse, + SuggestionsGetResponse, + VenueGetResponse, + VenuesGetResponse, +) + +__all__ = [ + "TicketmasterClient", + "AttractionGetResponse", + "AttractionsGetResponse", + "ClassificationGetResponse", + "ClassificationsGetResponse", + "EventGetResponse", + "EventImagesGetResponse", + "EventsGetResponse", + "GenreGetResponse", + "SegmentGetResponse", + "SubGenreGetResponse", + "SuggestionsGetResponse", + "VenueGetResponse", + "VenuesGetResponse", +] + + +# Type Definitions + +# Client Class + +class TicketmasterClient(ConnectorClientBase): + """Typed client for ticketmaster connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a TicketmasterClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "ticketmaster" + + async def events_get( + self, + *, + size: Optional[int] = None, + id: Optional[str] = None, + keyword: Optional[str] = None, + attraction_id: Optional[str] = None, + venue_id: Optional[str] = None, + postal_code: Optional[str] = None, + latlong: Optional[str] = None, + radius: Optional[str] = None, + unit: Optional[str] = None, + source: Optional[str] = None, + locale: Optional[str] = None, + market_id: Optional[str] = None, + start_date_time: Optional[str] = None, + end_date_time: Optional[str] = None, + include_t_b_a: Optional[str] = None, + include_t_b_d: Optional[str] = None, + include_test: Optional[str] = None, + page: Optional[str] = None, + sort: Optional[str] = None, + onsale_start_date_time: Optional[str] = None, + onsale_end_date_time: Optional[str] = None, + city: Optional[List[str]] = None, + country_code: Optional[str] = None, + state_code: Optional[str] = None, + classification_name: Optional[List[str]] = None, + classification_id: Optional[List[str]] = None, + dma_id: Optional[str] = None, + local_start_date_time: Optional[List[str]] = None, + local_start_end_date_time: Optional[List[str]] = None, + start_end_date_time: Optional[List[str]] = None, + public_visibility_start_date_time: Optional[List[str]] = None, + pre_sale_date_time: Optional[List[str]] = None, + onsale_on_start_date: Optional[str] = None, + onsale_on_after_start_date: Optional[str] = None, + collection_id: Optional[List[str]] = None, + segment_id: Optional[List[str]] = None, + segment_name: Optional[List[str]] = None, + include_family: Optional[str] = None, + promoter_id: Optional[str] = None, + genre_id: Optional[List[str]] = None, + sub_genre_id: Optional[List[str]] = None, + type_id: Optional[List[str]] = None, + sub_type_id: Optional[List[str]] = None, + geo_point: Optional[str] = None, + preferred_country: Optional[str] = None, + include_spellcheck: Optional[str] = None, + domain: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Event search + + Find events and filter your search by location, date, availability, and + much more. + + Swagger operation ID: `EventsGet`. + + Args: + size: The page size of the response. + id: The filter for entities by their identifier. + keyword: The keyword to search on. + attraction_id: The filter by attraction identifier. + venue_id: The filter by venue identifier. + postal_code: The filter by postal code or zipcode. + latlong: The filter for events by latitude and longitude. This + filter is deprecated and may be removed in a future release, + please use geoPoint instead. + radius: The radius of the area in which we want to search for + events. + unit: The unit of the radius. + source: The filter for entities by their primary source name or + publishing source name. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + market_id: The filter by market identifier. + start_date_time: The filter with a start date after this date. + end_date_time: The filter with a start date before this date. + include_t_b_a: Indicates whether to include events with date to be + announced (TBA). + include_t_b_d: Indicates whether to include events with a date to + be defined (TBD). + include_test: Indicates whether to include entities flagged as test + in the response. + page: The page number. + sort: The sorting order of the search result. + onsale_start_date_time: The filter with onsale start date after + this date. + onsale_end_date_time: The filter with onsale end date before this + date. + city: The filter by city. + country_code: The filter by country code. + state_code: The filter by state code. + classification_name: The filter by classification name: name of any + segment, genre, sub-genre, type, sub-type. + classification_id: The filter by classification identifier: + identifier of any segment, genre, sub-genre, type, sub-type. + dma_id: The filter by DMA identifier. + local_start_date_time: The filter with event local start date time + within this range. + local_start_end_date_time: The filter for events where event local + start and end date overlap this range. + start_end_date_time: The filter for events where event start and + end date overlap this range. + public_visibility_start_date_time: The filter for events with + public visibility starting. + pre_sale_date_time: The filter for events with a presale start and + end that intersects with this range. + onsale_on_start_date: The filter with onsale start date on this + date. + onsale_on_after_start_date: The filter with onsale range within + this date. + collection_id: The filter by collection identifier. + segment_id: The filter by segment identifier. + segment_name: The filter by segment name. + include_family: The filter by classification that are + family-friendly. + promoter_id: The filter by promoter identifier. + genre_id: The filter by genre identifier. + sub_genre_id: The filter by sub-genre identifier. + type_id: The filter by type identifier. + sub_type_id: The filter by sub-type identifier. + geo_point: The filter for events by geoHash. + preferred_country: The popularity boost by country, default is us. + include_spellcheck: Indicates whether to include spell check + suggestions in the response. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/discovery/v2/events.json" + ) + query_params = [] + item: object + if size is not None: + value = str(size) + if isinstance(size, bool): + value = value.lower() + query_params.append(f"size={quote(value, safe='')}") + if id is not None: + value = str(id) + if isinstance(id, bool): + value = value.lower() + query_params.append(f"id={quote(value, safe='')}") + if keyword is not None: + value = str(keyword) + if isinstance(keyword, bool): + value = value.lower() + query_params.append(f"keyword={quote(value, safe='')}") + if attraction_id is not None: + value = str(attraction_id) + if isinstance(attraction_id, bool): + value = value.lower() + query_params.append(f"attractionId={quote(value, safe='')}") + if venue_id is not None: + value = str(venue_id) + if isinstance(venue_id, bool): + value = value.lower() + query_params.append(f"venueId={quote(value, safe='')}") + if postal_code is not None: + value = str(postal_code) + if isinstance(postal_code, bool): + value = value.lower() + query_params.append(f"postalCode={quote(value, safe='')}") + if latlong is not None: + value = str(latlong) + if isinstance(latlong, bool): + value = value.lower() + query_params.append(f"latlong={quote(value, safe='')}") + if radius is not None: + value = str(radius) + if isinstance(radius, bool): + value = value.lower() + query_params.append(f"radius={quote(value, safe='')}") + if unit is not None: + value = str(unit) + if isinstance(unit, bool): + value = value.lower() + query_params.append(f"unit={quote(value, safe='')}") + if source is not None: + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if locale is not None: + value = str(locale) + if isinstance(locale, bool): + value = value.lower() + query_params.append(f"locale={quote(value, safe='')}") + if market_id is not None: + value = str(market_id) + if isinstance(market_id, bool): + value = value.lower() + query_params.append(f"marketId={quote(value, safe='')}") + if start_date_time is not None: + value = str(start_date_time) + if isinstance(start_date_time, bool): + value = value.lower() + query_params.append(f"startDateTime={quote(value, safe='')}") + if end_date_time is not None: + value = str(end_date_time) + if isinstance(end_date_time, bool): + value = value.lower() + query_params.append(f"endDateTime={quote(value, safe='')}") + if include_t_b_a is not None: + value = str(include_t_b_a) + if isinstance(include_t_b_a, bool): + value = value.lower() + query_params.append(f"includeTBA={quote(value, safe='')}") + if include_t_b_d is not None: + value = str(include_t_b_d) + if isinstance(include_t_b_d, bool): + value = value.lower() + query_params.append(f"includeTBD={quote(value, safe='')}") + if include_test is not None: + value = str(include_test) + if isinstance(include_test, bool): + value = value.lower() + query_params.append(f"includeTest={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if sort is not None: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if onsale_start_date_time is not None: + value = str(onsale_start_date_time) + if isinstance(onsale_start_date_time, bool): + value = value.lower() + query_params.append(f"onsaleStartDateTime={quote(value, safe='')}") + if onsale_end_date_time is not None: + value = str(onsale_end_date_time) + if isinstance(onsale_end_date_time, bool): + value = value.lower() + query_params.append(f"onsaleEndDateTime={quote(value, safe='')}") + if city is not None: + if isinstance(city, list): + joined_parts = [] + for item in city: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"city={quote(joined, safe='')}") + else: + value = str(city) + if isinstance(city, bool): + value = value.lower() + query_params.append(f"city={quote(value, safe='')}") + if country_code is not None: + value = str(country_code) + if isinstance(country_code, bool): + value = value.lower() + query_params.append(f"countryCode={quote(value, safe='')}") + if state_code is not None: + value = str(state_code) + if isinstance(state_code, bool): + value = value.lower() + query_params.append(f"stateCode={quote(value, safe='')}") + if classification_name is not None: + if isinstance(classification_name, list): + joined_parts = [] + for item in classification_name: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"classificationName={quote(joined, safe='')}") + else: + value = str(classification_name) + if isinstance(classification_name, bool): + value = value.lower() + query_params.append(f"classificationName={quote(value, safe='')}") + if classification_id is not None: + if isinstance(classification_id, list): + joined_parts = [] + for item in classification_id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"classificationId={quote(joined, safe='')}") + else: + value = str(classification_id) + if isinstance(classification_id, bool): + value = value.lower() + query_params.append(f"classificationId={quote(value, safe='')}") + if dma_id is not None: + value = str(dma_id) + if isinstance(dma_id, bool): + value = value.lower() + query_params.append(f"dmaId={quote(value, safe='')}") + if local_start_date_time is not None: + if isinstance(local_start_date_time, list): + joined_parts = [] + for item in local_start_date_time: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"localStartDateTime={quote(joined, safe='')}") + else: + value = str(local_start_date_time) + if isinstance(local_start_date_time, bool): + value = value.lower() + query_params.append(f"localStartDateTime={quote(value, safe='')}") + if local_start_end_date_time is not None: + if isinstance(local_start_end_date_time, list): + joined_parts = [] + for item in local_start_end_date_time: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"localStartEndDateTime={quote(joined, safe='')}") + else: + value = str(local_start_end_date_time) + if isinstance(local_start_end_date_time, bool): + value = value.lower() + query_params.append(f"localStartEndDateTime={quote(value, safe='')}") + if start_end_date_time is not None: + if isinstance(start_end_date_time, list): + joined_parts = [] + for item in start_end_date_time: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"startEndDateTime={quote(joined, safe='')}") + else: + value = str(start_end_date_time) + if isinstance(start_end_date_time, bool): + value = value.lower() + query_params.append(f"startEndDateTime={quote(value, safe='')}") + if public_visibility_start_date_time is not None: + if isinstance(public_visibility_start_date_time, list): + joined_parts = [] + for item in public_visibility_start_date_time: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"publicVisibilityStartDateTime={quote(joined, safe='')}") + else: + value = str(public_visibility_start_date_time) + if isinstance(public_visibility_start_date_time, bool): + value = value.lower() + query_params.append(f"publicVisibilityStartDateTime={quote(value, safe='')}") + if pre_sale_date_time is not None: + if isinstance(pre_sale_date_time, list): + joined_parts = [] + for item in pre_sale_date_time: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"preSaleDateTime={quote(joined, safe='')}") + else: + value = str(pre_sale_date_time) + if isinstance(pre_sale_date_time, bool): + value = value.lower() + query_params.append(f"preSaleDateTime={quote(value, safe='')}") + if onsale_on_start_date is not None: + value = str(onsale_on_start_date) + if isinstance(onsale_on_start_date, bool): + value = value.lower() + query_params.append(f"onsaleOnStartDate={quote(value, safe='')}") + if onsale_on_after_start_date is not None: + value = str(onsale_on_after_start_date) + if isinstance(onsale_on_after_start_date, bool): + value = value.lower() + query_params.append(f"onsaleOnAfterStartDate={quote(value, safe='')}") + if collection_id is not None: + if isinstance(collection_id, list): + joined_parts = [] + for item in collection_id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"collectionId={quote(joined, safe='')}") + else: + value = str(collection_id) + if isinstance(collection_id, bool): + value = value.lower() + query_params.append(f"collectionId={quote(value, safe='')}") + if segment_id is not None: + if isinstance(segment_id, list): + joined_parts = [] + for item in segment_id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"segmentId={quote(joined, safe='')}") + else: + value = str(segment_id) + if isinstance(segment_id, bool): + value = value.lower() + query_params.append(f"segmentId={quote(value, safe='')}") + if segment_name is not None: + if isinstance(segment_name, list): + joined_parts = [] + for item in segment_name: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"segmentName={quote(joined, safe='')}") + else: + value = str(segment_name) + if isinstance(segment_name, bool): + value = value.lower() + query_params.append(f"segmentName={quote(value, safe='')}") + if include_family is not None: + value = str(include_family) + if isinstance(include_family, bool): + value = value.lower() + query_params.append(f"includeFamily={quote(value, safe='')}") + if promoter_id is not None: + value = str(promoter_id) + if isinstance(promoter_id, bool): + value = value.lower() + query_params.append(f"promoterId={quote(value, safe='')}") + if genre_id is not None: + if isinstance(genre_id, list): + joined_parts = [] + for item in genre_id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"genreId={quote(joined, safe='')}") + else: + value = str(genre_id) + if isinstance(genre_id, bool): + value = value.lower() + query_params.append(f"genreId={quote(value, safe='')}") + if sub_genre_id is not None: + if isinstance(sub_genre_id, list): + joined_parts = [] + for item in sub_genre_id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"subGenreId={quote(joined, safe='')}") + else: + value = str(sub_genre_id) + if isinstance(sub_genre_id, bool): + value = value.lower() + query_params.append(f"subGenreId={quote(value, safe='')}") + if type_id is not None: + if isinstance(type_id, list): + joined_parts = [] + for item in type_id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"typeId={quote(joined, safe='')}") + else: + value = str(type_id) + if isinstance(type_id, bool): + value = value.lower() + query_params.append(f"typeId={quote(value, safe='')}") + if sub_type_id is not None: + if isinstance(sub_type_id, list): + joined_parts = [] + for item in sub_type_id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"subTypeId={quote(joined, safe='')}") + else: + value = str(sub_type_id) + if isinstance(sub_type_id, bool): + value = value.lower() + query_params.append(f"subTypeId={quote(value, safe='')}") + if geo_point is not None: + value = str(geo_point) + if isinstance(geo_point, bool): + value = value.lower() + query_params.append(f"geoPoint={quote(value, safe='')}") + if preferred_country is not None: + value = str(preferred_country) + if isinstance(preferred_country, bool): + value = value.lower() + query_params.append(f"preferredCountry={quote(value, safe='')}") + if include_spellcheck is not None: + value = str(include_spellcheck) + if isinstance(include_spellcheck, bool): + value = value.lower() + query_params.append(f"includeSpellcheck={quote(value, safe='')}") + if domain is not None: + if isinstance(domain, list): + joined_parts = [] + for item in domain: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"domain={quote(joined, safe='')}") + else: + value = str(domain) + if isinstance(domain, bool): + value = value.lower() + query_params.append(f"domain={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def event_get( + self, + id: str, + *, + locale: Optional[str] = None, + domain: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get event details + + Get details for a specific event using the unique identifier for the + event. This includes the venue and location, the attraction(s), and the + Ticketmaster Website URL for purchasing tickets for the event + + Swagger operation ID: `EventGet`. + + Args: + id: The unique identifier for the event. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/discovery/v2/events/{quote(str(id), safe='')}" + ) + query_params = [] + item: object + if locale is not None: + value = str(locale) + if isinstance(locale, bool): + value = value.lower() + query_params.append(f"locale={quote(value, safe='')}") + if domain is not None: + if isinstance(domain, list): + joined_parts = [] + for item in domain: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"domain={quote(joined, safe='')}") + else: + value = str(domain) + if isinstance(domain, bool): + value = value.lower() + query_params.append(f"domain={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def event_images_get( + self, + id: str, + *, + locale: Optional[str] = None, + domain: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get event images + + Get images for a specific event using the unique identifier for the + event. + + Swagger operation ID: `EventImagesGet`. + + Args: + id: The unique identifier for the event. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/discovery/v2/events/{quote(str(id), safe='')}/images" + ) + query_params = [] + item: object + if locale is not None: + value = str(locale) + if isinstance(locale, bool): + value = value.lower() + query_params.append(f"locale={quote(value, safe='')}") + if domain is not None: + if isinstance(domain, list): + joined_parts = [] + for item in domain: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"domain={quote(joined, safe='')}") + else: + value = str(domain) + if isinstance(domain, bool): + value = value.lower() + query_params.append(f"domain={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def attractions_get( + self, + *, + id: Optional[str] = None, + keyword: Optional[str] = None, + source: Optional[str] = None, + locale: Optional[str] = None, + include_test: Optional[str] = None, + size: Optional[str] = None, + page: Optional[str] = None, + sort: Optional[str] = None, + classification_name: Optional[List[str]] = None, + classification_id: Optional[List[str]] = None, + include_family: Optional[str] = None, + segment_id: Optional[List[str]] = None, + genre_id: Optional[List[str]] = None, + sub_genre_id: Optional[List[str]] = None, + type_id: Optional[List[str]] = None, + sub_type_id: Optional[List[str]] = None, + country_code: Optional[str] = None, + preferred_country: Optional[str] = None, + include_spellcheck: Optional[str] = None, + domain: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Attraction search + + Find attractions (artists, sports, packages, plays and so on) and + filter your search by name, and much more. + + Swagger operation ID: `AttractionsGet`. + + Args: + id: The filter for entities by their identifier. + keyword: The keyword to search on. + source: The filter for entities by their primary source name or + publishing source name. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + include_test: Indicates whether to include entities flagged as test + in the response. + size: The page size of the response. + page: The page number. + sort: The sorting order of the search result. + classification_name: The filter for attractions by classification + name. + classification_id: The filter for attractions by classification + identifier. + include_family: The filter by classification that are + family-friendly. + segment_id: The filter for attractions by segment identifier. + genre_id: The filter for attractions by genre identifier. + sub_genre_id: The filter for attractions by sub-genre identifier. + type_id: The filter for attractions by type identifier. + sub_type_id: The filter for attractions by sub-type identifier. + country_code: The filter for attractions by country code. + preferred_country: The popularity boost by country, default is us. + include_spellcheck: Indicates whether to include spell check + suggestions in the response. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/discovery/v2/attractions" + ) + query_params = [] + item: object + if id is not None: + value = str(id) + if isinstance(id, bool): + value = value.lower() + query_params.append(f"id={quote(value, safe='')}") + if keyword is not None: + value = str(keyword) + if isinstance(keyword, bool): + value = value.lower() + query_params.append(f"keyword={quote(value, safe='')}") + if source is not None: + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if locale is not None: + value = str(locale) + if isinstance(locale, bool): + value = value.lower() + query_params.append(f"locale={quote(value, safe='')}") + if include_test is not None: + value = str(include_test) + if isinstance(include_test, bool): + value = value.lower() + query_params.append(f"includeTest={quote(value, safe='')}") + if size is not None: + value = str(size) + if isinstance(size, bool): + value = value.lower() + query_params.append(f"size={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if sort is not None: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if classification_name is not None: + if isinstance(classification_name, list): + joined_parts = [] + for item in classification_name: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"classificationName={quote(joined, safe='')}") + else: + value = str(classification_name) + if isinstance(classification_name, bool): + value = value.lower() + query_params.append(f"classificationName={quote(value, safe='')}") + if classification_id is not None: + if isinstance(classification_id, list): + joined_parts = [] + for item in classification_id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"classificationId={quote(joined, safe='')}") + else: + value = str(classification_id) + if isinstance(classification_id, bool): + value = value.lower() + query_params.append(f"classificationId={quote(value, safe='')}") + if include_family is not None: + value = str(include_family) + if isinstance(include_family, bool): + value = value.lower() + query_params.append(f"includeFamily={quote(value, safe='')}") + if segment_id is not None: + if isinstance(segment_id, list): + joined_parts = [] + for item in segment_id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"segmentId={quote(joined, safe='')}") + else: + value = str(segment_id) + if isinstance(segment_id, bool): + value = value.lower() + query_params.append(f"segmentId={quote(value, safe='')}") + if genre_id is not None: + if isinstance(genre_id, list): + joined_parts = [] + for item in genre_id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"genreId={quote(joined, safe='')}") + else: + value = str(genre_id) + if isinstance(genre_id, bool): + value = value.lower() + query_params.append(f"genreId={quote(value, safe='')}") + if sub_genre_id is not None: + if isinstance(sub_genre_id, list): + joined_parts = [] + for item in sub_genre_id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"subGenreId={quote(joined, safe='')}") + else: + value = str(sub_genre_id) + if isinstance(sub_genre_id, bool): + value = value.lower() + query_params.append(f"subGenreId={quote(value, safe='')}") + if type_id is not None: + if isinstance(type_id, list): + joined_parts = [] + for item in type_id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"typeId={quote(joined, safe='')}") + else: + value = str(type_id) + if isinstance(type_id, bool): + value = value.lower() + query_params.append(f"typeId={quote(value, safe='')}") + if sub_type_id is not None: + if isinstance(sub_type_id, list): + joined_parts = [] + for item in sub_type_id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"subTypeId={quote(joined, safe='')}") + else: + value = str(sub_type_id) + if isinstance(sub_type_id, bool): + value = value.lower() + query_params.append(f"subTypeId={quote(value, safe='')}") + if country_code is not None: + value = str(country_code) + if isinstance(country_code, bool): + value = value.lower() + query_params.append(f"countryCode={quote(value, safe='')}") + if preferred_country is not None: + value = str(preferred_country) + if isinstance(preferred_country, bool): + value = value.lower() + query_params.append(f"preferredCountry={quote(value, safe='')}") + if include_spellcheck is not None: + value = str(include_spellcheck) + if isinstance(include_spellcheck, bool): + value = value.lower() + query_params.append(f"includeSpellcheck={quote(value, safe='')}") + if domain is not None: + if isinstance(domain, list): + joined_parts = [] + for item in domain: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"domain={quote(joined, safe='')}") + else: + value = str(domain) + if isinstance(domain, bool): + value = value.lower() + query_params.append(f"domain={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def attraction_get( + self, + id: str, + *, + locale: Optional[str] = None, + domain: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get attraction details + + Get details for a specific attraction using the unique identifier for + the attraction. + + Swagger operation ID: `AttractionGet`. + + Args: + id: The unique identifier for the attraction. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/discovery/v2/attractions/{quote(str(id), safe='')}" + ) + query_params = [] + item: object + if locale is not None: + value = str(locale) + if isinstance(locale, bool): + value = value.lower() + query_params.append(f"locale={quote(value, safe='')}") + if domain is not None: + if isinstance(domain, list): + joined_parts = [] + for item in domain: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"domain={quote(joined, safe='')}") + else: + value = str(domain) + if isinstance(domain, bool): + value = value.lower() + query_params.append(f"domain={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def classifications_get( + self, + *, + id: Optional[str] = None, + keyword: Optional[str] = None, + source: Optional[str] = None, + locale: Optional[str] = None, + include_test: Optional[str] = None, + size: Optional[str] = None, + page: Optional[str] = None, + sort: Optional[str] = None, + country_code: Optional[str] = None, + preferred_country: Optional[str] = None, + include_spellcheck: Optional[str] = None, + domain: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Classification search + + Find classifications and filter your search by name, and much more. + Classifications help define the nature of attractions and events. + + Swagger operation ID: `ClassificationsGet`. + + Args: + id: The filter for entities by their identifier. + keyword: The keyword to search on. + source: The filter for entities by their primary source name or + publishing source name. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + include_test: Indicates whether to include entities flagged as test + in the response. + size: The page size of the response. + page: The page number. + sort: The sorting order of the search result. + country_code: The filter for classifications by country code. + preferred_country: The popularity boost by country, default is us. + include_spellcheck: Indicates whether to include spell check + suggestions in the response. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/discovery/v2/classifications" + ) + query_params = [] + item: object + if id is not None: + value = str(id) + if isinstance(id, bool): + value = value.lower() + query_params.append(f"id={quote(value, safe='')}") + if keyword is not None: + value = str(keyword) + if isinstance(keyword, bool): + value = value.lower() + query_params.append(f"keyword={quote(value, safe='')}") + if source is not None: + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if locale is not None: + value = str(locale) + if isinstance(locale, bool): + value = value.lower() + query_params.append(f"locale={quote(value, safe='')}") + if include_test is not None: + value = str(include_test) + if isinstance(include_test, bool): + value = value.lower() + query_params.append(f"includeTest={quote(value, safe='')}") + if size is not None: + value = str(size) + if isinstance(size, bool): + value = value.lower() + query_params.append(f"size={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if sort is not None: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if country_code is not None: + value = str(country_code) + if isinstance(country_code, bool): + value = value.lower() + query_params.append(f"countryCode={quote(value, safe='')}") + if preferred_country is not None: + value = str(preferred_country) + if isinstance(preferred_country, bool): + value = value.lower() + query_params.append(f"preferredCountry={quote(value, safe='')}") + if include_spellcheck is not None: + value = str(include_spellcheck) + if isinstance(include_spellcheck, bool): + value = value.lower() + query_params.append(f"includeSpellcheck={quote(value, safe='')}") + if domain is not None: + if isinstance(domain, list): + joined_parts = [] + for item in domain: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"domain={quote(joined, safe='')}") + else: + value = str(domain) + if isinstance(domain, bool): + value = value.lower() + query_params.append(f"domain={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def classification_get( + self, + id: str, + *, + locale: Optional[str] = None, + domain: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get classification details + + Get details for a specific segment, genre, or sub-genre using its + unique identifier. + + Swagger operation ID: `ClassificationGet`. + + Args: + id: The unique identifier for the classification. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/discovery/v2/classifications/{quote(str(id), safe='')}" + ) + query_params = [] + item: object + if locale is not None: + value = str(locale) + if isinstance(locale, bool): + value = value.lower() + query_params.append(f"locale={quote(value, safe='')}") + if domain is not None: + if isinstance(domain, list): + joined_parts = [] + for item in domain: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"domain={quote(joined, safe='')}") + else: + value = str(domain) + if isinstance(domain, bool): + value = value.lower() + query_params.append(f"domain={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def genre_get( + self, + id: str, + *, + locale: Optional[str] = None, + domain: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get genre details + + Get details for a specific genre using its unique identifier. + + Swagger operation ID: `GenreGet`. + + Args: + id: The unique identifier for the genre. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/discovery/v2/classifications/genres/{quote(str(id), safe='')}" + ) + query_params = [] + item: object + if locale is not None: + value = str(locale) + if isinstance(locale, bool): + value = value.lower() + query_params.append(f"locale={quote(value, safe='')}") + if domain is not None: + if isinstance(domain, list): + joined_parts = [] + for item in domain: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"domain={quote(joined, safe='')}") + else: + value = str(domain) + if isinstance(domain, bool): + value = value.lower() + query_params.append(f"domain={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def segment_get( + self, + id: str, + *, + locale: Optional[str] = None, + domain: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get segment details + + Get details for a specific segment using its unique identifier. + + Swagger operation ID: `SegmentGet`. + + Args: + id: The unique identifier for the segment. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/discovery/v2/classifications/segments/{quote(str(id), safe='')}" + ) + query_params = [] + item: object + if locale is not None: + value = str(locale) + if isinstance(locale, bool): + value = value.lower() + query_params.append(f"locale={quote(value, safe='')}") + if domain is not None: + if isinstance(domain, list): + joined_parts = [] + for item in domain: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"domain={quote(joined, safe='')}") + else: + value = str(domain) + if isinstance(domain, bool): + value = value.lower() + query_params.append(f"domain={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def sub_genre_get( + self, + id: str, + *, + locale: Optional[str] = None, + domain: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get sub-genre details + + Get details for a specific sub-genre using its unique identifier. + + Swagger operation ID: `SubGenreGet`. + + Args: + id: The unique identifier for the sub-genre. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/discovery" + f"/v2" + f"/classifications" + f"/subgenres" + f"/{quote(str(id), safe='')}" + ) + query_params = [] + item: object + if locale is not None: + value = str(locale) + if isinstance(locale, bool): + value = value.lower() + query_params.append(f"locale={quote(value, safe='')}") + if domain is not None: + if isinstance(domain, list): + joined_parts = [] + for item in domain: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"domain={quote(joined, safe='')}") + else: + value = str(domain) + if isinstance(domain, bool): + value = value.lower() + query_params.append(f"domain={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def venues_get( + self, + *, + id: Optional[str] = None, + keyword: Optional[str] = None, + latlong: Optional[str] = None, + radius: Optional[str] = None, + unit: Optional[str] = None, + source: Optional[str] = None, + locale: Optional[str] = None, + include_test: Optional[str] = None, + size: Optional[str] = None, + page: Optional[str] = None, + sort: Optional[str] = None, + country_code: Optional[str] = None, + state_code: Optional[str] = None, + geo_point: Optional[str] = None, + preferred_country: Optional[str] = None, + include_spellcheck: Optional[str] = None, + domain: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Venue search + + Find venues and filter your search by name, and much more. + + Swagger operation ID: `VenuesGet`. + + Args: + id: The filter for entities by their identifier. + keyword: The keyword to search on. + latlong: The filter for venues by latitude and longitude. This + filter is deprecated and may be removed in a future release, + please use geoPoint instead. + radius: The radius of the area in which we want to search for + venues. + unit: The unit of the radius. + source: The filter for entities by their primary source name or + publishing source name. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + include_test: Indicates whether to include entities flagged as test + in the response. + size: The page size of the response. + page: The page number. + sort: The sorting order of the search result. + country_code: The filter for venues by country code. + state_code: The filter by state / province code. + geo_point: The filter for venues by geoHash. + preferred_country: The popularity boost by country, default is us. + include_spellcheck: Indicates whether to include spell check + suggestions in the response. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/discovery/v2/venues" + query_params = [] + item: object + if id is not None: + value = str(id) + if isinstance(id, bool): + value = value.lower() + query_params.append(f"id={quote(value, safe='')}") + if keyword is not None: + value = str(keyword) + if isinstance(keyword, bool): + value = value.lower() + query_params.append(f"keyword={quote(value, safe='')}") + if latlong is not None: + value = str(latlong) + if isinstance(latlong, bool): + value = value.lower() + query_params.append(f"latlong={quote(value, safe='')}") + if radius is not None: + value = str(radius) + if isinstance(radius, bool): + value = value.lower() + query_params.append(f"radius={quote(value, safe='')}") + if unit is not None: + value = str(unit) + if isinstance(unit, bool): + value = value.lower() + query_params.append(f"unit={quote(value, safe='')}") + if source is not None: + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if locale is not None: + value = str(locale) + if isinstance(locale, bool): + value = value.lower() + query_params.append(f"locale={quote(value, safe='')}") + if include_test is not None: + value = str(include_test) + if isinstance(include_test, bool): + value = value.lower() + query_params.append(f"includeTest={quote(value, safe='')}") + if size is not None: + value = str(size) + if isinstance(size, bool): + value = value.lower() + query_params.append(f"size={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if sort is not None: + value = str(sort) + if isinstance(sort, bool): + value = value.lower() + query_params.append(f"sort={quote(value, safe='')}") + if country_code is not None: + value = str(country_code) + if isinstance(country_code, bool): + value = value.lower() + query_params.append(f"countryCode={quote(value, safe='')}") + if state_code is not None: + value = str(state_code) + if isinstance(state_code, bool): + value = value.lower() + query_params.append(f"stateCode={quote(value, safe='')}") + if geo_point is not None: + value = str(geo_point) + if isinstance(geo_point, bool): + value = value.lower() + query_params.append(f"geoPoint={quote(value, safe='')}") + if preferred_country is not None: + value = str(preferred_country) + if isinstance(preferred_country, bool): + value = value.lower() + query_params.append(f"preferredCountry={quote(value, safe='')}") + if include_spellcheck is not None: + value = str(include_spellcheck) + if isinstance(include_spellcheck, bool): + value = value.lower() + query_params.append(f"includeSpellcheck={quote(value, safe='')}") + if domain is not None: + if isinstance(domain, list): + joined_parts = [] + for item in domain: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"domain={quote(joined, safe='')}") + else: + value = str(domain) + if isinstance(domain, bool): + value = value.lower() + query_params.append(f"domain={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def venue_get( + self, + id: str, + *, + locale: Optional[str] = None, + domain: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get venue details + + Get details for a specific venue using the unique identifier for the + venue. + + Swagger operation ID: `VenueGet`. + + Args: + id: The unique identifier for the venue. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/discovery/v2/venues/{quote(str(id), safe='')}" + ) + query_params = [] + item: object + if locale is not None: + value = str(locale) + if isinstance(locale, bool): + value = value.lower() + query_params.append(f"locale={quote(value, safe='')}") + if domain is not None: + if isinstance(domain, list): + joined_parts = [] + for item in domain: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"domain={quote(joined, safe='')}") + else: + value = str(domain) + if isinstance(domain, bool): + value = value.lower() + query_params.append(f"domain={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def suggestions_get( + self, + *, + keyword: Optional[str] = None, + latlong: Optional[str] = None, + radius: Optional[str] = None, + unit: Optional[str] = None, + source: Optional[str] = None, + locale: Optional[str] = None, + include_t_b_a: Optional[str] = None, + include_t_b_d: Optional[str] = None, + include_test: Optional[str] = None, + size: Optional[str] = None, + country_code: Optional[str] = None, + segment_id: Optional[List[str]] = None, + geo_point: Optional[str] = None, + resource: Optional[List[str]] = None, + preferred_country: Optional[str] = None, + start_end_date_time: Optional[List[str]] = None, + local_start_end_date_time: Optional[List[str]] = None, + include_spellcheck: Optional[str] = None, + domain: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Find suggestions + + Find search suggestions and filter your suggestions by location, + source, etc. + + Swagger operation ID: `SuggestionsGet`. + + Args: + keyword: The keyword to search on. + latlong: The filter for events by latitude and longitude. This + filter is deprecated and may be removed in a future release, + please use geoPoint instead. + radius: The radius of the area in which we want to search for + events. + unit: The unit of the radius. + source: The filter for entities by their primary source name or + publishing source name. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + include_t_b_a: Indicates whether to include events with date to be + announced (TBA). Defaults to no if date parameter sent, yes + otherwise. + include_t_b_d: Indicates whether to include events with a date to + be defined (TBD). Defaults to no if date parameter sent, yes + otherwise. + include_test: Indicates whether to include entities flagged as test + in the response. + size: Size of every entity returned in the response. + country_code: The filter suggestions by country code. + segment_id: The filter suggestions by segment identifier. + geo_point: The filter for events by geoHash. + resource: Which resources to include in the suggest response, + defaults to all resources. + preferred_country: The popularity boost by country, default is us. + start_end_date_time: The filter for events where event start and + end date overlap this range. + local_start_end_date_time: The filter for events where event local + start and end date overlap this range. + include_spellcheck: Indicates whether to include spell check + suggestions in the response. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/discovery/v2/suggest" + query_params = [] + item: object + if keyword is not None: + value = str(keyword) + if isinstance(keyword, bool): + value = value.lower() + query_params.append(f"keyword={quote(value, safe='')}") + if latlong is not None: + value = str(latlong) + if isinstance(latlong, bool): + value = value.lower() + query_params.append(f"latlong={quote(value, safe='')}") + if radius is not None: + value = str(radius) + if isinstance(radius, bool): + value = value.lower() + query_params.append(f"radius={quote(value, safe='')}") + if unit is not None: + value = str(unit) + if isinstance(unit, bool): + value = value.lower() + query_params.append(f"unit={quote(value, safe='')}") + if source is not None: + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + if locale is not None: + value = str(locale) + if isinstance(locale, bool): + value = value.lower() + query_params.append(f"locale={quote(value, safe='')}") + if include_t_b_a is not None: + value = str(include_t_b_a) + if isinstance(include_t_b_a, bool): + value = value.lower() + query_params.append(f"includeTBA={quote(value, safe='')}") + if include_t_b_d is not None: + value = str(include_t_b_d) + if isinstance(include_t_b_d, bool): + value = value.lower() + query_params.append(f"includeTBD={quote(value, safe='')}") + if include_test is not None: + value = str(include_test) + if isinstance(include_test, bool): + value = value.lower() + query_params.append(f"includeTest={quote(value, safe='')}") + if size is not None: + value = str(size) + if isinstance(size, bool): + value = value.lower() + query_params.append(f"size={quote(value, safe='')}") + if country_code is not None: + value = str(country_code) + if isinstance(country_code, bool): + value = value.lower() + query_params.append(f"countryCode={quote(value, safe='')}") + if segment_id is not None: + if isinstance(segment_id, list): + joined_parts = [] + for item in segment_id: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"segmentId={quote(joined, safe='')}") + else: + value = str(segment_id) + if isinstance(segment_id, bool): + value = value.lower() + query_params.append(f"segmentId={quote(value, safe='')}") + if geo_point is not None: + value = str(geo_point) + if isinstance(geo_point, bool): + value = value.lower() + query_params.append(f"geoPoint={quote(value, safe='')}") + if resource is not None: + if isinstance(resource, list): + joined_parts = [] + for item in resource: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"resource={quote(joined, safe='')}") + else: + value = str(resource) + if isinstance(resource, bool): + value = value.lower() + query_params.append(f"resource={quote(value, safe='')}") + if preferred_country is not None: + value = str(preferred_country) + if isinstance(preferred_country, bool): + value = value.lower() + query_params.append(f"preferredCountry={quote(value, safe='')}") + if start_end_date_time is not None: + if isinstance(start_end_date_time, list): + joined_parts = [] + for item in start_end_date_time: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"startEndDateTime={quote(joined, safe='')}") + else: + value = str(start_end_date_time) + if isinstance(start_end_date_time, bool): + value = value.lower() + query_params.append(f"startEndDateTime={quote(value, safe='')}") + if local_start_end_date_time is not None: + if isinstance(local_start_end_date_time, list): + joined_parts = [] + for item in local_start_end_date_time: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"localStartEndDateTime={quote(joined, safe='')}") + else: + value = str(local_start_end_date_time) + if isinstance(local_start_end_date_time, bool): + value = value.lower() + query_params.append(f"localStartEndDateTime={quote(value, safe='')}") + if include_spellcheck is not None: + value = str(include_spellcheck) + if isinstance(include_spellcheck, bool): + value = value.lower() + query_params.append(f"includeSpellcheck={quote(value, safe='')}") + if domain is not None: + if isinstance(domain, list): + joined_parts = [] + for item in domain: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"domain={quote(joined, safe='')}") + else: + value = str(domain) + if isinstance(domain, bool): + value = value.lower() + query_params.append(f"domain={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/todo.py b/src/azure/connectors/aio/todo.py new file mode 100644 index 0000000..9b30b04 --- /dev/null +++ b/src/azure/connectors/aio/todo.py @@ -0,0 +1,784 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# TodoClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.todo import ( + CreateToDo, + CreateToDoBody, + CreateToDoHtmlBody, + CreateToDoList, + CreateToDoListBody, + ToDo, + ToDoHtml, + TodoList, + UpdateToDo, + UpdateToDoBody, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "TodoClient", + "CreateToDo", + "CreateToDoBody", + "CreateToDoHtmlBody", + "CreateToDoList", + "CreateToDoListBody", + "ToDo", + "ToDoHtml", + "TodoList", + "UpdateToDo", + "UpdateToDoBody", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class TodoClient(ConnectorClientBase): + """Typed client for todo connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a TodoClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "todo" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def update_to_do_list( + self, + input: CreateToDoList | Mapping[str, Any], + folder_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a to-do list + + This operation is used to update a specific to-do list. + + Swagger operation ID: `UpdateToDoList`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + folder_id: To-do list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(folder_id), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_to_do_list( + self, + folder_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete a to-do list + + This operation is used to delete a specific to-do list. + + Swagger operation ID: `DeleteToDoList`. + + Args: + folder_id: To-do list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(folder_id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def create_to_do( + self, + input: CreateToDo | Mapping[str, Any], + folder_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add a to-do + + This operation is used to create a to-do in the specified to-do list. + + Swagger operation ID: `CreateToDoV3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + folder_id: To-do list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(folder_id), safe='')}/tasks" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_to_do_list( + self, + input: CreateToDoList | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a to-do list + + This operation is used to create a new to-do list. + + Swagger operation ID: `CreateToDoListV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/lists" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_to_do( + self, + folder_id: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete to-do + + This operation is used to delete a task. + + Swagger operation ID: `DeleteToDoV2`. + + Args: + folder_id: To-do list. + id: To-do task. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists" + f"/{quote(str(folder_id), safe='')}" + f"/tasks" + f"/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + def list_all_todo_lists( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List all to-do lists + + Returns a list of all the to-do lists. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAllTodoListsV2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/lists" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_to_do( + self, + folder_id: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a to-do + + This operation is used to get the to-do with the given Id. + + Swagger operation ID: `GetToDoV3`. + + Args: + folder_id: To-do list. + id: To-do task. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists" + f"/{quote(str(folder_id), safe='')}" + f"/tasks" + f"/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_to_do_list( + self, + folder_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a to-do list + + This operation is used to get a specific to-do list. + + Swagger operation ID: `GetToDoListV2`. + + Args: + folder_id: To-do list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(folder_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_to_dos_by_folder( + self, + folder_id: str, + *, + top: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List to-dos by folder + + This operation is used to retrieve all to-dos from a specific list. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListToDosByFolderV2`. + + Args: + folder_id: To-do list. + top: Total number of entries to retrieve (default = 10, maximum = + 999). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(folder_id), safe='')}/tasks" + ) + query_params = [] + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def update_to_do( + self, + input: UpdateToDo | Mapping[str, Any], + folder_id: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update to-do + + This operation is used to update a specific to-do. + + Swagger operation ID: `UpdateToDoV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + folder_id: To-do list. + id: To-do task. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists" + f"/{quote(str(folder_id), safe='')}" + f"/tasks" + f"/{quote(str(id), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/trello.py b/src/azure/connectors/aio/trello.py new file mode 100644 index 0000000..40a4eab --- /dev/null +++ b/src/azure/connectors/aio/trello.py @@ -0,0 +1,2887 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# TrelloClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.trello import ( + Badges, + Board, + BoardLabel, + BoardWithChecklists, + Card, + CardInAction, + CardWithChecklists, + CheckItemState, + Checkitem, + Checklist, + ClientSubscription, + Comment, + CommentPost, + CreateBoard, + CreateCard, + CreateList, + CreateListResponse, + Label, + List, + Member, + Membership, + ObjectEntity, + Perfs, + SubscriptionPayload, + SubscriptionResponse, + Team, + TeamPreferences, + UpdateBoard, + UpdateCard, + Webhook, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "TrelloClient", + "Badges", + "Board", + "BoardLabel", + "BoardWithChecklists", + "Card", + "CardInAction", + "CardWithChecklists", + "CheckItemState", + "Checkitem", + "Checklist", + "ClientSubscription", + "Comment", + "CommentPost", + "CreateBoard", + "CreateCard", + "CreateList", + "CreateListResponse", + "Label", + "List", + "Member", + "Membership", + "ObjectEntity", + "Perfs", + "SubscriptionPayload", + "SubscriptionResponse", + "Team", + "TeamPreferences", + "UpdateBoard", + "UpdateCard", + "Webhook", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class TrelloClient(ConnectorClientBase): + """Typed client for trello connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a TrelloClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "trello" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_cards( + self, + board_id: str, + *, + actions: Optional[str] = None, + attachments: Optional[bool] = None, + attachment_fields: Optional[str] = None, + stickers: Optional[bool] = None, + members: Optional[bool] = None, + memeber_fields: Optional[str] = None, + check_item_states: Optional[bool] = None, + checklists: Optional[str] = None, + limit: Optional[int] = None, + since: Optional[str] = None, + before: Optional[str] = None, + filter: Optional[str] = None, + fields: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List the cards in a board + + List the cards matching the query parameters in a specific board. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListCards`. + + Args: + board_id: The unique id of the board. + actions: The list the actions to return. Specify 'all' or a comma + separated list of valid values. + attachments: A boolean value (true, false) determining whether or + not to show attachments. + attachment_fields: List the attachment fields to return. Specify + 'all' or a comma separated list of valid values. + stickers: A boolean value (true, false) determining whether or not + to show stickers. + members: A boolean value (true, false) determining whether or not + to show members. + memeber_fields: List the member fields to return. Specify 'all' or + a comma separated list of valid values. + check_item_states: A boolean value (true, false) determining + whether or not to return the card states. + checklists: Specify the checklists to return. + limit: The max number of results to return, between 1 and 1000. + since: Fetch all cards after this date. + before: Fetch all cards before this date. + filter: An option on how to filter the response. The allowed values + are 'all', 'closed', 'none', 'open' or 'visible'. + fields: List the card fields to return. Specify 'all' or a comma + separated list of valid values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/boards/{quote(str(board_id), safe='')}/cards" + ) + query_params = [] + if actions is not None: + value = str(actions) + if isinstance(actions, bool): + value = value.lower() + query_params.append(f"actions={quote(value, safe='')}") + if attachments is not None: + value = str(attachments) + if isinstance(attachments, bool): + value = value.lower() + query_params.append(f"attachments={quote(value, safe='')}") + if attachment_fields is not None: + value = str(attachment_fields) + if isinstance(attachment_fields, bool): + value = value.lower() + query_params.append(f"attachment_fields={quote(value, safe='')}") + if stickers is not None: + value = str(stickers) + if isinstance(stickers, bool): + value = value.lower() + query_params.append(f"stickers={quote(value, safe='')}") + if members is not None: + value = str(members) + if isinstance(members, bool): + value = value.lower() + query_params.append(f"members={quote(value, safe='')}") + if memeber_fields is not None: + value = str(memeber_fields) + if isinstance(memeber_fields, bool): + value = value.lower() + query_params.append(f"memeber_fields={quote(value, safe='')}") + if check_item_states is not None: + value = str(check_item_states) + if isinstance(check_item_states, bool): + value = value.lower() + query_params.append(f"checkItemStates={quote(value, safe='')}") + if checklists is not None: + value = str(checklists) + if isinstance(checklists, bool): + value = value.lower() + query_params.append(f"checklists={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if since is not None: + value = str(since) + if isinstance(since, bool): + value = value.lower() + query_params.append(f"since={quote(value, safe='')}") + if before is not None: + value = str(before) + if isinstance(before, bool): + value = value.lower() + query_params.append(f"before={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"filter={quote(value, safe='')}") + if fields is not None: + value = str(fields) + if isinstance(fields, bool): + value = value.lower() + query_params.append(f"fields={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_cards_simple( + self, + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + A simple version of the list cards + + A simple version of the list cards API method used by dynamic values. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListCardsSimple`. + + Args: + board_id: Board Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/simple/boards/{quote(str(board_id), safe='')}/cards" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_card( + self, + card_id: str, + board_id: str, + *, + actions: Optional[str] = None, + actions_entities: Optional[bool] = None, + actions_display: Optional[bool] = None, + actions_limit: Optional[int] = None, + action_fields: Optional[str] = None, + action_member_creator_fields: Optional[str] = None, + attachments: Optional[bool] = None, + attachment_fields: Optional[str] = None, + members: Optional[bool] = None, + member_fields: Optional[str] = None, + members_voted: Optional[bool] = None, + member_voted_fields: Optional[str] = None, + check_item_states: Optional[bool] = None, + check_item_state_fields: Optional[str] = None, + checklists: Optional[str] = None, + checklist_fields: Optional[str] = None, + board: Optional[bool] = None, + board_fields: Optional[str] = None, + list: Optional[bool] = None, + list_fields: Optional[str] = None, + stickers: Optional[bool] = None, + sticker_fields: Optional[str] = None, + fields: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a card by id + + Get a specific card by its unique id. + + Swagger operation ID: `GetCard`. + + Args: + card_id: The id of the card to fetch. + board_id: The id of the board to fetch cards in. + actions: List the actions to return. Specify 'all' or a comma + separated list of valid values. + actions_entities: A boolean value (true, false) determining whether + or not to return action entities. + actions_display: A boolean value (true, false) determining whether + or not to return action displays. + actions_limit: Max number of actions to return. + action_fields: List of action fields to return for each action. + Specify 'all' or a comma separated list of valid values. + action_member_creator_fields: List of action member creator fields + to return. Specify 'all' or a comma separated list of valid + values. + attachments: A boolean value (true, false) determining whether or + not to return attachments. + attachment_fields: List of attachment fields to return for each + attachment. Specify 'all' or a comma separated list of valid + values. + members: A boolean value (true, false) determining whether or not + to return members. + member_fields: List of member fields to return for each member. + Specify 'all' or a comma separated list of valid values. + members_voted: A boolean value (true, false) determining whether or + not to return voted members. + member_voted_fields: List of voted member fields to return for each + voted member. Specify 'all' or a comma separated list of valid + values. + check_item_states: A boolean value (true, false) determining + whether or not to return card states. + check_item_state_fields: List of state fields to return for each of + the card item state. Specify 'all' or a comma separated list of + valid values. + checklists: Specify the checklists to return for each card. + checklist_fields: List of checklist fields to return for each + checklist. Specify 'all' or a comma separated list of valid + values. + board: A boolean value (true, false) determining whether or not to + return the board which the card belongs to. + board_fields: List the board fields to return. Specify 'all' or a + comma separated list of valid values. + list: A boolean value (true, false) determining whether or not to + return the list which the card belongs to. + list_fields: List the list fields to return. Specify 'all' or a + comma separated list of valid values. + stickers: A boolean value (true, false) determining whether or not + to return the stickers. + sticker_fields: List the sticker fields to return for each sticker. + Specify 'all' or a comma separated list of valid values. + fields: List the card fields to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/cards/{quote(str(card_id), safe='')}" + ) + query_params = [] + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"board_id={quote(value, safe='')}") + if actions is not None: + value = str(actions) + if isinstance(actions, bool): + value = value.lower() + query_params.append(f"actions={quote(value, safe='')}") + if actions_entities is not None: + value = str(actions_entities) + if isinstance(actions_entities, bool): + value = value.lower() + query_params.append(f"actions_entities={quote(value, safe='')}") + if actions_display is not None: + value = str(actions_display) + if isinstance(actions_display, bool): + value = value.lower() + query_params.append(f"actions_display={quote(value, safe='')}") + if actions_limit is not None: + value = str(actions_limit) + if isinstance(actions_limit, bool): + value = value.lower() + query_params.append(f"actions_limit={quote(value, safe='')}") + if action_fields is not None: + value = str(action_fields) + if isinstance(action_fields, bool): + value = value.lower() + query_params.append(f"action_fields={quote(value, safe='')}") + if action_member_creator_fields is not None: + value = str(action_member_creator_fields) + if isinstance(action_member_creator_fields, bool): + value = value.lower() + query_params.append(f"action_memberCreator_fields={quote(value, safe='')}") + if attachments is not None: + value = str(attachments) + if isinstance(attachments, bool): + value = value.lower() + query_params.append(f"attachments={quote(value, safe='')}") + if attachment_fields is not None: + value = str(attachment_fields) + if isinstance(attachment_fields, bool): + value = value.lower() + query_params.append(f"attachment_fields={quote(value, safe='')}") + if members is not None: + value = str(members) + if isinstance(members, bool): + value = value.lower() + query_params.append(f"members={quote(value, safe='')}") + if member_fields is not None: + value = str(member_fields) + if isinstance(member_fields, bool): + value = value.lower() + query_params.append(f"member_fields={quote(value, safe='')}") + if members_voted is not None: + value = str(members_voted) + if isinstance(members_voted, bool): + value = value.lower() + query_params.append(f"membersVoted={quote(value, safe='')}") + if member_voted_fields is not None: + value = str(member_voted_fields) + if isinstance(member_voted_fields, bool): + value = value.lower() + query_params.append(f"memberVoted_fields={quote(value, safe='')}") + if check_item_states is not None: + value = str(check_item_states) + if isinstance(check_item_states, bool): + value = value.lower() + query_params.append(f"checkItemStates={quote(value, safe='')}") + if check_item_state_fields is not None: + value = str(check_item_state_fields) + if isinstance(check_item_state_fields, bool): + value = value.lower() + query_params.append(f"checkItemState_fields={quote(value, safe='')}") + if checklists is not None: + value = str(checklists) + if isinstance(checklists, bool): + value = value.lower() + query_params.append(f"checklists={quote(value, safe='')}") + if checklist_fields is not None: + value = str(checklist_fields) + if isinstance(checklist_fields, bool): + value = value.lower() + query_params.append(f"checklist_fields={quote(value, safe='')}") + if board is not None: + value = str(board) + if isinstance(board, bool): + value = value.lower() + query_params.append(f"board={quote(value, safe='')}") + if board_fields is not None: + value = str(board_fields) + if isinstance(board_fields, bool): + value = value.lower() + query_params.append(f"board_fields={quote(value, safe='')}") + if list is not None: + value = str(list) + if isinstance(list, bool): + value = value.lower() + query_params.append(f"list={quote(value, safe='')}") + if list_fields is not None: + value = str(list_fields) + if isinstance(list_fields, bool): + value = value.lower() + query_params.append(f"list_fields={quote(value, safe='')}") + if stickers is not None: + value = str(stickers) + if isinstance(stickers, bool): + value = value.lower() + query_params.append(f"stickers={quote(value, safe='')}") + if sticker_fields is not None: + value = str(sticker_fields) + if isinstance(sticker_fields, bool): + value = value.lower() + query_params.append(f"sticker_fields={quote(value, safe='')}") + if fields is not None: + value = str(fields) + if isinstance(fields, bool): + value = value.lower() + query_params.append(f"fields={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_card( + self, + card_id: str, + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Delete a card + + Delete an existing card from the account. + + Swagger operation ID: `DeleteCard`. + + Args: + card_id: The id of the card to delete. + board_id: The id of the board to fetch cards from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/cards/{quote(str(card_id), safe='')}" + ) + query_params = [] + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"board_id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_boards( + self, + *, + filter: Optional[str] = None, + fields: Optional[str] = None, + actions: Optional[str] = None, + actions_entities: Optional[bool] = None, + actions_limit: Optional[int] = None, + actions_format: Optional[str] = None, + actions_since: Optional[str] = None, + action_fields: Optional[str] = None, + memberships: Optional[str] = None, + organization: Optional[bool] = None, + organization_fields: Optional[str] = None, + lists: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List boards + + List the boards matching the specified query parameters. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListBoards`. + + Args: + filter: List filters to apply to board results. Specify 'all' or a + comma separated list of valid values. + fields: List the board fields to return. Specify 'all' or a comma + separated list of valid values. + actions: List the action fields to return. Specify 'all' or a comma + separated list of valid values. + actions_entities: A boolean value (true, false) determining whether + or not to return action entities. + actions_limit: The max number of actions to return. + actions_format: Specify the format of the actions to return. The + valid options are 'count', 'list', 'minimal'. + actions_since: Return actions after the specified date. + action_fields: List the fields of the action to return. Specify + 'all' or a comma separated list of valid values. + memberships: Specify membership information to return. + organization: A boolean value (true, false) determining whether or + not to return organization information. + organization_fields: List the organization fields to return. + Specify 'all' or a comma separated list of valid values. + lists: Specify whether to return lists which belong to the board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/member/me/boards" + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"filter={quote(value, safe='')}") + if fields is not None: + value = str(fields) + if isinstance(fields, bool): + value = value.lower() + query_params.append(f"fields={quote(value, safe='')}") + if actions is not None: + value = str(actions) + if isinstance(actions, bool): + value = value.lower() + query_params.append(f"actions={quote(value, safe='')}") + if actions_entities is not None: + value = str(actions_entities) + if isinstance(actions_entities, bool): + value = value.lower() + query_params.append(f"actions_entities={quote(value, safe='')}") + if actions_limit is not None: + value = str(actions_limit) + if isinstance(actions_limit, bool): + value = value.lower() + query_params.append(f"actions_limit={quote(value, safe='')}") + if actions_format is not None: + value = str(actions_format) + if isinstance(actions_format, bool): + value = value.lower() + query_params.append(f"actions_format={quote(value, safe='')}") + if actions_since is not None: + value = str(actions_since) + if isinstance(actions_since, bool): + value = value.lower() + query_params.append(f"actions_since={quote(value, safe='')}") + if action_fields is not None: + value = str(action_fields) + if isinstance(action_fields, bool): + value = value.lower() + query_params.append(f"action_fields={quote(value, safe='')}") + if memberships is not None: + value = str(memberships) + if isinstance(memberships, bool): + value = value.lower() + query_params.append(f"memberships={quote(value, safe='')}") + if organization is not None: + value = str(organization) + if isinstance(organization, bool): + value = value.lower() + query_params.append(f"organization={quote(value, safe='')}") + if organization_fields is not None: + value = str(organization_fields) + if isinstance(organization_fields, bool): + value = value.lower() + query_params.append(f"organization_fields={quote(value, safe='')}") + if lists is not None: + value = str(lists) + if isinstance(lists, bool): + value = value.lower() + query_params.append(f"lists={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_boards_simple( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + A simple version of the list boards + + A simple version of the list boards API call with no parameters to be + used by dynamic values. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListBoardsSimple`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/simple/member/me/boards" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_board( + self, + board_id: str, + *, + actions: Optional[str] = None, + action_entities: Optional[bool] = None, + actions_display: Optional[bool] = None, + actions_format: Optional[str] = None, + actions_since: Optional[str] = None, + actions_limit: Optional[int] = None, + action_fields: Optional[str] = None, + action_member: Optional[bool] = None, + action_member_fields: Optional[str] = None, + action_member_creator: Optional[bool] = None, + action_member_creator_fields: Optional[str] = None, + cards: Optional[str] = None, + card_fields: Optional[str] = None, + card_attachments: Optional[bool] = None, + card_attachment_fields: Optional[str] = None, + card_checklists: Optional[str] = None, + card_stickers: Optional[bool] = None, + board_stars: Optional[str] = None, + labels: Optional[str] = None, + label_fields: Optional[str] = None, + labels_limit: Optional[int] = None, + lists: Optional[str] = None, + list_fields: Optional[str] = None, + memberships: Optional[str] = None, + memberships_member: Optional[bool] = None, + memberships_member_fields: Optional[str] = None, + members: Optional[str] = None, + member_fields: Optional[str] = None, + members_invited: Optional[str] = None, + members_invited_fields: Optional[str] = None, + checklists: Optional[str] = None, + checklist_fields: Optional[str] = None, + organization: Optional[bool] = None, + organization_fields: Optional[str] = None, + organization_memberships: Optional[str] = None, + my_perfs: Optional[bool] = None, + fields: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a board by Id + + Get a specific board by its unique identifier. + + Swagger operation ID: `GetBoard`. + + Args: + board_id: The unique Id of the board to get. + actions: List the actions to return. Specify 'all' or a comma + separated list of valid values. + action_entities: A boolean value (true, false) determining whether + or not to return action entities. + actions_display: A boolean value (true, false) determining whether + or not to return actions display. + actions_format: Specify the format of the actions to return. Valid + options are 'count', 'list', 'minimal'. + actions_since: Only return the actions after this date. + actions_limit: Max number of actions to return. + action_fields: List the fields to return with each field. Specify + 'all' or a comma separated list of valid values. + action_member: A boolean value (true, false) determining whether or + not to return action members. + action_member_fields: List the member fields to return with each + action member. Specify 'all' or a comma separated list of valid + values. + action_member_creator: A boolean value (true, false) determining + whether or not to return action member creator. + action_member_creator_fields: List the action member creator fields + to return. Specify 'all' or a comma separated list of valid + values. + cards: Specify the cards to return. Valid options are 'all', + 'closed', 'none', 'open', or 'visible'. + card_fields: List the fields to return for each card. Specify 'all' + or a comma separated list of valid values. + card_attachments: A boolean value (true, false) determining whether + or not to return attachments on cards. + card_attachment_fields: List the attachment fields to return for + each attachment. Specify 'all' or a comma separated list of + valid values. + card_checklists: Specify the checklists to return for each card. + card_stickers: A boolean value (true, false) determining whether or + not to return card stickers. + board_stars: Specify the board stars to return. + labels: Specify the labels to return. + label_fields: List the label fields to return for each label. + Specify 'all' or a comma separated list of valid values. + labels_limit: Max number of labels to return. + lists: Specify the lists to return. + list_fields: List the list fields to return for each list. Specify + 'all' or a comma separated list of valid values. + memberships: List the memberships to return. Specify 'all' or a + comma separated list of valid values. + memberships_member: A boolean value (true, false) determining + whether or not to return membership members. + memberships_member_fields: List the member fields to return for + each membership member. Specify 'all' or a comma separated list + of valid values. + members: List the members to return. Specify 'all' or a comma + separated list of valid values. + member_fields: List the member fields to return for each member. + Specify 'all' or a comma separated list of valid values. + members_invited: Specify the invited members to return. + members_invited_fields: List the fields to return for each. Specify + 'all' or a comma separated list of valid values. + checklists: Specify the checklists to return. + checklist_fields: List the checklist fields to return for each + checklist. Specify 'all' or a comma separated list of valid + values. + organization: A boolean value (true, false) determining whether or + not to return the organization information. + organization_fields: List the organization fields to return for + each organization. Specify 'all' or a comma separated list of + valid values. + organization_memberships: List the organization memberships to + return. Specify 'all' or a comma separated list of valid + values. + my_perfs: A boolean value (true, false) determining whether or not + to return my perfs. + fields: List the fields to return. Specify 'all' or a comma + separated list of valid values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/boards/{quote(str(board_id), safe='')}" + ) + query_params = [] + if actions is not None: + value = str(actions) + if isinstance(actions, bool): + value = value.lower() + query_params.append(f"actions={quote(value, safe='')}") + if action_entities is not None: + value = str(action_entities) + if isinstance(action_entities, bool): + value = value.lower() + query_params.append(f"action_entities={quote(value, safe='')}") + if actions_display is not None: + value = str(actions_display) + if isinstance(actions_display, bool): + value = value.lower() + query_params.append(f"actions_display={quote(value, safe='')}") + if actions_format is not None: + value = str(actions_format) + if isinstance(actions_format, bool): + value = value.lower() + query_params.append(f"actions_format={quote(value, safe='')}") + if actions_since is not None: + value = str(actions_since) + if isinstance(actions_since, bool): + value = value.lower() + query_params.append(f"actions_since={quote(value, safe='')}") + if actions_limit is not None: + value = str(actions_limit) + if isinstance(actions_limit, bool): + value = value.lower() + query_params.append(f"actions_limit={quote(value, safe='')}") + if action_fields is not None: + value = str(action_fields) + if isinstance(action_fields, bool): + value = value.lower() + query_params.append(f"action_fields={quote(value, safe='')}") + if action_member is not None: + value = str(action_member) + if isinstance(action_member, bool): + value = value.lower() + query_params.append(f"action_member={quote(value, safe='')}") + if action_member_fields is not None: + value = str(action_member_fields) + if isinstance(action_member_fields, bool): + value = value.lower() + query_params.append(f"action_member_fields={quote(value, safe='')}") + if action_member_creator is not None: + value = str(action_member_creator) + if isinstance(action_member_creator, bool): + value = value.lower() + query_params.append(f"action_memberCreator={quote(value, safe='')}") + if action_member_creator_fields is not None: + value = str(action_member_creator_fields) + if isinstance(action_member_creator_fields, bool): + value = value.lower() + query_params.append(f"action_memberCreator_fields={quote(value, safe='')}") + if cards is not None: + value = str(cards) + if isinstance(cards, bool): + value = value.lower() + query_params.append(f"cards={quote(value, safe='')}") + if card_fields is not None: + value = str(card_fields) + if isinstance(card_fields, bool): + value = value.lower() + query_params.append(f"card_fields={quote(value, safe='')}") + if card_attachments is not None: + value = str(card_attachments) + if isinstance(card_attachments, bool): + value = value.lower() + query_params.append(f"card_attachments={quote(value, safe='')}") + if card_attachment_fields is not None: + value = str(card_attachment_fields) + if isinstance(card_attachment_fields, bool): + value = value.lower() + query_params.append(f"card_attachment_fields={quote(value, safe='')}") + if card_checklists is not None: + value = str(card_checklists) + if isinstance(card_checklists, bool): + value = value.lower() + query_params.append(f"card_checklists={quote(value, safe='')}") + if card_stickers is not None: + value = str(card_stickers) + if isinstance(card_stickers, bool): + value = value.lower() + query_params.append(f"card_stickers={quote(value, safe='')}") + if board_stars is not None: + value = str(board_stars) + if isinstance(board_stars, bool): + value = value.lower() + query_params.append(f"boardStars={quote(value, safe='')}") + if labels is not None: + value = str(labels) + if isinstance(labels, bool): + value = value.lower() + query_params.append(f"labels={quote(value, safe='')}") + if label_fields is not None: + value = str(label_fields) + if isinstance(label_fields, bool): + value = value.lower() + query_params.append(f"label_fields={quote(value, safe='')}") + if labels_limit is not None: + value = str(labels_limit) + if isinstance(labels_limit, bool): + value = value.lower() + query_params.append(f"labels_limit={quote(value, safe='')}") + if lists is not None: + value = str(lists) + if isinstance(lists, bool): + value = value.lower() + query_params.append(f"lists={quote(value, safe='')}") + if list_fields is not None: + value = str(list_fields) + if isinstance(list_fields, bool): + value = value.lower() + query_params.append(f"list_fields={quote(value, safe='')}") + if memberships is not None: + value = str(memberships) + if isinstance(memberships, bool): + value = value.lower() + query_params.append(f"memberships={quote(value, safe='')}") + if memberships_member is not None: + value = str(memberships_member) + if isinstance(memberships_member, bool): + value = value.lower() + query_params.append(f"memberships_member={quote(value, safe='')}") + if memberships_member_fields is not None: + value = str(memberships_member_fields) + if isinstance(memberships_member_fields, bool): + value = value.lower() + query_params.append(f"memberships_member_fields={quote(value, safe='')}") + if members is not None: + value = str(members) + if isinstance(members, bool): + value = value.lower() + query_params.append(f"members={quote(value, safe='')}") + if member_fields is not None: + value = str(member_fields) + if isinstance(member_fields, bool): + value = value.lower() + query_params.append(f"member_fields={quote(value, safe='')}") + if members_invited is not None: + value = str(members_invited) + if isinstance(members_invited, bool): + value = value.lower() + query_params.append(f"membersInvited={quote(value, safe='')}") + if members_invited_fields is not None: + value = str(members_invited_fields) + if isinstance(members_invited_fields, bool): + value = value.lower() + query_params.append(f"membersInvited_fields={quote(value, safe='')}") + if checklists is not None: + value = str(checklists) + if isinstance(checklists, bool): + value = value.lower() + query_params.append(f"checklists={quote(value, safe='')}") + if checklist_fields is not None: + value = str(checklist_fields) + if isinstance(checklist_fields, bool): + value = value.lower() + query_params.append(f"checklist_fields={quote(value, safe='')}") + if organization is not None: + value = str(organization) + if isinstance(organization, bool): + value = value.lower() + query_params.append(f"organization={quote(value, safe='')}") + if organization_fields is not None: + value = str(organization_fields) + if isinstance(organization_fields, bool): + value = value.lower() + query_params.append(f"organization_fields={quote(value, safe='')}") + if organization_memberships is not None: + value = str(organization_memberships) + if isinstance(organization_memberships, bool): + value = value.lower() + query_params.append(f"organization_memberships={quote(value, safe='')}") + if my_perfs is not None: + value = str(my_perfs) + if isinstance(my_perfs, bool): + value = value.lower() + query_params.append(f"myPerfs={quote(value, safe='')}") + if fields is not None: + value = str(fields) + if isinstance(fields, bool): + value = value.lower() + query_params.append(f"fields={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_board( + self, + input: UpdateBoard | Mapping[str, Any], + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a board + + Update an existing board. + + Swagger operation ID: `UpdateBoard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + board_id: The unique identifier of the board to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/boards/{quote(str(board_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_lists( + self, + board_id: str, + *, + cards: Optional[str] = None, + card_fields: Optional[str] = None, + filter: Optional[str] = None, + fields: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List the card lists in a board + + List the card lists and the cards within the list in a specific board. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListLists`. + + Args: + board_id: The unique id of the board to fetch lists. + cards: Specify the cards to return. + card_fields: List the card fields to return from. Specify 'all' or + a comma separated list of valid values. + filter: Specify the filter property for lists. Valid options are + 'all, 'closed', 'none', or 'open'. + fields: List the fields to return. Specify 'all' or a comma + separated list of valid values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/boards/{quote(str(board_id), safe='')}/lists" + ) + query_params = [] + if cards is not None: + value = str(cards) + if isinstance(cards, bool): + value = value.lower() + query_params.append(f"cards={quote(value, safe='')}") + if card_fields is not None: + value = str(card_fields) + if isinstance(card_fields, bool): + value = value.lower() + query_params.append(f"card_fields={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"filter={quote(value, safe='')}") + if fields is not None: + value = str(fields) + if isinstance(fields, bool): + value = value.lower() + query_params.append(f"fields={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_lists_simple( + self, + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + A simple version of list lists + + A simple version of list lists to be used by dynamic values. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListListsSimple`. + + Args: + board_id: Unique Id of the board to fetch lists. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/simple/boards/{quote(str(board_id), safe='')}/lists" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_list( + self, + list_id: str, + board_id: str, + *, + cards: Optional[str] = None, + card_fields: Optional[str] = None, + board: Optional[bool] = None, + board_fields: Optional[str] = None, + fields: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get list by Id + + Get an existing list and the cards in the list by the unique identifier + of the list. + + Swagger operation ID: `GetList`. + + Args: + list_id: The unique Id of the list to fetch. + board_id: The unique Id of the board to fetch the lists from. + cards: Specify the cards to return. + card_fields: List the card fields to return for each card. Specify + 'all' or a comma separated list of valid values. + board: A boolean value (true, false) determining whether or not to + return board information. + board_fields: List the board fields to return. Specify 'all' or a + comma separated list of valid values. + fields: List the list fields to return. Specify 'all' or a comma + separated list of valid values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(list_id), safe='')}" + ) + query_params = [] + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"board_id={quote(value, safe='')}") + if cards is not None: + value = str(cards) + if isinstance(cards, bool): + value = value.lower() + query_params.append(f"cards={quote(value, safe='')}") + if card_fields is not None: + value = str(card_fields) + if isinstance(card_fields, bool): + value = value.lower() + query_params.append(f"card_fields={quote(value, safe='')}") + if board is not None: + value = str(board) + if isinstance(board, bool): + value = value.lower() + query_params.append(f"board={quote(value, safe='')}") + if board_fields is not None: + value = str(board_fields) + if isinstance(board_fields, bool): + value = value.lower() + query_params.append(f"board_fields={quote(value, safe='')}") + if fields is not None: + value = str(fields) + if isinstance(fields, bool): + value = value.lower() + query_params.append(f"fields={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_list( + self, + list_id: str, + board_id: str, + *, + name: Optional[str] = None, + closed: Optional[str] = None, + id_board: Optional[str] = None, + pos: Optional[str] = None, + subscribed: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a list + + Update an existing list. + + Swagger operation ID: `UpdateList`. + + Args: + list_id: The unique id of the list to update. + board_id: The unique id of the board the list is on. + name: The new list name. + closed: A string (true, false) determining whether or not to close + the list. + id_board: The unique id of the board to move the list to. + pos: The list position (top, bottom, or number). + subscribed: A boolean value (true, false) determining whether or + not to subscribe to the list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/lists/{quote(str(list_id), safe='')}" + ) + query_params = [] + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"board_id={quote(value, safe='')}") + if name is not None: + value = str(name) + if isinstance(name, bool): + value = value.lower() + query_params.append(f"name={quote(value, safe='')}") + if closed is not None: + value = str(closed) + if isinstance(closed, bool): + value = value.lower() + query_params.append(f"closed={quote(value, safe='')}") + if id_board is not None: + value = str(id_board) + if isinstance(id_board, bool): + value = value.lower() + query_params.append(f"idBoard={quote(value, safe='')}") + if pos is not None: + value = str(pos) + if isinstance(pos, bool): + value = value.lower() + query_params.append(f"pos={quote(value, safe='')}") + if subscribed is not None: + value = str(subscribed) + if isinstance(subscribed, bool): + value = value.lower() + query_params.append(f"subscribed={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_user_profile( + self, + *, + fields: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get your User Profile info + + Get information about your User Profile + + Swagger operation ID: `GetUserProfile`. + + Args: + fields: List the fields to return. Specify 'all' or a comma + separated list of valid values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/members/me" + query_params = [] + if fields is not None: + value = str(fields) + if isinstance(fields, bool): + value = value.lower() + query_params.append(f"fields={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_teams( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List teams you are a member of + + The list of teams or organizations the account is a member of. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTeams`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/members/me/organizations" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_team_members( + self, + team_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List members of a team + + List the members in a specific team. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListTeamMembers`. + + Args: + team_id: The unique Id of the team. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/organizations/{quote(str(team_id), safe='')}/members" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_board_members( + self, + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List members of a board + + List the members of a specific board. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListBoardMembers`. + + Args: + board_id: The unique Id of the board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/boards/{quote(str(board_id), safe='')}/members" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_board_labels( + self, + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List labels of a board + + List the labels of a specific board. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListBoardLabels`. + + Args: + board_id: The unique Id of the board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/boards/{quote(str(board_id), safe='')}/labels" + ) + query_params = [] + query_params.append("limit=" + quote("1000", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_team_for_board( + self, + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get the team for a board + + Get the team details for a specific board. + + Swagger operation ID: `GetTeamForBoard`. + + Args: + board_id: The unique Id of the board to fetch team. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/boards/{quote(str(board_id), safe='')}/organization" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_card_members( + self, + card_id: str, + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List members for a card + + List the members for a specific card. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListCardMembers`. + + Args: + card_id: The unique id of the card. + board_id: The unique id of the board to look for cards on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/cards/{quote(str(card_id), safe='')}/members" + ) + query_params = [] + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"board_id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_card_comments( + self, + card_id: str, + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List comments for a card + + List the comments for a specific card. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListCardComments`. + + Args: + card_id: The unique id of the card. + board_id: The unique id of the board to look for comments on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/cards/{quote(str(card_id), safe='')}/actions" + ) + query_params = [] + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"board_id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def add_comment_to_card( + self, + input: CommentPost | Mapping[str, Any], + card_id: str, + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add a comment to a card + + Add a comment to a specific card. + + Swagger operation ID: `AddCommentToCard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + card_id: The unique id of the card. + board_id: The unique id of the board to add a comment to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/cards/{quote(str(card_id), safe='')}/actions/comments" + ) + query_params = [] + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"board_id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def add_member_to_card( + self, + card_id: str, + board_id: str, + member_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add member to a card + + Add a member to a specific card. + + Swagger operation ID: `AddMemberToCard`. + + Args: + card_id: The unique identifier of the card to add a member to. + board_id: The unique id of the board the card is on. + member_id: The member id or username to add to the card. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/cards/{quote(str(card_id), safe='')}/idMembers" + ) + query_params = [] + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"board_id={quote(value, safe='')}") + value = str(member_id) + if isinstance(member_id, bool): + value = value.lower() + query_params.append(f"memberId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_board( + self, + input: CreateBoard | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a board + + Create a new board with the specified fields. + + Swagger operation ID: `CreateBoard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/boards" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_list( + self, + input: CreateList | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a list + + Create a new list. + + Swagger operation ID: `CreateList`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/lists" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def close_board( + self, + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Close a board + + Set a specific board to closed. + + Swagger operation ID: `CloseBoard`. + + Args: + board_id: The unique id of the board to close. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/boards/{quote(str(board_id), safe='')}/closed" + ) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_card( + self, + input: CreateCard | Mapping[str, Any], + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a card + + Creates a new card with the parameters provided. + + Swagger operation ID: `CreateCard_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + board_id: The id of the board to create the card in. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/cards" + query_params = [] + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"board_id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_card( + self, + input: UpdateCard | Mapping[str, Any], + card_id: str, + board_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update a card + + Update an existing card with new parameters. + + Swagger operation ID: `UpdateCard_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + card_id: The id of the card to update. + board_id: The id of the board to fetch cards from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v2/cards/{quote(str(card_id), safe='')}" + ) + query_params = [] + value = str(board_id) + if isinstance(board_id, bool): + value = value.lower() + query_params.append(f"board_id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/twitter.py b/src/azure/connectors/aio/twitter.py new file mode 100644 index 0000000..838771b --- /dev/null +++ b/src/azure/connectors/aio/twitter.py @@ -0,0 +1,978 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# TwitterClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.twitter import ( + OriginalTweetModel, + OriginalTweetUserDetailsModel, + OriginalTweetUserMentionsModel, + TriggerBatchResponseTweetModel, + TweetModel, + TweetResponseModel, + UserDetailsModel, + UserMentionsModel, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "TwitterClient", + "OriginalTweetModel", + "OriginalTweetUserDetailsModel", + "OriginalTweetUserMentionsModel", + "TriggerBatchResponseTweetModel", + "TweetModel", + "TweetResponseModel", + "UserDetailsModel", + "UserMentionsModel", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class TwitterClient(ConnectorClientBase): + """Typed client for twitter connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a TwitterClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "twitter" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_user_timeline( + self, + user_name: str, + *, + max_results: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get user timeline + + This operation gets a list of the most recent tweets posted by a given + user. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `UserTimeline`. + + Args: + user_name: X handle for the user. + max_results: Maximum number of tweets to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/usertimeline" + query_params = [] + value = str(user_name) + if isinstance(user_name, bool): + value = value.lower() + query_params.append(f"userName={quote(value, safe='')}") + if max_results is not None: + value = str(max_results) + if isinstance(max_results, bool): + value = value.lower() + query_params.append(f"maxResults={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_home_timeline( + self, + *, + max_results: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get home timeline + + This operation gets the most recent tweets and re-tweets posted by me + and my followers. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `HomeTimeline`. + + Args: + max_results: Maximum number of tweets to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/hometimeline" + query_params = [] + if max_results is not None: + value = str(max_results) + if isinstance(max_results, bool): + value = value.lower() + query_params.append(f"maxResults={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_search_tweet( + self, + search_query: str, + *, + max_results: Optional[int] = None, + since_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Search tweets + + This operation gets a list of relevant tweets matching the search + query. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SearchTweet`. + + Args: + search_query: Search term like \"happy hour\", #haiku, + from:@username, love OR hate. + max_results: Maximum number of tweets to return. + since_id: Return tweets after the specified tweet ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/searchtweets" + query_params = [] + value = str(search_query) + if isinstance(search_query, bool): + value = value.lower() + query_params.append(f"searchQuery={quote(value, safe='')}") + if max_results is not None: + value = str(max_results) + if isinstance(max_results, bool): + value = value.lower() + query_params.append(f"maxResults={quote(value, safe='')}") + if since_id is not None: + value = str(since_id) + if isinstance(since_id, bool): + value = value.lower() + query_params.append(f"sinceId={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_followers( + self, + user_name: str, + *, + max_results: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get followers + + This operation gets the list of users that follow a given user. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Followers`. + + Args: + user_name: X handle for the user. + max_results: Maximum number of users to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/followers" + query_params = [] + value = str(user_name) + if isinstance(user_name, bool): + value = value.lower() + query_params.append(f"userName={quote(value, safe='')}") + if max_results is not None: + value = str(max_results) + if isinstance(max_results, bool): + value = value.lower() + query_params.append(f"maxResults={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_my_followers( + self, + *, + max_results: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get my followers + + This operation gets the list of users who are following me. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `MyFollowers`. + + Args: + max_results: Maximum number of users to get. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/myfollowers" + query_params = [] + if max_results is not None: + value = str(max_results) + if isinstance(max_results, bool): + value = value.lower() + query_params.append(f"maxResults={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_following( + self, + user_name: str, + *, + max_results: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get following + + The operation gets the list of people the given user follows. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Following`. + + Args: + user_name: X handle for the user. + max_results: Maximum number of users to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/friends" + query_params = [] + value = str(user_name) + if isinstance(user_name, bool): + value = value.lower() + query_params.append(f"userName={quote(value, safe='')}") + if max_results is not None: + value = str(max_results) + if isinstance(max_results, bool): + value = value.lower() + query_params.append(f"maxResults={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_my_following( + self, + *, + max_results: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get my following + + This operation gets the list of users that I am following. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `MyFollowing`. + + Args: + max_results: Maximum number of users to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/myfriends" + query_params = [] + if max_results is not None: + value = str(max_results) + if isinstance(max_results, bool): + value = value.lower() + query_params.append(f"maxResults={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def user( + self, + user_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get user + + This operation gets the profile details for a given user, such as user + name, description, followers count, and more. + + Swagger operation ID: `User`. + + Args: + user_name: X handle for the user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/user" + query_params = [] + value = str(user_name) + if isinstance(user_name, bool): + value = value.lower() + query_params.append(f"userName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def tweet( + self, + input: bytes, + *, + tweet_text: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Post a tweet + + This operation posts a new tweet. + + Swagger operation ID: `Tweet`. + + Args: + input: The binary request body. + tweet_text: Text to be posted. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/posttweet" + query_params = [] + if tweet_text is not None: + value = str(tweet_text) + if isinstance(tweet_text, bool): + value = value.lower() + query_params.append(f"tweetText={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def retweet( + self, + tweet_id: str, + *, + trim_user: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Retweet + + This operation retweets a tweet. + + Swagger operation ID: `Retweet`. + + Args: + tweet_id: Tweet to be retweeted. + trim_user: Boolean to indicate whether to trim user information. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/retweet" + query_params = [] + value = str(tweet_id) + if isinstance(tweet_id, bool): + value = value.lower() + query_params.append(f"tweetId={quote(value, safe='')}") + if trim_user is not None: + value = str(trim_user) + if isinstance(trim_user, bool): + value = value.lower() + query_params.append(f"trimUser={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/typeform.py b/src/azure/connectors/aio/typeform.py new file mode 100644 index 0000000..ae7d8b0 --- /dev/null +++ b/src/azure/connectors/aio/typeform.py @@ -0,0 +1,318 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# TypeformClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.typeform import ( + Item, + ItemNew, + ListFormsResponse, + ListFormsResponseOld, + NewResponseWebhookInput, + ResponseList, + WebhookCreationResponse, + WebhookPayload, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "TypeformClient", + "Item", + "ItemNew", + "ListFormsResponse", + "ListFormsResponseOld", + "NewResponseWebhookInput", + "ResponseList", + "WebhookCreationResponse", + "WebhookPayload", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class TypeformClient(ConnectorClientBase): + """Typed client for typeform connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a TypeformClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "typeform" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_forms( + self, + *, + search: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + workspace_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List forms + + Retrieves a list of JSON descriptions for all forms in your Typeform + account (public and private). + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListForms_V2`. + + Args: + search: Returns items that contain the specified string. + page: The page of results to retrieve. Default is the first page. + page_size: Number of results to retrieve per page. Default is 10. + Maximum is 200. + workspace_id: Retrieve typeforms for the specified workspace. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/forms" + query_params = [] + if search is not None: + value = str(search) + if isinstance(search, bool): + value = value.lower() + query_params.append(f"search={quote(value, safe='')}") + if page is not None: + value = str(page) + if isinstance(page, bool): + value = value.lower() + query_params.append(f"page={quote(value, safe='')}") + if page_size is not None: + value = str(page_size) + if isinstance(page_size, bool): + value = value.lower() + query_params.append(f"page_size={quote(value, safe='')}") + if workspace_id is not None: + value = str(workspace_id) + if isinstance(workspace_id, bool): + value = value.lower() + query_params.append(f"workspace_id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_schema( + self, + form_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get schema + + Get schema + + Swagger operation ID: `GetSchema_V3`. + + Args: + form_id: Form. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v3/forms/{quote(str(form_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/universalprint.py b/src/azure/connectors/aio/universalprint.py new file mode 100644 index 0000000..d14f815 --- /dev/null +++ b/src/azure/connectors/aio/universalprint.py @@ -0,0 +1,367 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# UniversalprintClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.universalprint import ( + ListRecentSharesResponse, +) + +__all__ = [ + "UniversalprintClient", + "ListRecentSharesResponse", +] + + +# Type Definitions + +# Client Class + +class UniversalprintClient(ConnectorClientBase): + """Typed client for universalprint connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a UniversalprintClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "universalprint" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def print_file( + self, + input: bytes, + printer: str, + file_name: str, + *, + configuration_copies: Optional[int] = None, + configuration_orientation: Optional[str] = None, + configuration_color_mode: Optional[str] = None, + configuration_media_size: Optional[str] = None, + configuration_duplex_mode: Optional[str] = None, + configuration_pages_per_sheet: Optional[int] = None, + configuration_dpi: Optional[int] = None, + configuration_quality: Optional[str] = None, + configuration_media_type: Optional[str] = None, + configuration_finishings: Optional[List[str]] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Print PDF + + Prints the given pdf. + + Swagger operation ID: `PrintFile`. + + Args: + input: The binary request body. + printer: The name of the printer. + file_name: The name of file. + configuration_copies: The number of copies that should be printed. + configuration_orientation: The direction in which document is + displayed. + configuration_color_mode: The color configuration to print the job. + configuration_media_size: The page size for the paper or other + print media. + configuration_duplex_mode: The setting to print one-sided jobs or + double-sided jobs. + configuration_pages_per_sheet: The number of input Pages to impose + upon a single Impression. + configuration_dpi: The resolution to use when printing the job. + configuration_quality: The print quality to process a print job. + configuration_media_type: The type of media to use. + configuration_finishings: The finishing processes to apply to the + printed document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/print/shares" + query_params = [] + item: object + value = str(printer) + if isinstance(printer, bool): + value = value.lower() + query_params.append(f"printer={quote(value, safe='')}") + value = str(file_name) + if isinstance(file_name, bool): + value = value.lower() + query_params.append(f"fileName={quote(value, safe='')}") + if configuration_copies is not None: + value = str(configuration_copies) + if isinstance(configuration_copies, bool): + value = value.lower() + query_params.append(f"configuration_copies={quote(value, safe='')}") + if configuration_orientation is not None: + value = str(configuration_orientation) + if isinstance(configuration_orientation, bool): + value = value.lower() + query_params.append(f"configuration_orientation={quote(value, safe='')}") + if configuration_color_mode is not None: + value = str(configuration_color_mode) + if isinstance(configuration_color_mode, bool): + value = value.lower() + query_params.append(f"configuration_colorMode={quote(value, safe='')}") + if configuration_media_size is not None: + value = str(configuration_media_size) + if isinstance(configuration_media_size, bool): + value = value.lower() + query_params.append(f"configuration_mediaSize={quote(value, safe='')}") + if configuration_duplex_mode is not None: + value = str(configuration_duplex_mode) + if isinstance(configuration_duplex_mode, bool): + value = value.lower() + query_params.append(f"configuration_duplexMode={quote(value, safe='')}") + if configuration_pages_per_sheet is not None: + value = str(configuration_pages_per_sheet) + if isinstance(configuration_pages_per_sheet, bool): + value = value.lower() + query_params.append(f"configuration_pagesPerSheet={quote(value, safe='')}") + if configuration_dpi is not None: + value = str(configuration_dpi) + if isinstance(configuration_dpi, bool): + value = value.lower() + query_params.append(f"configuration_dpi={quote(value, safe='')}") + if configuration_quality is not None: + value = str(configuration_quality) + if isinstance(configuration_quality, bool): + value = value.lower() + query_params.append(f"configuration_quality={quote(value, safe='')}") + if configuration_media_type is not None: + value = str(configuration_media_type) + if isinstance(configuration_media_type, bool): + value = value.lower() + query_params.append(f"configuration_mediaType={quote(value, safe='')}") + if configuration_finishings is not None: + if isinstance(configuration_finishings, list): + joined_parts = [] + for item in configuration_finishings: + value = str(item) + if isinstance(item, bool): + value = value.lower() + joined_parts.append(value) + joined = ','.join(joined_parts) + query_params.append(f"configuration_finishings={quote(joined, safe='')}") + else: + value = str(configuration_finishings) + if isinstance(configuration_finishings, bool): + value = value.lower() + query_params.append(f"configuration_finishings={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", + request_url, + body=input, + content_type="application/octet-stream", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_recent_shares( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List recently used shares + + List recently used printer shares. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListRecentShares`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/beta/me/print/recentPrinterShares" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/waywedo.py b/src/azure/connectors/aio/waywedo.py new file mode 100644 index 0000000..8f68e73 --- /dev/null +++ b/src/azure/connectors/aio/waywedo.py @@ -0,0 +1,1178 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# WaywedoClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.waywedo import ( + ChecklistComment, + ChecklistCreateWebHookInput, + ChecklistInstance, + ChecklistInstancesInput, + ChecklistStep, + ChecklistStepCompletedWebHookInput, + ChecklistStepsCompleteInput, + ChecklistStepsCompleteResponse, + CollaboratorsAddInput, + CollaboratorsAddResponse, + CommentAddInput, + CompletedStep, + FinishChecklistWebHookInput, + GenerateAcceptancePDFWebHookInput, + GetAllChecklistInstancesResponse, + InviteSupervisorWebHookInput, + NewCommentWebHookInput, + Procedure, + ProcedureAcceptance, + User, + UsersInput, + UsersPostResponse, + WebhookRegistered, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "WaywedoClient", + "ChecklistComment", + "ChecklistCreateWebHookInput", + "ChecklistInstance", + "ChecklistInstancesInput", + "ChecklistStep", + "ChecklistStepCompletedWebHookInput", + "ChecklistStepsCompleteInput", + "ChecklistStepsCompleteResponse", + "CollaboratorsAddInput", + "CollaboratorsAddResponse", + "CommentAddInput", + "CompletedStep", + "FinishChecklistWebHookInput", + "GenerateAcceptancePDFWebHookInput", + "GetAllChecklistInstancesResponse", + "InviteSupervisorWebHookInput", + "NewCommentWebHookInput", + "Procedure", + "ProcedureAcceptance", + "User", + "UsersInput", + "UsersPostResponse", + "WebhookRegistered", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class WaywedoClient(ConnectorClientBase): + """Typed client for waywedo connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a WaywedoClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "waywedo" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def comment_add( + self, + input: CommentAddInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add a comment to a checklist instance step + + Adds a new comment to an Activated Checklist Instance step. + + Swagger operation ID: `Comment_Add`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v1/ChecklistInstanceComments" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def checklist_instances( + self, + input: ChecklistInstancesInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Checklist Instance + + Creates a new activated checklist instance. + + Swagger operation ID: `ChecklistInstances_Post`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/ChecklistInstances" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def checklist_instances_get( + self, + instance_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get A Checklist Instance + + Retrieve a specific checklist instance by ID + + Swagger operation ID: `ChecklistInstances_Get`. + + Args: + instance_id: The ID of the checklist instance. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1/ChecklistInstances/{quote(str(instance_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_checklist_instances_activity( + self, + instance_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Checklist Instance Activity + + Retrieve all activity for a checklist instance + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ChecklistInstances_Activity`. + + Args: + instance_id: Select the checklist instance. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1" + f"/ChecklistInstances" + f"/{quote(str(instance_id), safe='')}" + f"/Activity" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_find_steps( + self, + instance_id: str, + *, + query: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Find Checklist Step + + Find a step of a checklist instance + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Find_Steps`. + + Args: + instance_id: Select the checklist instance. + query: Search for a step title. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1/ChecklistInstances/{quote(str(instance_id), safe='')}/Steps" + ) + query_params = [] + if query is not None: + value = str(query) + if isinstance(query, bool): + value = value.lower() + query_params.append(f"query={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def checklist_steps_get( + self, + instance_id: str, + step_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get A Checklist Step + + Retrieve a specific checklist step by ID + + Swagger operation ID: `ChecklistSteps_Get`. + + Args: + instance_id: The ID of the checklist instance. + step_id: The ID of the checklist step. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1" + f"/ChecklistInstances" + f"/{quote(str(instance_id), safe='')}" + f"/Steps" + f"/{quote(str(step_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def checklist_steps_complete( + self, + input: ChecklistStepsCompleteInput | Mapping[str, Any], + instance_id: str, + step_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Complete a Checklist Step + + Mark a specific step in a checklist instance as complete. + + Swagger operation ID: `ChecklistSteps_Complete`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + instance_id: Select the checklist instance. + step_id: Select the checklist step. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1" + f"/ChecklistInstances" + f"/{quote(str(instance_id), safe='')}" + f"/Steps" + f"/{quote(str(step_id), safe='')}" + f"/Complete" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def collaborators_add( + self, + input: CollaboratorsAddInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Collaborators to a Checklist Instance + + Adds one or more collaborators to a checklist instance. + + Swagger operation ID: `Collaborators_Add`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/Collaborators" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_find_checklist( + self, + *, + query: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Find Checklist + + Search for a checklist by title + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Find_Checklist`. + + Args: + query: The title of the checklist. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/Procedures" + query_params = [] + query_params.append("type=" + quote("2", safe='')) + if query is not None: + value = str(query) + if isinstance(query, bool): + value = value.lower() + query_params.append(f"query={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def procedures_get( + self, + procedure_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get A Checklist Or Procedure + + Retrieve a specific checklist or procedure by ID + + Swagger operation ID: `Procedures_Get`. + + Args: + procedure_id: The ID of the checklist or procedure. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1/Procedures/{quote(str(procedure_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_find_checklist_instances( + self, + procedure_id: int, + *, + query: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Find Checklist Instance + + Search for a checklist instance by title. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Find_Checklist_Instances`. + + Args: + procedure_id: Select a checklist. + query: The title of the checklist instance. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1" + f"/Procedures" + f"/{quote(str(procedure_id), safe='')}" + f"/ChecklistInstances" + ) + query_params = [] + if query is not None: + value = str(query) + if isinstance(query, bool): + value = value.lower() + query_params.append(f"query={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_find_user( + self, + *, + query: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Find User + + Search for a user by name or email. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `Find_User`. + + Args: + query: The name or email address of the user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/Users" + query_params = [] + if query is not None: + value = str(query) + if isinstance(query, bool): + value = value.lower() + query_params.append(f"query={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def users( + self, + input: UsersInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add a New User + + Creates and invites a new user. + + Swagger operation ID: `Users_Post`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/Users" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_all_checklist_instances( + self, + *, + limit: Optional[int] = None, + offset: Optional[int] = None, + status: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get All Checklist Instances + + Retrieve a list of all activated checklist instances. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAll_ChecklistInstances`. + + Args: + limit: Maximum number of results to fetch. + offset: The number of records skipped. + status: The status of instances returned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/ChecklistInstances" + query_params = [] + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if offset is not None: + value = str(offset) + if isinstance(offset, bool): + value = value.lower() + query_params.append(f"offset={quote(value, safe='')}") + if status is not None: + value = str(status) + if isinstance(status, bool): + value = value.lower() + query_params.append(f"status={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("results", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/wdatp.py b/src/azure/connectors/aio/wdatp.py new file mode 100644 index 0000000..1643a44 --- /dev/null +++ b/src/azure/connectors/aio/wdatp.py @@ -0,0 +1,2459 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# WdatpClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.wdatp import ( + AdvancedHuntingInput, + AdvancedHuntingResponse, + AdvancedHuntingSchemaInput, + AdvancedHuntingSchemaResponse, + Alert, + CancelSingleMachineActionInput, + CollectInvestigationPackageInput, + CreateAlertByReferenceInput, + DomainStats, + FileStats, + GetAlertsResponse, + GetInvestigationPackageUriResponse, + GetInvestigationsResponse, + GetLiveResponseDownloadLinkResponse, + GetMachineActionsResponse, + GetMachinesResponse, + GetRemediationActivitiesResponse, + GetRemediationActivityMachineListResponse, + InitiateInvestigationInput, + InitiateInvestigationResponse, + Investigation, + IpStats, + IsolateMachineInput, + LiveResponseCommand, + LiveResponseCommandStatus, + Machine, + MachineAction, + MachineTagInput, + OnNewRemediationActivityResponse, + PatchAlertInput, + RemediationActivity, + RestrictAppExecutionInput, + RunAntivirusScanInput, + RunLiveResponseInput, + StartInvestigationInput, + UnisolateMachineInput, + UnrestrictAppExecutionInput, + WebHookNotification, + WebHookSubscriptionRequest, + WebHookSubscriptionTableEntity, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "WdatpClient", + "AdvancedHuntingInput", + "AdvancedHuntingResponse", + "AdvancedHuntingSchemaInput", + "AdvancedHuntingSchemaResponse", + "Alert", + "CancelSingleMachineActionInput", + "CollectInvestigationPackageInput", + "CreateAlertByReferenceInput", + "DomainStats", + "FileStats", + "GetAlertsResponse", + "GetInvestigationPackageUriResponse", + "GetInvestigationsResponse", + "GetLiveResponseDownloadLinkResponse", + "GetMachineActionsResponse", + "GetMachinesResponse", + "GetRemediationActivitiesResponse", + "GetRemediationActivityMachineListResponse", + "InitiateInvestigationInput", + "InitiateInvestigationResponse", + "Investigation", + "IpStats", + "IsolateMachineInput", + "LiveResponseCommand", + "LiveResponseCommandStatus", + "Machine", + "MachineAction", + "MachineTagInput", + "OnNewRemediationActivityResponse", + "PatchAlertInput", + "RemediationActivity", + "RestrictAppExecutionInput", + "RunAntivirusScanInput", + "RunLiveResponseInput", + "StartInvestigationInput", + "UnisolateMachineInput", + "UnrestrictAppExecutionInput", + "WebHookNotification", + "WebHookSubscriptionRequest", + "WebHookSubscriptionTableEntity", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class WdatpClient(ConnectorClientBase): + """Typed client for wdatp connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a WdatpClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "wdatp" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def advanced_hunting( + self, + input: AdvancedHuntingInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Advanced Hunting (Deprecated) + + Run a custom query over Microsoft Defender for Endpoint data. This + action supports only queries over MDE tables. This action is deprecated + and will be retired on February 1, 2027. Migrate to the Microsoft Graph + Security API. For migration guidance, see: + https://learn.microsoft.com/en-us/graph/api/resources/security-api-overview?view=graph-rest-1.0#powerplatformflow-migrationpowerapps-power-automate-logic-apps + + Swagger operation ID: `AdvancedHunting`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/advancedqueries/run" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_alert_by_reference( + self, + input: CreateAlertByReferenceInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Alerts - Create alert + + Create Alert based on specific Event + + Swagger operation ID: `CreateAlertByReference`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/api/alerts/createAlertByReference" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_alerts( + self, + *, + expand: Optional[str] = None, + filter: Optional[str] = None, + select: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + count: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Alerts - Get list of alerts + + Retrieve from Windows Defender ATP the most recent alerts + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAlerts`. + + Args: + expand: Expands related entities inline. + filter: Filters the results, using OData syntax. + select: Selects which properties to include in the response, + defaults to all. + orderby: Sorts the results. + top: Returns only the first n results. + skip: Skips the first n results. + count: Includes a count of the matching results in the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/alerts" + query_params = [] + if expand is not None: + value = str(expand) + if isinstance(expand, bool): + value = value.lower() + query_params.append(f"$expand={quote(value, safe='')}") + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if count is not None: + value = str(count) + if isinstance(count, bool): + value = value.lower() + query_params.append(f"$count={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_single_alert( + self, + alert_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Alerts - Get single alert + + Retrieve from Windows Defender ATP a specific alert + + Swagger operation ID: `GetSingleAlert`. + + Args: + alert_id: The identifier of the alert to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/alerts/{quote(str(alert_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def patch_alert( + self, + input: PatchAlertInput | Mapping[str, Any], + alert_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Alerts - Update alert + + Update a Windows Defender ATP alert + + Swagger operation ID: `PatchAlert`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + alert_id: The identifier of the alert to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/alerts/{quote(str(alert_id), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def initiate_investigation( + self, + input: InitiateInvestigationInput | Mapping[str, Any], + machine_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Actions - Initiate investigation on a machine (to be deprecated) + + Initiate investigation on a machine + + Swagger operation ID: `InitiateInvestigation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to investigate. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/machines" + f"/{quote(str(machine_id), safe='')}" + f"/initiateInvestigation" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def start_investigation( + self, + input: StartInvestigationInput | Mapping[str, Any], + machine_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Actions - Start automated investigation on a machine + + Start automated investigation on a machine + + Swagger operation ID: `StartInvestigation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to investigate. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/machines" + f"/{quote(str(machine_id), safe='')}" + f"/startInvestigation" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_single_machine_action( + self, + machine_action_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Actions - Get single machine action + + Retrieve from Windows Defender ATP a specific machine action + + Swagger operation ID: `GetSingleMachineAction`. + + Args: + machine_action_id: The identifier of the machine action to + retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/machineactions/{quote(str(machine_action_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def cancel_single_machine_action( + self, + input: CancelSingleMachineActionInput | Mapping[str, Any], + machine_action_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Actions - Cancel a single machine action + + Cancel a specific machine action + + Swagger operation ID: `CancelSingleMachineAction`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_action_id: The identifier of the machine action to cancel. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/machineactions" + f"/{quote(str(machine_action_id), safe='')}" + f"/cancel" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_live_response_download_link( + self, + machine_action_id: str, + command_index: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Actions - Get live response command result download URI + + Get result download URI for a completed live response command + + Swagger operation ID: `GetLiveResponseDownloadLink`. + + Args: + machine_action_id: The identifier of the machine action. + command_index: The index of the live response command to get the + results download URI for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/machineactions" + f"/{quote(str(machine_action_id), safe='')}" + f"/GetLiveResponseResultDownloadLink(index=" + f"{quote(str(command_index), safe='')}" + f")" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_machine_actions( + self, + *, + filter: Optional[str] = None, + select: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + count: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Actions - Get list of machine actions + + Retrieve from Windows Defender ATP the most recent machine actions + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMachineActions`. + + Args: + filter: Filters the results, using OData syntax. + select: Selects which properties to include in the response, + defaults to all. + orderby: Sorts the results. + top: Returns only the first n results. + skip: Skips the first n results. + count: Includes a count of the matching results in the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/machineactions" + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if count is not None: + value = str(count) + if isinstance(count, bool): + value = value.lower() + query_params.append(f"$count={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_file_stats( + self, + file_id: str, + *, + look_back_hours: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Files - Get the statistics for the given file + + Retrieve from Windows Defender ATP statistics for the given file to a + given file by identifier Sha1, or Sha256 + + Swagger operation ID: `GetFileStats`. + + Args: + file_id: The file identifier - Sha1, or Sha256. + look_back_hours: The look back period in hours to look by, the + default is 24 hours. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/files/{quote(str(file_id), safe='')}/stats" + ) + query_params = [] + if look_back_hours is not None: + value = str(look_back_hours) + if isinstance(look_back_hours, bool): + value = value.lower() + query_params.append(f"lookBackHours={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_domain_stats( + self, + domain_name: str, + *, + look_back_hours: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Domains - Get the statistics for the given domain name + + Retrieve from Windows Defender ATP statistics related to a given domain + name + + Swagger operation ID: `GetDomainStats`. + + Args: + domain_name: The domain name. + look_back_hours: The look back period in hours to look by, the + default is 24 hours. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/domains/{quote(str(domain_name), safe='')}/stats" + ) + query_params = [] + if look_back_hours is not None: + value = str(look_back_hours) + if isinstance(look_back_hours, bool): + value = value.lower() + query_params.append(f"lookBackHours={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_ip_stats( + self, + ip_address: str, + *, + look_back_hours: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Ips - Get the statistics for the given ip address + + Retrieve from Windows Defender ATP statistics related to a given ip + address - given in ipv4 or ipv6 format. + + Swagger operation ID: `GetIpStats`. + + Args: + ip_address: The ip address. + look_back_hours: The look back period in hours to look by, the + default is 24 hours. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/ips/{quote(str(ip_address), safe='')}/stats" + ) + query_params = [] + if look_back_hours is not None: + value = str(look_back_hours) + if isinstance(look_back_hours, bool): + value = value.lower() + query_params.append(f"lookBackHours={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_single_investigation( + self, + investigation_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Actions - Get single investigation + + Retrieve from Microsoft Defender ATP a specific investigation + + Swagger operation ID: `GetSingleInvestigation`. + + Args: + investigation_id: The identifier of the investigation to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/investigations/{quote(str(investigation_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_investigations( + self, + *, + filter: Optional[str] = None, + select: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + count: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Actions - Get list of investigation + + Retrieve from Microsoft Defender ATP the most recent investigations + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetInvestigations`. + + Args: + filter: Filters the results, using OData syntax. + select: Selects which properties to include in the response, + defaults to all. + orderby: Sorts the results. + top: Returns only the first n results. + skip: Skips the first n results. + count: Includes a count of the matching results in the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/investigations" + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if count is not None: + value = str(count) + if isinstance(count, bool): + value = value.lower() + query_params.append(f"$count={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def collect_investigation_package( + self, + input: CollectInvestigationPackageInput | Mapping[str, Any], + machine_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Actions - Collect investigation package + + Collect investigation package from a machine + + Swagger operation ID: `CollectInvestigationPackage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to collect the investigation + from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/machines" + f"/{quote(str(machine_id), safe='')}" + f"/collectInvestigationPackage" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_investigation_package_uri( + self, + machine_action_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Actions - Get investigation package download URI + + Get a URI that allows downloading of an investigation package + + Swagger operation ID: `GetInvestigationPackageUri`. + + Args: + machine_action_id: The ID of the investigation package collection. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/machineactions" + f"/{quote(str(machine_action_id), safe='')}" + f"/getPackageUri" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def isolate_machine( + self, + input: IsolateMachineInput | Mapping[str, Any], + machine_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Actions - Isolate machine + + Isolate a machine from network + + Swagger operation ID: `IsolateMachine`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to isolate. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/machines/{quote(str(machine_id), safe='')}/isolate" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def unisolate_machine( + self, + input: UnisolateMachineInput | Mapping[str, Any], + machine_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Actions - Unisolate machine + + Unisolate a machine from network + + Swagger operation ID: `UnisolateMachine`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to unisolate. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/machines/{quote(str(machine_id), safe='')}/unisolate" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def restrict_app_execution( + self, + input: RestrictAppExecutionInput | Mapping[str, Any], + machine_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Actions - Restrict app execution + + Restrict execution of all applications on the machine except a + predefined set + + Swagger operation ID: `RestrictAppExecution`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to restrict. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/machines" + f"/{quote(str(machine_id), safe='')}" + f"/restrictCodeExecution" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def unrestrict_app_execution( + self, + input: UnrestrictAppExecutionInput | Mapping[str, Any], + machine_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Actions - Remove app execution restriction + + Enable execution of any application on the machine + + Swagger operation ID: `UnrestrictAppExecution`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to unrestrict. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/machines" + f"/{quote(str(machine_id), safe='')}" + f"/unrestrictCodeExecution" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def run_antivirus_scan( + self, + input: RunAntivirusScanInput | Mapping[str, Any], + machine_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Actions - Run antivirus scan + + Initiate Windows Defender Antivirus scan on a machine + + Swagger operation ID: `RunAntivirusScan`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to scan. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/machines/{quote(str(machine_id), safe='')}/runAntiVirusScan" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def run_live_response( + self, + input: RunLiveResponseInput | Mapping[str, Any], + machine_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Actions - Run live response + + Run live response api commands for a single machine + + Swagger operation ID: `RunLiveResponse`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to run live response session on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/machines/{quote(str(machine_id), safe='')}/runliveresponse" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_remediation_activities( + self, + *, + filter: Optional[str] = None, + select: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + count: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Remediation tasks - Get list of remediation activities (Preview) + + Retrieve from Windows Defender ATP the remediation activities + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetRemediationActivities`. + + Args: + filter: Filters the results, using OData syntax. + select: Selects which properties to include in the response, + defaults to all. + orderby: Sorts the results. + top: Returns only the first n results. + skip: Skips the first n results. + count: Includes a count of the matching results in the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/remediationtasks" + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if count is not None: + value = str(count) + if isinstance(count, bool): + value = value.lower() + query_params.append(f"$count={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_single_remediation_activity( + self, + remediation_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + RemediationActivities - Get single remediation activity (Preview) + + Retrieve from Windows Defender ATP a specific remediation activity + + Swagger operation ID: `GetSingleRemediationActivity`. + + Args: + remediation_id: The identifier of the remediation activity to + retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/remediationtasks/{quote(str(remediation_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_get_remediation_activity_machine( + self, + remediation_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Remediation activities - Get list of related machines (Preview) + + Retrieve from Windows Defender ATP the related machines to a specific + remediation activity + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetRemediationActivityMachineList`. + + Args: + remediation_id: The identifier of the remediation activity to + retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api" + f"/remediationtasks" + f"/{quote(str(remediation_id), safe='')}" + f"/machinereferences" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_machines( + self, + *, + filter: Optional[str] = None, + select: Optional[str] = None, + orderby: Optional[str] = None, + top: Optional[int] = None, + skip: Optional[int] = None, + count: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Machines - Get list of machines + + Retrieve from Windows Defender ATP the most recent machines + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMachines`. + + Args: + filter: Filters the results, using OData syntax. + select: Selects which properties to include in the response, + defaults to all. + orderby: Sorts the results. + top: Returns only the first n results. + skip: Skips the first n results. + count: Includes a count of the matching results in the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/machines" + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if count is not None: + value = str(count) + if isinstance(count, bool): + value = value.lower() + query_params.append(f"$count={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_single_machine( + self, + machine_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Machines - Get single machine + + Retrieve from Windows Defender ATP a specific machine + + Swagger operation ID: `GetSingleMachine`. + + Args: + machine_id: The identifier of the machine to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/machines/{quote(str(machine_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def machine_tag( + self, + input: MachineTagInput | Mapping[str, Any], + machine_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Machines - Tag machine + + Add or remove a tag to/from a machine + + Swagger operation ID: `MachineTag`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to which the tag should be added + or removed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/machines/{quote(str(machine_id), safe='')}/tags" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def advanced_hunting_schema( + self, + input: AdvancedHuntingSchemaInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Advanced Hunting Schema + + Gets the schema for a Windows Defender ATP custom query + + Swagger operation ID: `AdvancedHuntingSchema`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/api/advancedqueries/schema" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/webex.py b/src/azure/connectors/aio/webex.py new file mode 100644 index 0000000..9b84b28 --- /dev/null +++ b/src/azure/connectors/aio/webex.py @@ -0,0 +1,881 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# WebexClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.webex import ( + CreateSpaceInput, + CreateSpaceMemberInput, + CreateSpaceMemberResponse, + CreateSpaceResponse, + CreateTeamMemberInput, + CreateTeamMemberResponse, + GetMessageDetailsResponse, + GetMessagesResponse, + GetMyOwnDetailsResponse, + GetPeopleResponse, + GetSpaceDetailResponse, + GetSpacesResponse, + MembershipsCreatedInput, + MembershipsCreatedResponse, + MembershipsDeletedInput, + MembershipsDeletedResponse, + MembershipsUpdatedInput, + MembershipsUpdatedResponse, + MessagesCreatedInput, + MessagesCreatedResponse, + MessagesDeletedInput, + MessagesDeletedResponse, + SendMessageInput, + SendMessageResponse, + SpaceCreatedInput, + SpaceCreatedResponse, + SpaceUpdatedInput, + SpaceUpdatedResponse, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "WebexClient", + "CreateSpaceInput", + "CreateSpaceMemberInput", + "CreateSpaceMemberResponse", + "CreateSpaceResponse", + "CreateTeamMemberInput", + "CreateTeamMemberResponse", + "GetMessageDetailsResponse", + "GetMessagesResponse", + "GetMyOwnDetailsResponse", + "GetPeopleResponse", + "GetSpaceDetailResponse", + "GetSpacesResponse", + "MembershipsCreatedInput", + "MembershipsCreatedResponse", + "MembershipsDeletedInput", + "MembershipsDeletedResponse", + "MembershipsUpdatedInput", + "MembershipsUpdatedResponse", + "MessagesCreatedInput", + "MessagesCreatedResponse", + "MessagesDeletedInput", + "MessagesDeletedResponse", + "SendMessageInput", + "SendMessageResponse", + "SpaceCreatedInput", + "SpaceCreatedResponse", + "SpaceUpdatedInput", + "SpaceUpdatedResponse", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class WebexClient(ConnectorClientBase): + """Typed client for webex connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a WebexClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "webex" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_space_member( + self, + input: CreateSpaceMemberInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Member to Space + + Add a member to an existing space + + Swagger operation ID: `CreateSpaceMember`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/memberships" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_messages( + self, + room_id: str, + *, + mentioned_people: Optional[str] = None, + before_message: Optional[str] = None, + before: Optional[str] = None, + max: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Messages + + Get a list of recent messages for a space + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMessages`. + + Args: + room_id: List messages in a space for a given space ID. + mentioned_people: List messages where the caller is mentioned by + specifying \"me\" or the caller personId. + before_message: List messages sent before a message, by ID. + before: List messages sent before a date and time, in ISO8601 + format. + max: Limit the maximum number of messages in the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/messages" + query_params = [] + value = str(room_id) + if isinstance(room_id, bool): + value = value.lower() + query_params.append(f"roomId={quote(value, safe='')}") + if mentioned_people is not None: + value = str(mentioned_people) + if isinstance(mentioned_people, bool): + value = value.lower() + query_params.append(f"mentionedPeople={quote(value, safe='')}") + if before_message is not None: + value = str(before_message) + if isinstance(before_message, bool): + value = value.lower() + query_params.append(f"beforeMessage={quote(value, safe='')}") + if before is not None: + value = str(before) + if isinstance(before, bool): + value = value.lower() + query_params.append(f"before={quote(value, safe='')}") + if max is not None: + value = str(max) + if isinstance(max, bool): + value = value.lower() + query_params.append(f"max={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def send_message( + self, + input: SendMessageInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send a Message + + Send a message to webex + + Swagger operation ID: `SendMessage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/messages" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_message_details( + self, + message_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Message Details + + Shows details for a message, by message ID. + + Swagger operation ID: `GetMessageDetails`. + + Args: + message_id: The message ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1/messages/{quote(str(message_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_people( + self, + *, + id: Optional[str] = None, + email: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get People + + Lookup details and presence information for people in your organization + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetPeople`. + + Args: + id: List people by ID. Accepts up to 85 person IDs separated by + commas. + email: List people with this email address. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/people" + query_params = [] + if id is not None: + value = str(id) + if isinstance(id, bool): + value = value.lower() + query_params.append(f"id={quote(value, safe='')}") + if email is not None: + value = str(email) + if isinstance(email, bool): + value = value.lower() + query_params.append(f"email={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_my_own_details( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get My Own Details + + Lookup your own details + + Swagger operation ID: `GetMyOwnDetails`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/people/me" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_spaces( + self, + *, + max: Optional[int] = None, + type_: Optional[str] = None, + sort_by: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get Spaces List + + This action retrieves a list of spaces + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetSpaces`. + + Args: + max: Maximum number of spaces to return. + type_: (group) only include group spaces, (direct) only include 1 + to 1 spaces, returns all if not specified. + sort_by: (id) the space id, (lastactivity) the last activity + timestamp, (created) space creation date. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/rooms" + query_params = [] + if max is not None: + value = str(max) + if isinstance(max, bool): + value = value.lower() + query_params.append(f"max={quote(value, safe='')}") + if type_ is not None: + value = str(type_) + if isinstance(type_, bool): + value = value.lower() + query_params.append(f"type={quote(value, safe='')}") + if sort_by is not None: + value = str(sort_by) + if isinstance(sort_by, bool): + value = value.lower() + query_params.append(f"sortBy={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def create_space( + self, + input: CreateSpaceInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Space + + Create space or team space + + Swagger operation ID: `CreateSpace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/rooms" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_space_detail( + self, + room_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get Space Details + + Return details of a given space + + Swagger operation ID: `GetSpaceDetail`. + + Args: + room_id: Select a space. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v1/rooms/{quote(str(room_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create_team_member( + self, + input: CreateTeamMemberInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Add Member to Team + + Add a member to a team + + Swagger operation ID: `CreateTeamMember`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1/team/memberships" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/wordonlinebusiness.py b/src/azure/connectors/aio/wordonlinebusiness.py new file mode 100644 index 0000000..679829d --- /dev/null +++ b/src/azure/connectors/aio/wordonlinebusiness.py @@ -0,0 +1,618 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# WordonlinebusinessClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.wordonlinebusiness import ( + BlobMetadata, + ContentBody, + CreateFileItemInput, + GetDrivesResponse, + GetFileSchemaResponse, + GetFiles, + GetSourcesResponse, + SensitivityLabelMetadata, +) + +__all__ = [ + "WordonlinebusinessClient", + "BlobMetadata", + "ContentBody", + "CreateFileItemInput", + "GetDrivesResponse", + "GetFileSchemaResponse", + "GetFiles", + "GetSourcesResponse", + "SensitivityLabelMetadata", +] + + +# Type Definitions + +# Client Class + +class WordonlinebusinessClient(ConnectorClientBase): + """Typed client for wordonlinebusiness connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a WordonlinebusinessClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "wordonlinebusiness" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def create_file_item( + self, + input: CreateFileItemInput | Mapping[str, Any], + source: str, + drive: str, + file: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Populate a Microsoft Word template + + Reads a Microsoft Word template to then fill the template fields with + selected dynamic values to generate a Word Document. + + Swagger operation ID: `CreateFileItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + drive: Select a document library from the drop-down. + file: Select a Word file through File Browse. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/templates/getFile" + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(drive) + if isinstance(drive, bool): + value = value.lower() + query_params.append(f"drive={quote(value, safe='')}") + value = str(file) + if isinstance(file, bool): + value = value.lower() + query_params.append(f"file={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def create_word_file_with_content( + self, + input: ContentBody | Mapping[str, Any], + *, + file_name: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create a Microsoft Word document with the given content + + Creates a Microsoft Word file with the given content in the root + directory (use only from Copilot Studio) + + Swagger operation ID: `CreateWordFileWithContent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + file_name: Name of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/templates/createWordFileWithContent" + ) + query_params = [] + if file_name is not None: + value = str(file_name) + if isinstance(file_name, bool): + value = value.lower() + query_params.append(f"fileName={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_file_pdf( + self, + source: str, + drive: str, + file: str, + *, + extract_sensitivity_label: Optional[bool] = None, + fetch_sensitivity_label_metadata: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Convert Word Document to PDF + + Gets a PDF version of the selected file + + Swagger operation ID: `GetFilePDF`. + + Args: + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + drive: Select a document library from the drop-down. + file: Select a Word file through File Browse. + extract_sensitivity_label: Select if you want to extract + Sensitivity label ( false, true). + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/api/templates/convertFile" + ) + query_params = [] + query_params.append("format=" + quote("pdf", safe='')) + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(drive) + if isinstance(drive, bool): + value = value.lower() + query_params.append(f"drive={quote(value, safe='')}") + value = str(file) + if isinstance(file, bool): + value = value.lower() + query_params.append(f"file={quote(value, safe='')}") + if extract_sensitivity_label is not None: + value = str(extract_sensitivity_label) + if isinstance(extract_sensitivity_label, bool): + value = value.lower() + query_params.append(f"extractSensitivityLabel={quote(value, safe='')}") + if fetch_sensitivity_label_metadata is not None: + value = str(fetch_sensitivity_label_metadata) + if isinstance(fetch_sensitivity_label_metadata, bool): + value = value.lower() + query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + def list_sources( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get sources + + Get a list of sources. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetSources`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/codeless/v1.0/sources" + query_params = [] + query_params.append("$top=" + quote("", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_drives( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get drives + + Get a list of drives. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetDrives`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/codeless/v1.0/drives" + query_params = [] + query_params.append("source=" + quote("me", safe='')) + query_params.append("$select=" + quote("", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_file_schema( + self, + source: str, + drive: str, + file: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Fetches the schema of the selected file + + Fetches the schema of the selected file. + + Swagger operation ID: `GetFileSchema`. + + Args: + source: source. + drive: drive. + file: file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/api/templates/schema" + query_params = [] + value = str(source) + if isinstance(source, bool): + value = value.lower() + query_params.append(f"source={quote(value, safe='')}") + value = str(drive) + if isinstance(drive, bool): + value = value.lower() + query_params.append(f"drive={quote(value, safe='')}") + value = str(file) + if isinstance(file, bool): + value = value.lower() + query_params.append(f"file={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/wordpress.py b/src/azure/connectors/aio/wordpress.py new file mode 100644 index 0000000..a953491 --- /dev/null +++ b/src/azure/connectors/aio/wordpress.py @@ -0,0 +1,429 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# WordpressClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.wordpress import ( + CreatePostModel, + Error, + ListPostsResponse, + PostModel, + PostResponse, + PostsModel, + Site, + SiteInsightsModel, + SiteList, + SiteModel, + SiteStatsChartModel, + SiteStatsModel, + TopPostModel, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "WordpressClient", + "CreatePostModel", + "Error", + "ListPostsResponse", + "PostModel", + "PostResponse", + "PostsModel", + "Site", + "SiteInsightsModel", + "SiteList", + "SiteModel", + "SiteStatsChartModel", + "SiteStatsModel", + "TopPostModel", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class WordpressClient(ConnectorClientBase): + """Typed client for wordpress connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a WordpressClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "wordpress" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def site_stats( + self, + site_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get site statistics + + Get statistics for a specified site + + Swagger operation ID: `SiteStats`. + + Args: + site_id: The site's id or domain. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/sites/{quote(str(site_id), safe='')}/stats" + ) + query_params = [] + query_params.append("fields=" + quote("stats", safe='')) + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get( + self, + site_id: str, + post_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get post + + Get post + + Swagger operation ID: `GetPost`. + + Args: + site_id: The site's id or domain. + post_id: The post Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/sites" + f"/{quote(str(site_id), safe='')}" + f"/posts" + f"/{quote(str(post_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def create( + self, + input: CreatePostModel | Mapping[str, Any], + site_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create post + + Create post + + Swagger operation ID: `CreatePost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + site_id: The site's id or domain. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/sites/{quote(str(site_id), safe='')}/posts/new" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_sites( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + List sites + + List sites + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `ListSites`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/me/sites" + query_params = [] + query_params.append( + "fields=" + quote( + "ID, name, description, URL, is_multisite, post_count,subscribers_count," + " lang,visible,is_private,single_user_site,is_vip,is_following", + safe='' + ) + ) + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("sites", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/aio/yammer.py b/src/azure/connectors/aio/yammer.py new file mode 100644 index 0000000..16befaa --- /dev/null +++ b/src/azure/connectors/aio/yammer.py @@ -0,0 +1,1009 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# YammerClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.yammer import ( + LikedBy, + Message, + MessageBody, + MessageList, + Network, + PageableMessageList, + PostOperationRequest, + Topic, + User, + YammerEntity, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "YammerClient", + "LikedBy", + "Message", + "MessageBody", + "MessageList", + "Network", + "PageableMessageList", + "PostOperationRequest", + "Topic", + "User", + "YammerEntity", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class YammerClient(ConnectorClientBase): + """Typed client for yammer connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a YammerClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "yammer" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_networks( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get my networks + + Gets all the networks that the user belongs to. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetNetworks`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/networks.json" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_groups( + self, + *, + network_id: Optional[str] = None, + mine: Optional[int] = None, + show_all_company_group: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get groups + + Gets all groups. If mine = 1, get only groups to which the user belongs + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetGroups`. + + Args: + network_id: Network ID. + mine: Used for getting groups which user is part of. + show_all_company_group: Used for showing All Company Group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/groups.json" + query_params = [] + if network_id is not None: + value = str(network_id) + if isinstance(network_id, bool): + value = value.lower() + query_params.append(f"network_id={quote(value, safe='')}") + if mine is not None: + value = str(mine) + if isinstance(mine, bool): + value = value.lower() + query_params.append(f"mine={quote(value, safe='')}") + if show_all_company_group is not None: + value = str(show_all_company_group) + if isinstance(show_all_company_group, bool): + value = value.lower() + query_params.append(f"showAllCompanyGroup={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_user_details_by_id( + self, + user_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get user details + + This operation returns user profile details. + + Swagger operation ID: `GetUserDetailsById`. + + Args: + user_id: Unique identifier of the user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/users/{quote(str(user_id), safe='')}.json" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def like_message( + self, + message_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Like message + + This operation is used to like the specified message. + + Swagger operation ID: `LikeMessage`. + + Args: + message_id: Unique id of the message. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/messages/liked_by/current.json" + ) + query_params = [] + value = str(message_id) + if isinstance(message_id, bool): + value = value.lower() + query_params.append(f"message_id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + def list_all_messages( + self, + *, + network_id: Optional[str] = None, + older_than: Optional[int] = None, + newer_than: Optional[int] = None, + threaded: Optional[str] = None, + limit: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get all messages + + This operation returns all public messages in the logged in user's Viva + Engage network. Corresponds to \"All\" conversations in the Viva Engage + web interface. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetAllMessagesV3`. + + Args: + network_id: Network ID. + older_than: Returns messages older than the message ID specified as + a numeric string. This is useful for paginating messages. For + example, if you're currently viewing 20 messages and the oldest + is number 2912, you could append \"?older_than=2912″ to your + request to get the 20 messages prior to those you're seeing. + newer_than: Returns messages newer than the message ID specified as + a numeric string. This should be used when polling for new + messages. If you're looking at messages, and the most recent + message returned is 3516, you can make a request with the + parameter \"?newer_than=3516″ to ensure that you do not get + duplicate copies of messages already on your page. + threaded: Threaded=true will only return the thread starter (first + message) for each thread. This parameter is intended for apps + which need to display message threads collapsed. + threaded=extended will return the thread starter messages and + the two most recent messages all ordered by activity, as they + are viewed in the default view on the Viva Engage web + interface. + limit: Return only the specified number of messages. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v3/messages.json" + query_params = [] + if network_id is not None: + value = str(network_id) + if isinstance(network_id, bool): + value = value.lower() + query_params.append(f"network_id={quote(value, safe='')}") + if older_than is not None: + value = str(older_than) + if isinstance(older_than, bool): + value = value.lower() + query_params.append(f"older_than={quote(value, safe='')}") + if newer_than is not None: + value = str(newer_than) + if isinstance(newer_than, bool): + value = value.lower() + query_params.append(f"newer_than={quote(value, safe='')}") + if threaded is not None: + value = str(threaded) + if isinstance(threaded, bool): + value = value.lower() + query_params.append(f"threaded={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_messages_following( + self, + *, + network_id: Optional[str] = None, + older_than: Optional[int] = None, + newer_than: Optional[int] = None, + threaded: Optional[str] = None, + limit: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get the messages from my Following feed + + This operation returns the messages from Following feed which is + conversations involving people, groups and topics that the user is + following. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMessagesFollowingV3`. + + Args: + network_id: Unique identifier of the network. + older_than: Returns messages older than the message ID specified as + a numeric string. This is useful for paginating messages. For + example, if you're currently viewing 20 messages and the oldest + is number 2912, you could append \"?older_than=2912″ to your + request to get the 20 messages prior to those you're seeing. + newer_than: Returns messages newer than the message ID specified as + a numeric string. This should be used when polling for new + messages. If you're looking at messages, and the most recent + message returned is 3516, you can make a request with the + parameter \"?newer_than=3516″ to ensure that you do not get + duplicate copies of messages already on your page. + threaded: Threaded=true will only return the thread starter (first + message) for each thread. This parameter is intended for apps + which need to display message threads collapsed. + threaded=extended will return the thread starter messages and + the two most recent messages all ordered by activity, as they + are viewed in the default view on the Viva Engage web + interface. + limit: Return only the specified number of messages. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/v3/messages/following.json" + ) + query_params = [] + if network_id is not None: + value = str(network_id) + if isinstance(network_id, bool): + value = value.lower() + query_params.append(f"network_id={quote(value, safe='')}") + if older_than is not None: + value = str(older_than) + if isinstance(older_than, bool): + value = value.lower() + query_params.append(f"older_than={quote(value, safe='')}") + if newer_than is not None: + value = str(newer_than) + if isinstance(newer_than, bool): + value = value.lower() + query_params.append(f"newer_than={quote(value, safe='')}") + if threaded is not None: + value = str(threaded) + if isinstance(threaded, bool): + value = value.lower() + query_params.append(f"threaded={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_messages_in_group( + self, + group_id: int, + *, + network_id: Optional[str] = None, + older_than: Optional[int] = None, + newer_than: Optional[int] = None, + threaded: Optional[str] = None, + limit: Optional[int] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get messages in a group + + This operation returns the messages posted in a group. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMessagesInGroupV3`. + + Args: + group_id: Unique identifier of the group. + network_id: Unique identifier of the network. + older_than: Returns messages in threads where the thread's latest + message is older than the specified message ID. Any thread with + a most recent message ID that is newer than or equal to the + specified ID will not have any of its messages returned by this + query. + newer_than: Returns messages in threads where the thread's latest + message is newer than the specified message ID. Any thread with + a most recent message ID that is older than or equal to the + specified ID will not have any of its messages returned by this + query. + threaded: Threaded=true will only return the thread starter (first + message) for each thread. This parameter is intended for apps + which need to display message threads collapsed. + threaded=extended will return the thread starter messages and + the two most recent messages all ordered by activity, as they + are viewed in the default view on the Viva Engage web + interface. + limit: Return only the specified number of messages. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v3/messages/in_group/{quote(str(group_id), safe='')}.json" + ) + query_params = [] + if network_id is not None: + value = str(network_id) + if isinstance(network_id, bool): + value = value.lower() + query_params.append(f"network_id={quote(value, safe='')}") + if older_than is not None: + value = str(older_than) + if isinstance(older_than, bool): + value = value.lower() + query_params.append(f"older_than={quote(value, safe='')}") + if newer_than is not None: + value = str(newer_than) + if isinstance(newer_than, bool): + value = value.lower() + query_params.append(f"newer_than={quote(value, safe='')}") + if threaded is not None: + value = str(threaded) + if isinstance(threaded, bool): + value = value.lower() + query_params.append(f"threaded={quote(value, safe='')}") + if limit is not None: + value = str(limit) + if isinstance(limit, bool): + value = value.lower() + query_params.append(f"limit={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_messages_in_thread( + self, + thread_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get messages in a thread + + This operation returns the messages posted in a thread. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetMessagesInThreadV3`. + + Args: + thread_id: Unique identifier of the thread. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/v3/messages/in_thread/{quote(str(thread_id), safe='')}.json" + ) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def post_message( + self, + input: PostOperationRequest | Mapping[str, Any], + *, + network_id: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Post message + + This operation is used to post a Message to a Group or All Company + Feed. If group ID is provided, message will be posted to the specified + group else it will be posted in All Company Feed. + + Swagger operation ID: `PostMessageV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + network_id: Unique id of the network. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v2/messages.json" + query_params = [] + if network_id is not None: + value = str(network_id) + if isinstance(network_id, bool): + value = value.lower() + query_params.append(f"network_id={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/zendesk.py b/src/azure/connectors/aio/zendesk.py new file mode 100644 index 0000000..7d0a6bf --- /dev/null +++ b/src/azure/connectors/aio/zendesk.py @@ -0,0 +1,817 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# ZendeskClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.zendesk import ( + BlobDataSetsMetadata, + DataSet, + DataSetsList, + DataSetsMetadata, + GetCurrentUserInfoResponse, + Item, + ItemsList, + ObjectEntity, + SearchResult, + Table, + TableCapabilitiesMetadata, + TableFilterRestrictionsMetadata, + TableMetadata, + TableSelectRestrictionsMetadata, + TableSortRestrictionsMetadata, + TablesList, + TabularDataSetsMetadata, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "ZendeskClient", + "BlobDataSetsMetadata", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "GetCurrentUserInfoResponse", + "Item", + "ItemsList", + "ObjectEntity", + "SearchResult", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TablesList", + "TabularDataSetsMetadata", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class ZendeskClient(ConnectorClientBase): + """Typed client for zendesk connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a ZendeskClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "zendesk" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_tables( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get tables + + Retrieves Zendesk tables from a site + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTables`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/datasets/default/tables" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + def list_items( + self, + table: str, + *, + filter: Optional[str] = None, + orderby: Optional[str] = None, + skip: Optional[int] = None, + top: Optional[int] = None, + select: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get items + + Retrieves Zendesk items of a certain Zendesk type (example: 'Ticket') + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetItems`. + + Args: + table: Zendesk item type (example: 'Ticket'). + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + skip: Number of entries to skip (default = 0). + top: Maximum number of entries to retrieve (default = 512). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + query_params = [] + if filter is not None: + value = str(filter) + if isinstance(filter, bool): + value = value.lower() + query_params.append(f"$filter={quote(value, safe='')}") + if orderby is not None: + value = str(orderby) + if isinstance(orderby, bool): + value = value.lower() + query_params.append(f"$orderby={quote(value, safe='')}") + if skip is not None: + value = str(skip) + if isinstance(skip, bool): + value = value.lower() + query_params.append(f"$skip={quote(value, safe='')}") + if top is not None: + value = str(top) + if isinstance(top, bool): + value = value.lower() + query_params.append(f"$top={quote(value, safe='')}") + if select is not None: + value = str(select) + if isinstance(select, bool): + value = value.lower() + query_params.append(f"$select={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("@odata.nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() + + return AsyncItemPaged(get_next, extract_data) + + async def post_item( + self, + input: Item | Mapping[str, Any], + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Create Item + + Creates a Zendesk item + + Swagger operation ID: `PostItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Zendesk item type (example: 'Ticket'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + ) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_item( + self, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get item + + Retrieves a Zendesk item + + Swagger operation ID: `GetItem`. + + Args: + table: Zendesk item type (example: 'Ticket'). + id: Unique identifier of the item to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def delete_item( + self, + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete item + + Deletes a Zendesk item + + Swagger operation ID: `DeleteItem`. + + Args: + table: Zendesk item type (example: 'Ticket'). + id: Unique identifier of the item to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "DELETE", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "DELETE", + request_url, + response.status, + response.text, + response=response, + ) + + async def patch_item( + self, + input: Item | Mapping[str, Any], + table: str, + id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update item + + Updates an existing Zendesk item + + Swagger operation ID: `PatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Zendesk item type (example: 'Ticket'). + id: Unique identifier of the item to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + f"/items" + f"/{quote(quote(str(id), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "PATCH", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PATCH", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + def list_search_articles( + self, + query: str, + *, + locale: Optional[str] = None, + brand_id: Optional[int] = None, + category: Optional[int] = None, + section: Optional[int] = None, + label_names: Optional[str] = None, + multibrand: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Search Articles + + Returns a default number of 25 articles per page, up to a maximum of + 1000 results. + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `SearchArticles`. + + Args: + query: Article to search for. + locale: The locale the item is displayed in. + brand_id: Search for articles in the specified brand. + category: Limit the search to this category id. + section: Limit the search to this section id. + label_names: A comma-separated list of label names. + multibrand: Enable search across all brands if true. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v2/help_center/articles/search" + ) + query_params = [] + value = str(query) + if isinstance(query, bool): + value = value.lower() + query_params.append(f"query={quote(value, safe='')}") + if locale is not None: + value = str(locale) + if isinstance(locale, bool): + value = value.lower() + query_params.append(f"locale={quote(value, safe='')}") + if brand_id is not None: + value = str(brand_id) + if isinstance(brand_id, bool): + value = value.lower() + query_params.append(f"brand_id={quote(value, safe='')}") + if category is not None: + value = str(category) + if isinstance(category, bool): + value = value.lower() + query_params.append(f"category={quote(value, safe='')}") + if section is not None: + value = str(section) + if isinstance(section, bool): + value = value.lower() + query_params.append(f"section={quote(value, safe='')}") + if label_names is not None: + value = str(label_names) + if isinstance(label_names, bool): + value = value.lower() + query_params.append(f"label_names={quote(value, safe='')}") + if multibrand is not None: + value = str(multibrand) + if isinstance(multibrand, bool): + value = value.lower() + query_params.append(f"multibrand={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("results", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) + + async def get_table( + self, + table: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get item metadata + + Retrieves item metadata for Zendesk object type + + Swagger operation ID: `GetTable`. + + Args: + table: Zendesk item type (example: 'Ticket'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/$metadata.json" + f"/datasets" + f"/default" + f"/tables" + f"/{quote(quote(str(table), safe=''), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/zeptomail.py b/src/azure/connectors/aio/zeptomail.py new file mode 100644 index 0000000..a979541 --- /dev/null +++ b/src/azure/connectors/aio/zeptomail.py @@ -0,0 +1,483 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# ZeptomailClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, Any, Mapping +from urllib.parse import quote +import json + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, +) + +from azure.connectors.zeptomail import ( + EmailAddress, + EmailAddressItems, + FromAddress, + GetMailAgentResponse, + GetProcessedEmailsResponse, + ProcessedMailStatsResponse, + ReplyToAddress, + SendMailInput, + SendTemplateMailInput, + SuccessMessage, +) + +__all__ = [ + "ZeptomailClient", + "EmailAddress", + "EmailAddressItems", + "FromAddress", + "GetMailAgentResponse", + "GetProcessedEmailsResponse", + "ProcessedMailStatsResponse", + "ReplyToAddress", + "SendMailInput", + "SendTemplateMailInput", + "SuccessMessage", +] + + +# Type Definitions + +# Client Class + +class ZeptomailClient(ConnectorClientBase): + """Typed client for zeptomail connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a ZeptomailClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "zeptomail" + + async def get_mail_agent( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get all Mail Agent + + This endpoint fetches details of all the Mail Agents in the account. It + returns data including Mail Agent name, Mail Agent key, Created time, + Status. \\n\\nData Fields Explained:\\n- mailagent_name: Name of the + Mail Agent.\\n- mailagent_key: Mail Agent Key.\\n- mailagent_alias: + Mail Agent Alias.\\n- created_time: Time at which the Mail Agent was + created.\\n- status: Status of the Mail Agent.\\n\\nExample 1: To + retrieve details of all Mail Agents in the ZeptoMail account. Sample + prompt 1: Get me details of all the Mail Agents in the account. + + Swagger operation ID: `GetMailAgent`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/portal/v1.0/mailagents" + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_processed_emails( + self, + mailagent_key: str, + *, + subject: Optional[str] = None, + from_: Optional[str] = None, + to: Optional[str] = None, + date_from: Optional[str] = None, + date_to: Optional[str] = None, + request_id: Optional[str] = None, + is_hb: Optional[bool] = None, + is_sb: Optional[bool] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get processed email details + + This endpoint fetches detailed information about emails processed by + Mail Agent identified by its unique ID. It returns data including the + Subject, From Address, Sent time and Request ID for emails sent for the + time range. The mailagent_key parameter should match the Mail Agent key + of the Mail Agent as listed in our system. + + Swagger operation ID: `Get_Processed_Emails`. + + Args: + mailagent_key: Choose Mail Agent or enter the Mail Agent key. + subject: Enter subject of the email. + from_: Enter sender address of the email. + to: Enter recipient address of the email. + date_from: Enter from date for search in the format + yyyy-MM-ddTHH:mm:sszzz. + date_to: Enter to date for search in the format + yyyy-MM-ddTHH:mm:sszzz. + request_id: Enter Request ID of the email. + is_hb: Include hardbounces in results. + is_sb: Include softbounces in results. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/email" + query_params = [] + value = str(mailagent_key) + if isinstance(mailagent_key, bool): + value = value.lower() + query_params.append(f"mailagent_key={quote(value, safe='')}") + if subject is not None: + value = str(subject) + if isinstance(subject, bool): + value = value.lower() + query_params.append(f"subject={quote(value, safe='')}") + if from_ is not None: + value = str(from_) + if isinstance(from_, bool): + value = value.lower() + query_params.append(f"from={quote(value, safe='')}") + if to is not None: + value = str(to) + if isinstance(to, bool): + value = value.lower() + query_params.append(f"to={quote(value, safe='')}") + if date_from is not None: + value = str(date_from) + if isinstance(date_from, bool): + value = value.lower() + query_params.append(f"date_from={quote(value, safe='')}") + if date_to is not None: + value = str(date_to) + if isinstance(date_to, bool): + value = value.lower() + query_params.append(f"date_to={quote(value, safe='')}") + if request_id is not None: + value = str(request_id) + if isinstance(request_id, bool): + value = value.lower() + query_params.append(f"request_id={quote(value, safe='')}") + if is_hb is not None: + value = str(is_hb) + if isinstance(is_hb, bool): + value = value.lower() + query_params.append(f"is_hb={quote(value, safe='')}") + if is_sb is not None: + value = str(is_sb) + if isinstance(is_sb, bool): + value = value.lower() + query_params.append(f"is_sb={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_mail( + self, + input: SendMailInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send mail + + To send an email to the desired recipient. + + Swagger operation ID: `SendMail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/email" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_template_mail( + self, + input: SendTemplateMailInput | Mapping[str, Any], + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Send template mail + + Sending a single email using Templates. + + Swagger operation ID: `SendTemplateMail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/email/template" + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def processed_mail_stats( + self, + mailagent: str, + *, + from_time: Optional[str] = None, + to_time: Optional[str] = None, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Processed emails analytics + + This endpoint fetches emails analytics for emails sent by Mail Agent + identified by its Mail Agent name. It returns data including total + count of Hardbounce, Softbounce and Sent statistics over a period of + time and each day . The mailagent parameter should match the Mail Agent + name as listed in our system. + + Swagger operation ID: `Processed_Mail_Stats`. + + Args: + mailagent: Choose or enter Mail agent name. + from_time: Enter statics from date in the format + yyyy-MM-ddTHH:mm:sszzz. + to_time: Enter statics to date in the format + yyyy-MM-ddTHH:mm:sszzz. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/v1.0/stats/email" + query_params = [] + value = str(mailagent) + if isinstance(mailagent, bool): + value = value.lower() + query_params.append(f"mailagent={quote(value, safe='')}") + if from_time is not None: + value = str(from_time) + if isinstance(from_time, bool): + value = value.lower() + query_params.append(f"from_time={quote(value, safe='')}") + if to_time is not None: + value = str(to_time) + if isinstance(to_time, bool): + value = value.lower() + query_params.append(f"to_time={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) diff --git a/src/azure/connectors/aio/zohosign.py b/src/azure/connectors/aio/zohosign.py new file mode 100644 index 0000000..173db4e --- /dev/null +++ b/src/azure/connectors/aio/zohosign.py @@ -0,0 +1,896 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +# ZohosignClient.py - Auto-generated DirectClient SDK +# Do not edit this file directly. + +from __future__ import annotations + +from typing import Optional, AsyncIterator, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit +import json + +from azure.core.async_paging import AsyncItemPaged +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from azure.connectors.sdk.aio import ( + ConnectorClientBase, + ConnectorException, + ConnectorResponseHook, + ConnectorResponseSnapshot, +) + +from azure.connectors.zohosign import ( + GetDocumentResponse, + GetFormDataResponse, + GetTemplatesResponse, + InvokeAPIInput, + InvokeAPIResponse, + SendSignRequestResponse, + UpdateDocumentInput, + UpdateDocumentResponse, + ZohoSignTriggersInput, + TRIGGER_OPERATIONS, +) + +__all__ = [ + "ZohosignClient", + "GetDocumentResponse", + "GetFormDataResponse", + "GetTemplatesResponse", + "InvokeAPIInput", + "InvokeAPIResponse", + "SendSignRequestResponse", + "UpdateDocumentInput", + "UpdateDocumentResponse", + "ZohoSignTriggersInput", + "TRIGGER_OPERATIONS", +] + + +# Type Definitions + +# Client Class + +class ZohosignClient(ConnectorClientBase): + """Typed client for zohosign connector.""" + + def __init__( + self, + connection_runtime_url: str, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a ZohosignClient. + + Args: + connection_runtime_url: The connection runtime + URL from Azure Portal. + credential: Caller-owned Azure Core credential. + max_retry_attempts: The maximum number of request attempts. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. + Nonpositive values disable SDK and transport deadlines. + use_exponential_backoff: Whether retries use exponential backoff. + initial_retry_delay_seconds: The initial retry delay in seconds. + maximum_retry_delay_seconds: The maximum retry delay in seconds. + retry_jitter_factor: The jitter fraction applied to retry delays. + retry_unsafe_http_methods: Whether unsafe HTTP methods may be + retried. + transport: Optional Azure Core async HTTP transport closed by + the client through its asynchronous lifecycle. + **kwargs: Optional Azure Core pipeline policy settings. + """ + if not connection_runtime_url: + raise ValueError("connection_runtime_url cannot be None or empty") + + if credential is None: + raise ValueError("credential cannot be None") + + super().__init__( + credential, + max_retry_attempts=max_retry_attempts, + timeout=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + self._connection_runtime_url = connection_runtime_url.rstrip('/') + + @property + def connector_name(self) -> str: + return "zohosign" + + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + async def invoke_api( + self, + input: InvokeAPIInput | Mapping[str, Any], + url: str, + method: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Invoke API + + Invoke API + + Swagger operation ID: `InvokeAPI`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + url: Provide url path. + method: Select API Method to be used. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}/{quote(str(url), safe='')}" + ) + query_params = [] + value = str(method) + if isinstance(method, bool): + value = value.lower() + query_params.append(f"method={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + + response = await self.http_client.send( + "POST", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def download_completion_certificate( + self, + request_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Download Completion Certificate + + Downloads the completion certificate of a specific envelope + + Swagger operation ID: `download-completion-certificate`. + + Args: + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/requests" + f"/{quote(str(request_id), safe='')}" + f"/completioncertificate" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def download_document( + self, + request_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Download Document + + Downloads a specific envelope + + Swagger operation ID: `download-document`. + + Args: + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/requests/{quote(str(request_id), safe='')}/pdf" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def download_file( + self, + request_id: int, + document_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> bytes: + """ + Download File + + Downloads a specific document or file + + Swagger operation ID: `download-file`. + + Args: + request_id: Request ID. + document_id: Document ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/requests" + f"/{quote(str(request_id), safe='')}" + f"/documents" + f"/{quote(str(document_id), safe='')}" + f"/pdf" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response.content + + async def get_form_data( + self, + request_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get data of completed request + + Shows the details of a signed envelope + + Swagger operation ID: `get-form-data`. + + Args: + request_id: Request id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/requests/{quote(str(request_id), safe='')}/fielddata" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def recall_document( + self, + request_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Recall a particular document + + Recall a particular document + + Swagger operation ID: `recall-document`. + + Args: + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/requests/{quote(str(request_id), safe='')}/recall" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def remind_document_recipients( + self, + request_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Reminder for recipients + + Send a reminder to recipients of a particular document. + + Swagger operation ID: `remind-document-recipients`. + + Args: + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/requests/{quote(str(request_id), safe='')}/remind" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + async def delete_document( + self, + request_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Delete Document + + Delete a particular document + + Swagger operation ID: `delete-document`. + + Args: + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/requests/{quote(str(request_id), safe='')}/delete" + ) + + response = await self.http_client.send( + "PUT", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + async def get_document( + self, + request_id: int, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Get a document + + Shows the details of a specific envelope + + Swagger operation ID: `get-document`. + + Args: + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/requests/{quote(str(request_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def update_document( + self, + input: UpdateDocumentInput | Mapping[str, Any], + request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + Update the properties of a created request + + Update the properties of a created request + + Swagger operation ID: `UpdateDocument`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/requests/{quote(str(request_id), safe='')}" + ) + + response = await self.http_client.send( + "PUT", request_url, body=input, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "PUT", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def send_sign_request( + self, + request_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> dict[str, Any] | None: + """ + SendSignRequest + + Send the uploaded document out for signature + + Swagger operation ID: `SendSignRequest`. + + Args: + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/requests/{quote(str(request_id), safe='')}/submit" + ) + + response = await self.http_client.send( + "POST", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) + + if not response.text: + return None + + return json.loads(response.text) + + async def get_template_details( + self, + template_id: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """ + Get particular template details + + Shows the details of a specific document template + + Swagger operation ID: `get-template-details`. + + Args: + template_id: List of Templates. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/templates/{quote(str(template_id), safe='')}" + ) + + response = await self.http_client.send( + "GET", request_url, body=None, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + def list_templates( + self, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> AsyncItemPaged[dict[str, Any]]: + """ + Get list of templates + + Shows a list of all the document templates created + + Returns an Azure Core async pager that follows the connector + continuation URL. + + Swagger operation ID: `GetTemplates`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + AsyncItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `async for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/templates" + initial_request_url = request_url + request_body = None + + async def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = await self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) + + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + async def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], AsyncIterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + async def items() -> AsyncIterator[dict[str, Any]]: + for item in page.get("templates", []): + yield item + + return None, items() + + return AsyncItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/arm.py b/src/azure/connectors/arm.py index a6c63a4..9ec8e43 100644 --- a/src/azure/connectors/arm.py +++ b/src/azure/connectors/arm.py @@ -5,21 +5,73 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "ArmClient", + "AliasPathType", + "AliasType", + "BasicDependency", + "DebugSetting", + "Dependency", + "Deployment", + "DeploymentExportResult", + "DeploymentExtended", + "DeploymentListResult", + "DeploymentOperation", + "DeploymentOperationProperties", + "DeploymentOperationsListResult", + "DeploymentProperties", + "DeploymentPropertiesExtended", + "DeploymentValidateResult", + "ExportTemplateRequest", + "GenericResource", + "HttpMessage", + "Identity", + "Location", + "LocationListResult", + "ObjectWithoutType", + "ParametersLink", + "Plan", + "Provider", + "ProviderListResult", + "ProviderResourceType", + "ProviderResourcesInvokeInput", + "ProviderResourcesInvokeResponse", + "ResourceGroup", + "ResourceGroupExportResult", + "ResourceGroupListResult", + "ResourceGroupProperties", + "ResourceListResult", + "ResourceManagementErrorWithDetails", + "ResourcesInvokeInput", + "ResourcesInvokeResponse", + "Sku", + "Subscription", + "SubscriptionListResult", + "SubscriptionPolicies", + "TagCount", + "TagDetails", + "TagValue", + "TagsListResult", + "TargetResource", + "TemplateLink", +] + # Type Definitions @@ -29,7 +81,12 @@ class LocationListResult: Response for Lists the subscription locations """ - value: Optional[List[Location]] = None + value: Optional[ + List[Location | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The locations.""" @@ -39,34 +96,39 @@ class Subscription: Response for Read a subscription """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ The fully qualified Id. For example, /subscriptions/00000000-0000-0000-0000-000000000000. """ - subscription_id: Optional[str] = field( + subscription_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "subscriptionId"}, ) """The subscription Id.""" - tenant_id: Optional[str] = field( + tenant_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tenantId"}, ) """The tenant Id.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The subscription display name.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """The subscription state.""" - subscription_policies: Optional[SubscriptionPolicies] = field( + subscription_policies: Optional[SubscriptionPolicies | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "subscriptionPolicies"}, ) - authorization_source: Optional[str] = field( + authorization_source: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "authorizationSource"}, ) """ @@ -82,10 +144,16 @@ class SubscriptionListResult: Response for List subscriptions """ - value: Optional[List[Subscription]] = None + value: Optional[ + List[Subscription | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The subscriptions.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -97,11 +165,16 @@ class DeploymentExtended: Response for Read a template deployment """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the deployment.""" - name: Optional[str] = None + name: str """The name of the deployment.""" - properties: Optional[DeploymentPropertiesExtended] = None + properties: Optional[ + DeploymentPropertiesExtended | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -110,8 +183,18 @@ class DeploymentValidateResult: Response for Validate a template deployment """ - error: Optional[ResourceManagementErrorWithDetails] = None - properties: Optional[DeploymentPropertiesExtended] = None + error: Optional[ + ResourceManagementErrorWithDetails | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + properties: Optional[ + DeploymentPropertiesExtended | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -120,7 +203,7 @@ class DeploymentExportResult: Response for Export deployment template """ - template: Optional[Dict[str, Any]] = None + template: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The template content.""" @@ -130,10 +213,16 @@ class DeploymentListResult: Response for List template deployments """ - value: Optional[List[DeploymentExtended]] = None + value: Optional[ + List[DeploymentExtended | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of deployments.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -145,14 +234,20 @@ class DeploymentOperation: Response for Read a template deployment operation """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Full deployment operation id.""" - operation_id: Optional[str] = field( + operation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "operationId"}, ) """Deployment operation id.""" - properties: Optional[DeploymentOperationProperties] = None + properties: Optional[ + DeploymentOperationProperties | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -161,10 +256,16 @@ class DeploymentOperationsListResult: Response for Lists template deployment operations """ - value: Optional[List[DeploymentOperation]] = None + value: Optional[ + List[DeploymentOperation | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of deployments.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -176,17 +277,21 @@ class Provider: Response for Unregister resource provider """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The provider id.""" - namespace: Optional[str] = None + namespace: Optional[str] = dataclass_field(default=None, kw_only=True) """The namespace of the provider.""" - registration_state: Optional[str] = field( + registration_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "registrationState"}, ) """The registration state of the provider.""" - resource_types: Optional[List[ProviderResourceType]] = field( + resource_types: Optional[ + List[ProviderResourceType | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceTypes"}, ) """The collection of provider resource types.""" @@ -198,10 +303,16 @@ class ProviderListResult: Response for List resource providers """ - value: Optional[List[Provider]] = None + value: Optional[ + List[Provider | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of resource providers.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -213,10 +324,16 @@ class ResourceListResult: Response for List resources by resource group """ - value: Optional[List[GenericResource]] = None + value: Optional[ + List[GenericResource | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of resources.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -228,26 +345,32 @@ class ResourceGroup: Response for Read a resource group """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ The ID of the resource group (e.g. /subscriptions/XXX/resourceGroups/YYY). """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The Name of the resource group.""" - location: Optional[str] = None + location: str """ The location of the resource group. It cannot be changed after the resource group has been created. Has to be one of the supported Azure Locations, such as West US, East US, West Europe, East Asia, etc. """ - managed_by: Optional[str] = field( + managed_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managedBy"}, ) """Id of the resource that manages this resource group.""" - tags: Optional[Dict[str, str]] = None + tags: Optional[Dict[str, str]] = dataclass_field(default=None, kw_only=True) """The tags attached to the resource group.""" - properties: Optional[ResourceGroupProperties] = None + properties: Optional[ + ResourceGroupProperties | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -256,9 +379,14 @@ class ResourceGroupExportResult: Response for Export a resource group template """ - template: Optional[Dict[str, Any]] = None + template: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The template content.""" - error: Optional[ResourceManagementErrorWithDetails] = None + error: Optional[ + ResourceManagementErrorWithDetails | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -267,10 +395,16 @@ class ResourceGroupListResult: Response for List resource groups """ - value: Optional[List[ResourceGroup]] = None + value: Optional[ + List[ResourceGroup | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of resource groups.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -282,27 +416,32 @@ class GenericResource: Response for Read a resource """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Resource Id""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Resource name""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Resource type""" - location: Optional[str] = None + location: Optional[str] = dataclass_field(default=None, kw_only=True) """Resource location""" - tags: Optional[Dict[str, str]] = None + tags: Optional[Dict[str, str]] = dataclass_field(default=None, kw_only=True) """Resource tags""" - plan: Optional[Plan] = None - kind: Optional[str] = None + plan: Optional[Plan | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + kind: Optional[str] = dataclass_field(default=None, kw_only=True) """The kind of the resource.""" - managed_by: Optional[str] = field( + managed_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managedBy"}, ) """Id of the resource that manages this resource.""" - sku: Optional[Sku] = None - identity: Optional[Identity] = None - properties: Optional[Dict[str, Any]] = None + sku: Optional[Sku | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + identity: Optional[Identity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + properties: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The resource properties.""" @@ -312,7 +451,7 @@ class ResourcesInvokeInput: Invoke resource operation """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -325,7 +464,7 @@ class ResourcesInvokeResponse: Response for Invoke resource operation """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -338,7 +477,7 @@ class ProviderResourcesInvokeInput: Invoke resource operation in provider """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -351,7 +490,7 @@ class ProviderResourcesInvokeResponse: Response for Invoke resource operation in provider """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -364,14 +503,15 @@ class TagValue: Response for Create or update a subscription resource tag value """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The tag ID.""" - tag_value: Optional[str] = field( + tag_value: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tagValue"}, ) """The tag value.""" - count: Optional[TagCount] = None + count: Optional[TagCount | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -380,15 +520,21 @@ class TagDetails: Response for Create or update a subscription resource tag name """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The tag ID.""" - tag_name: Optional[str] = field( + tag_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tagName"}, ) """The tag name.""" - count: Optional[TagCount] = None - values: Optional[List[TagValue]] = None + count: Optional[TagCount | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + values: Optional[ + List[TagValue | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of tag values.""" @@ -398,10 +544,16 @@ class TagsListResult: Response for List subscription resource tags """ - value: Optional[List[TagDetails]] = None + value: Optional[ + List[TagDetails | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of tags.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -413,26 +565,28 @@ class Location: Definition: Location """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ The fully qualified Id of the location. For example, /subscriptions/00000000-0000-0000-0000-000000000000/locations/westus. """ - subscription_id: Optional[str] = field( + subscription_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "subscriptionId"}, ) """The subscription Id.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The location name.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The display name of the location.""" - latitude: Optional[str] = None + latitude: Optional[str] = dataclass_field(default=None, kw_only=True) """The latitude of the location.""" - longitude: Optional[str] = None + longitude: Optional[str] = dataclass_field(default=None, kw_only=True) """The longitude of the location.""" @@ -442,8 +596,9 @@ class SubscriptionPolicies: Definition: SubscriptionPolicies """ - location_placement_id: Optional[str] = field( + location_placement_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "locationPlacementId"}, ) """ @@ -451,13 +606,15 @@ class SubscriptionPolicies: visible for a subscription. For example, a subscription with a location placement Id of Public_2014-09-01 has access to Azure public regions. """ - quota_id: Optional[str] = field( + quota_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "quotaId"}, ) """The subscription quota Id.""" - spending_limit: Optional[str] = field( + spending_limit: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "spendingLimit"}, ) """The subscription spending limit.""" @@ -469,10 +626,11 @@ class TemplateLink: Definition: TemplateLink """ - uri: Optional[str] = None + uri: str """URI referencing the template.""" - content_version: Optional[str] = field( + content_version: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentVersion"}, ) """If included it must match the ContentVersion in the template.""" @@ -484,10 +642,11 @@ class ParametersLink: Definition: ParametersLink """ - uri: Optional[str] = None + uri: str """URI referencing the template.""" - content_version: Optional[str] = field( + content_version: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentVersion"}, ) """If included it must match the ContentVersion in the template.""" @@ -499,28 +658,31 @@ class DeploymentProperties: Definition: DeploymentProperties """ - template: Optional[Dict[str, Any]] = None + template: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """ The template content. It can be a JObject or a well formed JSON string. Use only one of Template or TemplateLink. """ - template_link: Optional[TemplateLink] = field( + template_link: Optional[TemplateLink | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "templateLink"}, ) - parameters: Optional[Dict[str, Any]] = None + parameters: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """ Deployment parameters. It can be a JObject or a well formed JSON string. Use only one of Parameters or ParametersLink. """ - parameters_link: Optional[ParametersLink] = field( + parameters_link: Optional[ParametersLink | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parametersLink"}, ) - mode: Optional[str] = None + mode: str """The deployment mode.""" - debug_setting: Optional[DebugSetting] = field( + debug_setting: Optional[DebugSetting | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "debugSetting"}, ) @@ -531,8 +693,9 @@ class DebugSetting: Definition: DebugSetting """ - detail_level: Optional[str] = field( + detail_level: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "detailLevel"}, ) """The debug detail level.""" @@ -544,7 +707,12 @@ class Deployment: Definition: Deployment """ - properties: Optional[DeploymentProperties] = None + properties: Optional[ + DeploymentProperties | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -553,13 +721,13 @@ class ResourceManagementErrorWithDetails: Definition: ResourceManagementErrorWithDetails """ - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """The error code returned from the server.""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """The error message returned from the server.""" - target: Optional[str] = None + target: Optional[str] = dataclass_field(default=None, kw_only=True) """The target of the error.""" - details: Optional[List[Dict[str, Any]]] = None + details: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Validation error.""" @@ -569,10 +737,11 @@ class AliasPathType: Definition: AliasPathType """ - path: Optional[str] = None + path: Optional[str] = dataclass_field(default=None, kw_only=True) """The path of an alias.""" - api_versions: Optional[List[str]] = field( + api_versions: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "apiVersions"}, ) """The api versions.""" @@ -584,9 +753,14 @@ class AliasType: Definition: AliasType """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The alias name.""" - paths: Optional[List[AliasPathType]] = None + paths: Optional[ + List[AliasPathType | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The paths for an alias.""" @@ -596,23 +770,35 @@ class ProviderResourceType: Definition: ProviderResourceType """ - resource_type: Optional[str] = field( + resource_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceType"}, ) """The resource type.""" - locations: Optional[List[ObjectWithoutType]] = None + locations: Optional[ + List[ObjectWithoutType | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """ The collection of locations where this resource type can be created in. """ - aliases: Optional[List[AliasType]] = None + aliases: Optional[ + List[AliasType | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The aliases that are supported by this resource type.""" - api_versions: Optional[List[str]] = field( + api_versions: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "apiVersions"}, ) """The api version.""" - properties: Optional[Dict[str, str]] = None + properties: Optional[Dict[str, str]] = dataclass_field(default=None, kw_only=True) """The properties.""" @@ -622,15 +808,17 @@ class BasicDependency: Definition: BasicDependency """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the dependency.""" - resource_type: Optional[str] = field( + resource_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceType"}, ) """The dependency resource type.""" - resource_name: Optional[str] = field( + resource_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceName"}, ) """The dependency resource name.""" @@ -642,20 +830,23 @@ class Dependency: Definition: Dependency """ - depends_on: Optional[List[BasicDependency]] = field( + depends_on: Optional[List[BasicDependency | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dependsOn"}, ) """The list of dependencies.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the dependency.""" - resource_type: Optional[str] = field( + resource_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceType"}, ) """The dependency resource type.""" - resource_name: Optional[str] = field( + resource_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceName"}, ) """The dependency resource name.""" @@ -667,40 +858,55 @@ class DeploymentPropertiesExtended: Definition: DeploymentPropertiesExtended """ - provisioning_state: Optional[str] = field( + provisioning_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "provisioningState"}, ) """The state of the provisioning.""" - correlation_id: Optional[str] = field( + correlation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "correlationId"}, ) """The correlation ID of the deployment.""" - timestamp: Optional[str] = None + timestamp: Optional[str] = dataclass_field(default=None, kw_only=True) """The timestamp of the template deployment.""" - outputs: Optional[Dict[str, Any]] = None + outputs: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Key/value pairs that represent deploymentoutput.""" - providers: Optional[List[Provider]] = None + providers: Optional[ + List[Provider | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of resource providers needed for the deployment.""" - dependencies: Optional[List[Dependency]] = None + dependencies: Optional[ + List[Dependency | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of deployment dependencies.""" - template: Optional[Dict[str, Any]] = None + template: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The template content. Use only one of Template or TemplateLink.""" - template_link: Optional[TemplateLink] = field( + template_link: Optional[TemplateLink | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "templateLink"}, ) - parameters: Optional[Dict[str, Any]] = None + parameters: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Deployment parameters. Use only one of Parameters or ParametersLink.""" - parameters_link: Optional[ParametersLink] = field( + parameters_link: Optional[ParametersLink | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parametersLink"}, ) - mode: Optional[str] = None + mode: str """The deployment mode.""" - debug_setting: Optional[DebugSetting] = field( + debug_setting: Optional[DebugSetting | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "debugSetting"}, ) @@ -711,14 +917,15 @@ class Plan: Definition: Plan """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The plan ID.""" - publisher: Optional[str] = None + publisher: Optional[str] = dataclass_field(default=None, kw_only=True) """The publisher ID.""" - product: Optional[str] = None + product: Optional[str] = dataclass_field(default=None, kw_only=True) """The offer ID.""" - promotion_code: Optional[str] = field( + promotion_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "promotionCode"}, ) """The promotion code.""" @@ -730,17 +937,17 @@ class Sku: Definition: Sku """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The sku name.""" - tier: Optional[str] = None + tier: Optional[str] = dataclass_field(default=None, kw_only=True) """The sku tier.""" - size: Optional[str] = None + size: Optional[str] = dataclass_field(default=None, kw_only=True) """The sku size.""" - family: Optional[str] = None + family: Optional[str] = dataclass_field(default=None, kw_only=True) """The sku family.""" - model: Optional[str] = None + model: Optional[str] = dataclass_field(default=None, kw_only=True) """The sku model.""" - capacity: Optional[int] = None + capacity: Optional[int] = dataclass_field(default=None, kw_only=True) """The sku capacity.""" @@ -750,17 +957,23 @@ class Identity: Definition: Identity """ - principal_id: Optional[str] = field( + principal_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "principalId"}, ) """The principal id of resource identity.""" - tenant_id: Optional[str] = field( + tenant_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tenantId"}, ) """The tenant id of resource.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The identity type.""" @@ -770,8 +983,9 @@ class ResourceGroupProperties: Definition: ResourceGroupProperties """ - provisioning_state: Optional[str] = field( + provisioning_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "provisioningState"}, ) """The provisioning state.""" @@ -783,12 +997,12 @@ class ExportTemplateRequest: Definition: ExportTemplateRequest """ - resources: Optional[List[str]] = None + resources: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ The ids of the resources. The only supported string currently is '*' (all resources). Future api updates will support exporting specific resources. """ - options: Optional[str] = None + options: Optional[str] = dataclass_field(default=None, kw_only=True) """ The export template options. Supported values include 'IncludeParameterDefaultValue', 'IncludeComments' or @@ -802,9 +1016,13 @@ class TagCount: Definition: TagCount """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type of count.""" - value: Optional[int] = None + value: Optional[int] = dataclass_field(default=None, kw_only=True) """Value of count.""" @@ -814,15 +1032,17 @@ class TargetResource: Definition: TargetResource """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the resource.""" - resource_name: Optional[str] = field( + resource_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceName"}, ) """The name of the resource.""" - resource_type: Optional[str] = field( + resource_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceType"}, ) """The type of the resource.""" @@ -834,7 +1054,7 @@ class HttpMessage: Definition: HttpMessage """ - content: Optional[Dict[str, Any]] = None + content: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """HTTP message content.""" @@ -844,34 +1064,44 @@ class DeploymentOperationProperties: Definition: DeploymentOperationProperties """ - provisioning_state: Optional[str] = field( + provisioning_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "provisioningState"}, ) """The state of the provisioning.""" - timestamp: Optional[str] = None + timestamp: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time of the operation.""" - service_request_id: Optional[str] = field( + service_request_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "serviceRequestId"}, ) """Deployment operation service request id.""" - status_code: Optional[str] = field( + status_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "statusCode"}, ) """Operation status code.""" - status_message: Optional[Dict[str, Any]] = field( + status_message: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "statusMessage"}, ) """Operation status message.""" - target_resource: Optional[TargetResource] = field( + target_resource: Optional[TargetResource | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "targetResource"}, ) - request: Optional[HttpMessage] = None - response: Optional[HttpMessage] = None + request: Optional[HttpMessage | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + response: Optional[ + HttpMessage | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -880,7 +1110,7 @@ class ObjectWithoutType: Definition: ObjectWithoutType """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -895,16 +1125,16 @@ class ArmClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -915,8 +1145,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -924,8 +1154,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -937,7 +1167,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -959,7 +1189,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -991,7 +1221,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def subscriptions_list_locations_async( + def list_subscriptions_list_locations( self, subscription_id: str, *, @@ -999,11 +1229,32 @@ async def subscriptions_list_locations_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Lists the subscription locations Lists the locations available for the subscription. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Subscriptions_ListLocations`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1013,29 +1264,50 @@ async def subscriptions_list_locations_async( query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def subscriptions_get_async( + def subscriptions_get( self, subscription_id: str, *, @@ -1048,6 +1320,23 @@ async def subscriptions_get_async( Read a subscription Reads the details for a particular subscription. + + Swagger operation ID: `Subscriptions_Get`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1058,7 +1347,7 @@ async def subscriptions_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1072,6 +1361,7 @@ async def subscriptions_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1079,32 +1369,54 @@ async def subscriptions_get_async( return json.loads(response.text) - async def subscriptions_list_async( + def list_subscriptions( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List subscriptions Gets a list of all the subscriptions to which the principal has access. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Subscriptions_List`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/subscriptions" query_params = [] query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1117,29 +1429,38 @@ async def subscriptions_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def deployments_get_async( + return ItemPaged(get_next, extract_data) + + def deployments_get( self, subscription_id: str, resource_group_name: str, deployment_name: str, - wait: Optional[bool] = None, *, + wait: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1149,6 +1470,27 @@ async def deployments_get_async( Read a template deployment Reads a template deployment within a resource group. + + Swagger operation ID: `Deployments_Get`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the resource group template + deployment. + wait: If the action should wait until deployment is completed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1171,7 +1513,7 @@ async def deployments_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1185,6 +1527,7 @@ async def deployments_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1192,14 +1535,14 @@ async def deployments_get_async( return json.loads(response.text) - async def deployments_create_or_update_async( + def deployments_create_or_update( self, - input: Deployment, + input: Deployment | Mapping[str, Any], subscription_id: str, resource_group_name: str, deployment_name: str, - wait: Optional[bool] = None, *, + wait: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1210,6 +1553,28 @@ async def deployments_create_or_update_async( Create or update a named resource group template deployment. A template and parameters are expected for the request to succeed. + + Swagger operation ID: `Deployments_CreateOrUpdate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the deployment. + wait: If the action should wait until deployment is completed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1232,7 +1597,7 @@ async def deployments_create_or_update_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1246,6 +1611,7 @@ async def deployments_create_or_update_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1253,7 +1619,7 @@ async def deployments_create_or_update_async( return json.loads(response.text) - async def deployments_delete_async( + def deployments_delete( self, subscription_id: str, resource_group_name: str, @@ -1269,6 +1635,26 @@ async def deployments_delete_async( Deletes a resource group template deployment. The resources will not be deleted; only the metadata about the template deployment. + + Swagger operation ID: `Deployments_Delete`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the resource group template + deployment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1286,7 +1672,7 @@ async def deployments_delete_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1294,15 +1680,19 @@ async def deployments_delete_async( response_hook=response_hook, ) + if response.status == 404: + return None + if not (200 <= response.status < 300): raise ConnectorException( "DELETE", request_url, response.status, response.text, + response=response, ) - async def deployments_cancel_async( + def deployments_cancel( self, subscription_id: str, resource_group_name: str, @@ -1318,6 +1708,26 @@ async def deployments_cancel_async( Cancel a currently running template deployment. All pending template operations will be suspended. + + Swagger operation ID: `Deployments_Cancel`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the resource group template + deployment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1336,7 +1746,7 @@ async def deployments_cancel_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1350,11 +1760,12 @@ async def deployments_cancel_async( request_url, response.status, response.text, + response=response, ) - async def deployments_validate_async( + def deployments_validate( self, - input: Deployment, + input: Deployment | Mapping[str, Any], subscription_id: str, resource_group_name: str, deployment_name: str, @@ -1370,6 +1781,28 @@ async def deployments_validate_async( Validates a deployment template. This operation does not have side effects and can be used to test a template deployment for syntax or logical errors. + + Swagger operation ID: `Deployments_Validate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the resource group template + deployment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1388,7 +1821,7 @@ async def deployments_validate_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1402,6 +1835,7 @@ async def deployments_validate_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1409,7 +1843,7 @@ async def deployments_validate_async( return json.loads(response.text) - async def deployments_export_template_async( + def deployments_export_template( self, subscription_id: str, resource_group_name: str, @@ -1424,6 +1858,26 @@ async def deployments_export_template_async( Export deployment template Exports a template from a past resource group deployment. + + Swagger operation ID: `Deployments_ExportTemplate`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the resource group template + deployment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1442,7 +1896,7 @@ async def deployments_export_template_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1456,6 +1910,7 @@ async def deployments_export_template_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1463,26 +1918,47 @@ async def deployments_export_template_async( return json.loads(response.text) - async def deployments_list_async( + def list_deployments( self, subscription_id: str, resource_group_name: str, + *, filter: Optional[str] = None, top: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List template deployments Lists all the resource group template deployments. This operation is useful to know what has been provisioned thus far. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Deployments_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + filter: The filter to apply on the operation. + top: Query parameters. If nothing is passed returns all values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1508,11 +1984,18 @@ async def deployments_list_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1525,23 +2008,32 @@ async def deployments_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def deployment_operations_get_async( + return ItemPaged(get_next, extract_data) + + def deployment_operations_get( self, subscription_id: str, resource_group_name: str, @@ -1558,6 +2050,27 @@ async def deployment_operations_get_async( Reads a particular resource group template deployment operation. This is useful for troubleshooting failed template deployments. + + Swagger operation ID: `DeploymentOperations_Get`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the resource group template + deployment. + operation_id: Operation Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1575,7 +2088,7 @@ async def deployment_operations_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1589,6 +2102,7 @@ async def deployment_operations_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1596,26 +2110,48 @@ async def deployment_operations_get_async( return json.loads(response.text) - async def deployment_operations_list_async( + def list_deployment_operations( self, subscription_id: str, resource_group_name: str, deployment_name: str, - top: Optional[int] = None, *, + top: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Lists template deployment operations Lists all the template deployment operations. This is useful for troubleshooting failed template deployments. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `DeploymentOperations_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + deployment_name: The name of the resource group template + deployment. + top: Query parameters. If nothing is passed returns all values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1636,11 +2172,18 @@ async def deployment_operations_list_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1653,23 +2196,32 @@ async def deployment_operations_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def providers_unregister_async( + return ItemPaged(get_next, extract_data) + + def providers_unregister( self, subscription_id: str, resource_provider_namespace: str, @@ -1685,6 +2237,24 @@ async def providers_unregister_async( Unregisters provider from a subscription. This operation will fail if there are any resources from that resource provider in the subscription. + + Swagger operation ID: `Providers_Unregister`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_provider_namespace: Namespace of the resource provider. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1699,7 +2269,7 @@ async def providers_unregister_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1713,6 +2283,7 @@ async def providers_unregister_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1720,7 +2291,7 @@ async def providers_unregister_async( return json.loads(response.text) - async def providers_register_async( + def providers_register( self, subscription_id: str, resource_provider_namespace: str, @@ -1735,6 +2306,24 @@ async def providers_register_async( Registers a resource provider to be used with a subscription. This will provision permissions for the service into your subscription. + + Swagger operation ID: `Providers_Register`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_provider_namespace: Namespace of the resource provider. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1749,7 +2338,7 @@ async def providers_register_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1763,6 +2352,7 @@ async def providers_register_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1770,24 +2360,44 @@ async def providers_register_async( return json.loads(response.text) - async def providers_list_async( + def list_providers( self, subscription_id: str, + *, top: Optional[int] = None, expand: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List resource providers Lists the resource providers available for the subscription. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Providers_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + top: Query parameters. If nothing is passed returns all values. + expand: The $expand query parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1807,11 +2417,18 @@ async def providers_list_async( query_params.append(f"$expand={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1824,28 +2441,37 @@ async def providers_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def providers_get_async( + return ItemPaged(get_next, extract_data) + + def providers_get( self, subscription_id: str, resource_provider_namespace: str, - expand: Optional[str] = None, *, + expand: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1855,6 +2481,25 @@ async def providers_get_async( Read resource provider Reads a particular resource provider within the subscription. + + Swagger operation ID: `Providers_Get`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_provider_namespace: Namespace of the resource provider. + expand: The $expand query parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1873,7 +2518,7 @@ async def providers_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1887,6 +2532,7 @@ async def providers_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1894,26 +2540,48 @@ async def providers_get_async( return json.loads(response.text) - async def resource_groups_list_resources_async( + def list_resource_groups_list_resources( self, subscription_id: str, resource_group_name: str, + *, filter: Optional[str] = None, expand: Optional[str] = None, top: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List resources by resource group Lists all the resources under a resource group. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ResourceGroups_ListResources`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + filter: The filter to apply on the operation. + expand: The $expand query parameter. + top: Query parameters. If nothing is passed returns all values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1942,11 +2610,18 @@ async def resource_groups_list_resources_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1959,23 +2634,32 @@ async def resource_groups_list_resources_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def resource_groups_get_async( + return ItemPaged(get_next, extract_data) + + def resource_groups_get( self, subscription_id: str, resource_group_name: str, @@ -1989,6 +2673,24 @@ async def resource_groups_get_async( Read a resource group Reads a particular resource group within the subscription. + + Swagger operation ID: `ResourceGroups_Get`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2002,7 +2704,7 @@ async def resource_groups_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2016,6 +2718,7 @@ async def resource_groups_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2023,9 +2726,9 @@ async def resource_groups_get_async( return json.loads(response.text) - async def resource_groups_create_or_update_async( + def resource_groups_create_or_update( self, - input: ResourceGroup, + input: ResourceGroup | Mapping[str, Any], subscription_id: str, resource_group_name: str, *, @@ -2039,6 +2742,27 @@ async def resource_groups_create_or_update_async( Creates or updates a resource group. The response code can be used to distinguish between a create (201) or update (200). + + Swagger operation ID: `ResourceGroups_CreateOrUpdate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: The name of the resource group to be created + or updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2052,7 +2776,7 @@ async def resource_groups_create_or_update_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -2066,6 +2790,7 @@ async def resource_groups_create_or_update_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2073,7 +2798,7 @@ async def resource_groups_create_or_update_async( return json.loads(response.text) - async def resource_groups_delete_async( + def resource_groups_delete( self, subscription_id: str, resource_group_name: str, @@ -2087,6 +2812,24 @@ async def resource_groups_delete_async( Delete a resource group Delete a particular resource group within the subscription. + + Swagger operation ID: `ResourceGroups_Delete`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2100,7 +2843,7 @@ async def resource_groups_delete_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2114,11 +2857,12 @@ async def resource_groups_delete_async( request_url, response.status, response.text, + response=response, ) - async def resource_groups_patch_async( + def resource_groups_patch( self, - input: ResourceGroup, + input: ResourceGroup | Mapping[str, Any], subscription_id: str, resource_group_name: str, *, @@ -2132,6 +2876,26 @@ async def resource_groups_patch_async( Updates an existing resource group. If the resource does not exist, this request will fail. + + Swagger operation ID: `ResourceGroups_Patch`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2145,7 +2909,7 @@ async def resource_groups_patch_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -2159,6 +2923,7 @@ async def resource_groups_patch_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2166,9 +2931,9 @@ async def resource_groups_patch_async( return json.loads(response.text) - async def resource_groups_export_template_async( + def resource_groups_export_template( self, - input: ExportTemplateRequest, + input: ExportTemplateRequest | Mapping[str, Any], subscription_id: str, resource_group_name: str, *, @@ -2183,6 +2948,26 @@ async def resource_groups_export_template_async( Exports a deployment template from an existing resource group. This can only be successful if the underlying resources have a schema defined by Microsoft. + + Swagger operation ID: `ResourceGroups_ExportTemplate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2197,7 +2982,7 @@ async def resource_groups_export_template_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2211,6 +2996,7 @@ async def resource_groups_export_template_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2218,25 +3004,45 @@ async def resource_groups_export_template_async( return json.loads(response.text) - async def resource_groups_list_async( + def list_resource_groups( self, subscription_id: str, + *, filter: Optional[str] = None, top: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List resource groups Lists all the resource groups within the subscription. The results are paginated at 1,000+ records. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ResourceGroups_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + filter: The filter to apply on the operation. + top: Query parameters. If nothing is passed returns all values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2258,11 +3064,18 @@ async def resource_groups_list_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2275,42 +3088,72 @@ async def resource_groups_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def resources_list_async( + def list_resources( self, subscription_id: str, + *, filter: Optional[str] = None, expand: Optional[str] = None, top: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List resources by subscription Reads all of the resources under a particular subscription. The results are paginated at 1,000+ records. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Resources_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + filter: The filter to apply on the operation. + expand: The $expand query parameter. + top: Query parameters. If nothing is passed returns all values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2335,11 +3178,18 @@ async def resources_list_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2352,23 +3202,32 @@ async def resources_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def resources_get_by_id_async( + return ItemPaged(get_next, extract_data) + + def resources_get_by_id( self, subscription_id: str, resource_group_name: str, @@ -2385,6 +3244,28 @@ async def resources_get_by_id_async( Read a resource Reads a resource object. + + Swagger operation ID: `Resources_GetById`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + resource_provider_namespace: Namespace of the resource provider. + short_resource_id: The short Id of the resource, including the + resource name and resource type. For example, sites/mySite. + x_ms_api_version: Api Version to be used. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2404,7 +3285,7 @@ async def resources_get_by_id_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2418,6 +3299,7 @@ async def resources_get_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2425,9 +3307,9 @@ async def resources_get_by_id_async( return json.loads(response.text) - async def resources_create_or_update_by_id_async( + def resources_create_or_update_by_id( self, - input: GenericResource, + input: GenericResource | Mapping[str, Any], subscription_id: str, resource_group_name: str, resource_provider_namespace: str, @@ -2444,6 +3326,30 @@ async def resources_create_or_update_by_id_async( Creates or updates a resource. The response code can be used to distinguish between a create (201) or update (200). + + Swagger operation ID: `Resources_CreateOrUpdateById`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + resource_provider_namespace: Namespace of the resource provider. + short_resource_id: The short Id of the resource, including the + resource name and resource type. For example, sites/mySite. + x_ms_api_version: Api Version to be used. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2463,7 +3369,7 @@ async def resources_create_or_update_by_id_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -2477,6 +3383,7 @@ async def resources_create_or_update_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2484,7 +3391,7 @@ async def resources_create_or_update_by_id_async( return json.loads(response.text) - async def resources_delete_by_id_async( + def resources_delete_by_id( self, subscription_id: str, resource_group_name: str, @@ -2501,6 +3408,28 @@ async def resources_delete_by_id_async( Delete a resource Deletes a resource. + + Swagger operation ID: `Resources_DeleteById`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + resource_provider_namespace: Namespace of the resource provider. + short_resource_id: The short Id of the resource, including the + resource name and resource type. For example, sites/mySite. + x_ms_api_version: Api Version to be used. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2520,7 +3449,7 @@ async def resources_delete_by_id_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2534,11 +3463,12 @@ async def resources_delete_by_id_async( request_url, response.status, response.text, + response=response, ) - async def resources_invoke_async( + def resources_invoke( self, - input: ResourcesInvokeInput, + input: ResourcesInvokeInput | Mapping[str, Any], subscription_id: str, resource_group_name: str, resource_provider_namespace: str, @@ -2555,6 +3485,31 @@ async def resources_invoke_async( Invoke resource operation Invokes an operation on an Azure resource. + + Swagger operation ID: `Resources_Invoke`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + resource_provider_namespace: Namespace of the resource provider. + short_resource_id: The short Id of the resource, including the + resource name and resource type. For example, sites/mySite. + action_name: Name of the resource action to invoke. + x_ms_api_version: Api Version to be used. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2575,7 +3530,7 @@ async def resources_invoke_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2589,6 +3544,7 @@ async def resources_invoke_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2596,7 +3552,7 @@ async def resources_invoke_async( return json.loads(response.text) - async def provider_resources_get_by_id_async( + def provider_resources_get_by_id( self, subscription_id: str, resource_provider_namespace: str, @@ -2612,6 +3568,27 @@ async def provider_resources_get_by_id_async( Read a resource in provider Reads a resource object. + + Swagger operation ID: `Provider_Resources_GetById`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_provider_namespace: Namespace of the resource provider. + short_resource_id: The short Id of the resource, including the + resource name and resource type. For example, sites/mySite. + x_ms_api_version: Api Version to be used. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2629,7 +3606,7 @@ async def provider_resources_get_by_id_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2643,6 +3620,7 @@ async def provider_resources_get_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2650,9 +3628,9 @@ async def provider_resources_get_by_id_async( return json.loads(response.text) - async def provider_resources_invoke_async( + def provider_resources_invoke( self, - input: ProviderResourcesInvokeInput, + input: ProviderResourcesInvokeInput | Mapping[str, Any], subscription_id: str, resource_provider_namespace: str, short_resource_id: str, @@ -2667,6 +3645,29 @@ async def provider_resources_invoke_async( Invoke resource operation in provider Invokes an operation on an Azure resource. + + Swagger operation ID: `Provider_Resources_Invoke`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_provider_namespace: Namespace of the resource provider. + short_resource_id: The short Id of the resource, including the + resource name and resource type. For example, sites/mySite. + x_ms_api_version: Api Version to be used. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2684,7 +3685,7 @@ async def provider_resources_invoke_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2698,6 +3699,7 @@ async def provider_resources_invoke_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2705,7 +3707,7 @@ async def provider_resources_invoke_async( return json.loads(response.text) - async def tags_create_or_update_value_async( + def tags_create_or_update_value( self, subscription_id: str, tag_name: str, @@ -2720,6 +3722,25 @@ async def tags_create_or_update_value_async( Create or update a subscription resource tag value Create or update a subscription resource tag value. + + Swagger operation ID: `Tags_CreateOrUpdateValue`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + tag_name: The name of the tag. + tag_value: The value of the tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2735,7 +3756,7 @@ async def tags_create_or_update_value_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -2749,6 +3770,7 @@ async def tags_create_or_update_value_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2756,7 +3778,7 @@ async def tags_create_or_update_value_async( return json.loads(response.text) - async def tags_delete_value_async( + def tags_delete_value( self, subscription_id: str, tag_name: str, @@ -2771,6 +3793,25 @@ async def tags_delete_value_async( Delete a subscription resource tag value Delete a subscription resource tag value. + + Swagger operation ID: `Tags_DeleteValue`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + tag_name: The name of the tag. + tag_value: The value of the tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2786,7 +3827,7 @@ async def tags_delete_value_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2800,9 +3841,10 @@ async def tags_delete_value_async( request_url, response.status, response.text, + response=response, ) - async def tags_create_or_update_async( + def tags_create_or_update( self, subscription_id: str, tag_name: str, @@ -2816,6 +3858,24 @@ async def tags_create_or_update_async( Create or update a subscription resource tag name Create or update a subscription resource tag name. + + Swagger operation ID: `Tags_CreateOrUpdate`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + tag_name: The name of the tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2829,7 +3889,7 @@ async def tags_create_or_update_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -2843,6 +3903,7 @@ async def tags_create_or_update_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2850,7 +3911,7 @@ async def tags_create_or_update_async( return json.loads(response.text) - async def tags_delete_async( + def tags_delete( self, subscription_id: str, tag_name: str, @@ -2864,6 +3925,24 @@ async def tags_delete_async( Delete a subscription resource tag name Delete a subscription resource tag name. + + Swagger operation ID: `Tags_Delete`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + tag_name: The name of the tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2877,7 +3956,7 @@ async def tags_delete_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2891,9 +3970,10 @@ async def tags_delete_async( request_url, response.status, response.text, + response=response, ) - async def tags_list_async( + def list_tags( self, subscription_id: str, *, @@ -2901,14 +3981,32 @@ async def tags_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List subscription resource tags Lists all the subscription resource tags. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Tags_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2918,11 +4016,18 @@ async def tags_list_async( query_params.append("x-ms-api-version=" + quote("2016-06-01", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2935,18 +4040,27 @@ async def tags_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/azuread.py b/src/azure/connectors/azuread.py index 1b3c5aa..d06fc76 100644 --- a/src/azure/connectors/azuread.py +++ b/src/azure/connectors/azuread.py @@ -5,21 +5,41 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "AzureadClient", + "AssignManagerRequest", + "CheckMemberGroupsRequest", + "CreateGroupInput", + "CreateGroupResponse", + "CreateOffice365GroupInput", + "CreateSecurityGroupInput", + "CreateUserRequest", + "GetGroupMembersResponse", + "GetGroupRequest", + "GetGroupResponse", + "GetMemberGroupsRequest", + "GetMemberGroupsResponse", + "GetMemberGroupsResponseV2", + "GetUserResponse", + "UpdateUserRequest", +] + # Type Definitions @@ -29,32 +49,23 @@ class CreateOffice365GroupInput: Create Office 365 group """ - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """Display name of the new group.""" - description: Optional[str] = None + description: str """Description of the new group.""" - mail_nickname: Optional[str] = field( - default=None, + mail_nickname: str = dataclass_field( metadata={"wire_name": "mailNickname"}, ) """The mail alias of the new group.""" - group_types: Optional[List[str]] = field( - default=None, + group_types: List[str] = dataclass_field( metadata={"wire_name": "groupTypes"}, ) """For Office 365, group type is 'Unified'.""" - security_enabled: Optional[bool] = field( - default=None, + security_enabled: bool = dataclass_field( metadata={"wire_name": "securityEnabled"}, ) """True if the new group is a security group.""" - mail_enabled: Optional[bool] = field( - default=None, - metadata={"wire_name": "mailEnabled"}, - ) + mail_enabled: bool = dataclass_field(metadata={"wire_name": "mailEnabled"}) """True if the new group is a mailing group.""" @@ -64,80 +75,93 @@ class CreateGroupResponse: Response for Create Office 365 group """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """@odata.context""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - deleted_date_time: Optional[str] = field( + deleted_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "deletedDateTime"}, ) """deletedDateTime""" - classification: Optional[str] = None + classification: Optional[str] = dataclass_field(default=None, kw_only=True) """classification""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """createdDateTime""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """description""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """displayName""" - group_types: Optional[List[str]] = field( + group_types: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "groupTypes"}, ) """groupTypes""" - mail: Optional[str] = None + mail: Optional[str] = dataclass_field(default=None, kw_only=True) """mail""" - mail_enabled: Optional[bool] = field( + mail_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mailEnabled"}, ) """mailEnabled""" - mail_nickname: Optional[str] = field( + mail_nickname: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mailNickname"}, ) """mailNickname""" - on_premises_last_sync_date_time: Optional[str] = field( + on_premises_last_sync_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onPremisesLastSyncDateTime"}, ) """onPremisesLastSyncDateTime""" - on_premises_security_identifier: Optional[str] = field( + on_premises_security_identifier: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onPremisesSecurityIdentifier"}, ) """onPremisesSecurityIdentifier""" - on_premises_sync_enabled: Optional[bool] = field( + on_premises_sync_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onPremisesSyncEnabled"}, ) """onPremisesSyncEnabled""" - proxy_addresses: Optional[List[str]] = field( + proxy_addresses: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "proxyAddresses"}, ) """proxyAddresses""" - renewed_date_time: Optional[str] = field( + renewed_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "renewedDateTime"}, ) """renewedDateTime""" - security_enabled: Optional[bool] = field( + security_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "securityEnabled"}, ) """securityEnabled""" - visibility: Optional[str] = None + visibility: Optional[str] = dataclass_field(default=None, kw_only=True) """visibility""" @@ -147,27 +171,19 @@ class CreateSecurityGroupInput: Create security group """ - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """Display name of the new group.""" - description: Optional[str] = None + description: str """Description of the new group.""" - mail_nickname: Optional[str] = field( - default=None, + mail_nickname: str = dataclass_field( metadata={"wire_name": "mailNickname"}, ) """The mail alias of the new group.""" - security_enabled: Optional[bool] = field( - default=None, + security_enabled: bool = dataclass_field( metadata={"wire_name": "securityEnabled"}, ) """True if the new group is a security group.""" - mail_enabled: Optional[bool] = field( - default=None, - metadata={"wire_name": "mailEnabled"}, - ) + mail_enabled: bool = dataclass_field(metadata={"wire_name": "mailEnabled"}) """True if the new group is a mailing group.""" @@ -177,51 +193,58 @@ class GetGroupResponse: Response for Get group """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique identifier for the group.""" - deleted_date_time: Optional[str] = field( + deleted_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "deletedDateTime"}, ) """Date-time the group was deleted.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """Date-time the group was created.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """An optional description for the group.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The display name for the group.""" - mail: Optional[str] = None + mail: Optional[str] = dataclass_field(default=None, kw_only=True) """The SMTP address for the group.""" - mail_enabled: Optional[bool] = field( + mail_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mailEnabled"}, ) """True if the group is mail-enabled.""" - on_premises_last_sync_date_time: Optional[str] = field( + on_premises_last_sync_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onPremisesLastSyncDateTime"}, ) """ A date-time indicating the last time at which the group was synced with the on-premises directory. """ - on_premises_sync_enabled: Optional[bool] = field( + on_premises_sync_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onPremisesSyncEnabled"}, ) """True if this group is synced from an on-premises directory.""" - security_enabled: Optional[bool] = field( + security_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "securityEnabled"}, ) """True if the group is a security group.""" - visibility: Optional[str] = None + visibility: Optional[str] = dataclass_field(default=None, kw_only=True) """Visibility of the group (public or private).""" @@ -231,51 +254,59 @@ class GetUserResponse: Response for Get user """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """A unique identifier for the user.""" - business_phones: Optional[List[str]] = field( + business_phones: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "businessPhones"}, ) - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The name displayed in the address book for the user.""" - given_name: Optional[str] = field( + given_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "givenName"}, ) """The given name (first name) of the user.""" - job_title: Optional[str] = field( + job_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobTitle"}, ) """The user's job title.""" - mail: Optional[str] = None + mail: Optional[str] = dataclass_field(default=None, kw_only=True) """The SMTP address for the user.""" - mobile_phone: Optional[str] = field( + mobile_phone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mobilePhone"}, ) """The primary cellular telephone number for the user.""" - office_location: Optional[str] = field( + office_location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "officeLocation"}, ) """The office location in the user's place of business.""" - preferred_language: Optional[str] = field( + preferred_language: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "preferredLanguage"}, ) """ The preferred language for the user. Should follow ISO 639-1 Code; for example 'en-US'. """ - surname: Optional[str] = None + surname: Optional[str] = dataclass_field(default=None, kw_only=True) """The user's surname (family name or last name).""" - user_principal_name: Optional[str] = field( + user_principal_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userPrincipalName"}, ) """The user principal name (UPN) of the user.""" @@ -287,12 +318,18 @@ class GetGroupMembersResponse: Response for Get group members """ - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """Link to get next page of results""" - value: Optional[List[GetUserResponse]] = None + value: Optional[ + List[GetUserResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Array of users that are members of the group.""" @@ -302,34 +339,25 @@ class CreateGroupInput: Create group """ - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """Display name of the new group.""" - description: Optional[str] = None + description: str """Description of the new group.""" - mail_nickname: Optional[str] = field( - default=None, + mail_nickname: str = dataclass_field( metadata={"wire_name": "mailNickname"}, ) """The mail alias of the new group.""" - group_types: Optional[List[str]] = field( - default=None, + group_types: List[str] = dataclass_field( metadata={"wire_name": "groupTypes"}, ) """ Choose 'Unified' for an O365 group. Choose 'None' for a security group. """ - security_enabled: Optional[bool] = field( - default=None, + security_enabled: bool = dataclass_field( metadata={"wire_name": "securityEnabled"}, ) """True if the new group is a security group.""" - mail_enabled: Optional[bool] = field( - default=None, - metadata={"wire_name": "mailEnabled"}, - ) + mail_enabled: bool = dataclass_field(metadata={"wire_name": "mailEnabled"}) """True if the new group is a mailing group.""" @@ -339,7 +367,7 @@ class GetMemberGroupsResponseV2: Response for Check group membership (V2) """ - value: Optional[GetMemberGroupsResponse] = None + value: Optional[GetMemberGroupsResponse] = dataclass_field(default=None, kw_only=True) @dataclass @@ -348,10 +376,7 @@ class GetGroupRequest: Definition: GetGroup_Request """ - id: Optional[str] = field( - default=None, - metadata={"wire_name": "@odata.id"}, - ) + id: str = dataclass_field(metadata={"wire_name": "@odata.id"}) """ Unique identifier of a user (Ex. '5e6cf5c7-b511-4842-6aae-3f6b8ae5e95b'). """ @@ -363,10 +388,7 @@ class AssignManagerRequest: Definition: AssignManager_Request """ - id: Optional[str] = field( - default=None, - metadata={"wire_name": "@odata.id"}, - ) + id: str = dataclass_field(metadata={"wire_name": "@odata.id"}) """ Unique identifier of a manager (Ex. '5f6cf5c7-a561-4842-9aae-3e6d8ce5e95b'). @@ -379,76 +401,89 @@ class UpdateUserRequest: Definition: UpdateUser_Request """ - user_principal_name: Optional[str] = field( + user_principal_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userPrincipalName"}, ) """The user principal name (UPN) of the user.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The name displayed in the address book for the user.""" - mail_nickname: Optional[str] = field( + mail_nickname: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mailNickname"}, ) """The mail alias for the user.""" - given_name: Optional[str] = field( + given_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "givenName"}, ) """The given name (first name) of the user.""" - surname: Optional[str] = None + surname: Optional[str] = dataclass_field(default=None, kw_only=True) """The user's surname (family name or last name).""" - account_enabled: Optional[bool] = field( + account_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "accountEnabled"}, ) """True if the new account should be enabled.""" - job_title: Optional[str] = field( + job_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobTitle"}, ) """The user's job title.""" - department: Optional[str] = None + department: Optional[str] = dataclass_field(default=None, kw_only=True) """The name for the department in which the user works.""" - mobile_phone: Optional[str] = field( + mobile_phone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mobilePhone"}, ) """ The mobile phone number for the user in any format such as '1 (234) 567-8910'. """ - office_location: Optional[str] = field( + office_location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "officeLocation"}, ) """The office location in the user's place of business.""" - preferred_language: Optional[str] = field( + preferred_language: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "preferredLanguage"}, ) """ The preferred language for the user. Should follow ISO 639-1 Code; for example 'en-US'. """ - business_phones: Optional[List[str]] = field( + business_phones: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "businessPhones"}, ) - other_mails: Optional[List[str]] = field( + other_mails: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "otherMails"}, ) - custom_properties: Optional[Dict[str, str]] = field( + custom_properties: Optional[Dict[str, str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customProperties"}, ) """Free form property name and value for this user.""" - on_premises_extension_attributes: Optional[Dict[str, Any]] = field( + on_premises_extension_attributes: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onPremisesExtensionAttributes"}, ) @@ -459,8 +494,7 @@ class GetMemberGroupsRequest: Definition: GetMemberGroups_Request """ - security_enabled_only: Optional[bool] = field( - default=None, + security_enabled_only: bool = dataclass_field( metadata={"wire_name": "securityEnabledOnly"}, ) """Determines if only security enabled groups should be fetched.""" @@ -475,64 +509,63 @@ class CreateUserRequest: Definition: CreateUser_Request """ - account_enabled: Optional[bool] = field( - default=None, + account_enabled: bool = dataclass_field( metadata={"wire_name": "accountEnabled"}, ) """True if the new account should be enabled when it is created.""" - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """The name displayed in the address book for the user.""" - mail_nickname: Optional[str] = field( - default=None, + mail_nickname: str = dataclass_field( metadata={"wire_name": "mailNickname"}, ) """The mail alias for the user.""" - password_profile: Optional[Dict[str, Any]] = field( - default=None, + password_profile: Dict[str, Any] = dataclass_field( metadata={"wire_name": "passwordProfile"}, ) """passwordProfile""" - user_principal_name: Optional[str] = field( - default=None, + user_principal_name: str = dataclass_field( metadata={"wire_name": "userPrincipalName"}, ) """The user principal name (UPN) of the user.""" - given_name: Optional[str] = field( + given_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "givenName"}, ) """The user's given name (first name).""" - surname: Optional[str] = None + surname: Optional[str] = dataclass_field(default=None, kw_only=True) """The user's surname (family name or last name).""" - business_phones: Optional[List[str]] = field( + business_phones: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "businessPhones"}, ) - department: Optional[str] = None + department: Optional[str] = dataclass_field(default=None, kw_only=True) """The name for the department in which the user works.""" - job_title: Optional[str] = field( + job_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobTitle"}, ) """The user's job title.""" - mobile_phone: Optional[str] = field( + mobile_phone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mobilePhone"}, ) """ The mobile phone number for the user in any format such as '1 (234) 567-8910'. """ - office_location: Optional[str] = field( + office_location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "officeLocation"}, ) """The office location in the user's place of business.""" - preferred_language: Optional[str] = field( + preferred_language: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "preferredLanguage"}, ) """ @@ -547,10 +580,7 @@ class CheckMemberGroupsRequest: Definition: CheckMemberGroups_Request """ - group_ids: Optional[List[str]] = field( - default=None, - metadata={"wire_name": "groupIds"}, - ) + group_ids: List[str] = dataclass_field(metadata={"wire_name": "groupIds"}) # Client Class @@ -561,16 +591,16 @@ class AzureadClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -581,8 +611,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -590,8 +620,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -603,7 +633,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -625,7 +655,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -657,9 +687,9 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def create_office365_group_async( + def create_office365_group( self, - input: CreateOffice365GroupInput, + input: CreateOffice365GroupInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -670,10 +700,26 @@ async def create_office365_group_async( Create Office 365 group Create an Office 365 group in your Microsoft Entra ID tenant. + + Swagger operation ID: `CreateOffice365Group`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/groups/office365" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -687,6 +733,7 @@ async def create_office365_group_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -694,9 +741,9 @@ async def create_office365_group_async( return json.loads(response.text) - async def create_security_group_async( + def create_security_group( self, - input: CreateSecurityGroupInput, + input: CreateSecurityGroupInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -707,12 +754,28 @@ async def create_security_group_async( Create security group Create a security group in your Microsoft Entra ID tenant. + + Swagger operation ID: `CreateSecurityGroup`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1.0/groups/securityGroup" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -726,6 +789,7 @@ async def create_security_group_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -733,7 +797,7 @@ async def create_security_group_async( return json.loads(response.text) - async def get_group_async( + def get_group( self, id: str, *, @@ -746,13 +810,29 @@ async def get_group_async( Get group Get details for a group. + + Swagger operation ID: `GetGroup`. + + Args: + id: Unique identifier of a group (Ex. + '40639f36-46a6-73a6-91e2-9584b7913429'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/groups/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -766,6 +846,7 @@ async def get_group_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -773,7 +854,7 @@ async def get_group_async( return json.loads(response.text) - async def get_user_async( + def get_user( self, id: str, *, @@ -786,13 +867,29 @@ async def get_user_async( Get user Get details for a user. + + Swagger operation ID: `GetUser`. + + Args: + id: Unique identifier of a user (Ex. 'user@tennant.onmicrosoft.com' + or '5f6ce5c7-b521-4842-9bbe-3f6d5aa5e35b'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/users/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -806,6 +903,7 @@ async def get_user_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -813,9 +911,9 @@ async def get_user_async( return json.loads(response.text) - async def update_user_async( + def update_user( self, - input: UpdateUserRequest, + input: UpdateUserRequest | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -827,13 +925,31 @@ async def update_user_async( Update user Update the info for a user. + + Swagger operation ID: `UpdateUser`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique identifier of a user (Ex. 'user@tennant.onmicrosoft.com' + or '5f6ce5c7-b521-4842-9bbe-3f6d5aa5e35b'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/users/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -847,9 +963,10 @@ async def update_user_async( request_url, response.status, response.text, + response=response, ) - async def refresh_tokens_async( + def refresh_tokens( self, id: str, *, @@ -862,13 +979,29 @@ async def refresh_tokens_async( Refresh tokens Invalidate all refresh tokens for a user + + Swagger operation ID: `RefreshTokens`. + + Args: + id: Unique identifier of a user (Ex. 'user@tennant.onmicrosoft.com' + or '5f6ce5c7-b521-4842-9bbe-3f6d5aa5e35b'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/users/{quote(str(id), safe='')}/revokeSignInSessions" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -882,11 +1015,12 @@ async def refresh_tokens_async( request_url, response.status, response.text, + response=response, ) - async def create_user_async( + def create_user( self, - input: CreateUserRequest, + input: CreateUserRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -897,10 +1031,26 @@ async def create_user_async( Create user Create a new user in your Microsoft Entra ID tenant. + + Swagger operation ID: `CreateUser`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/users" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -914,6 +1064,7 @@ async def create_user_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -921,16 +1072,16 @@ async def create_user_async( return json.loads(response.text) - async def get_group_members_async( + def list_group_members( self, id: str, - top: Optional[int] = None, *, + top: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get group members @@ -939,8 +1090,27 @@ async def get_group_members_async( values, please turn on the Settings->Pagination feature and provide a Threshold limit. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetGroupMembers`. + + Args: + id: Unique identifier of a group (Ex. + '40639f36-46a6-73a6-91e2-9584b7913429'). + top: Limit on the number of results to return (from 1 to 999, + default is 100). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -954,11 +1124,18 @@ async def get_group_members_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -971,23 +1148,32 @@ async def get_group_members_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def remove_member_from_group_async( + def remove_member_from_group( self, group_id: str, member_id: str, @@ -1001,6 +1187,22 @@ async def remove_member_from_group_async( Remove Member From Group Remove Member From Group + + Swagger operation ID: `RemoveMemberFromGroup`. + + Args: + group_id: The Id of the group. + member_id: The Id of the member. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1012,7 +1214,7 @@ async def remove_member_from_group_async( f"/$ref" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1026,11 +1228,12 @@ async def remove_member_from_group_async( request_url, response.status, response.text, + response=response, ) - async def add_user_to_group_async( + def add_user_to_group( self, - input: GetGroupRequest, + input: GetGroupRequest | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -1042,13 +1245,31 @@ async def add_user_to_group_async( Add user to group Add a user to a group in this Microsoft Entra ID tenant. + + Swagger operation ID: `AddUserToGroup`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique identifier of a group (Ex. + '40639f36-46a6-73a6-91e2-9584b7913429'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/groups/{quote(str(id), safe='')}/members/$ref" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1062,11 +1283,12 @@ async def add_user_to_group_async( request_url, response.status, response.text, + response=response, ) - async def assign_manager_async( + def assign_manager( self, - input: AssignManagerRequest, + input: AssignManagerRequest | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -1078,13 +1300,31 @@ async def assign_manager_async( Assign manager Assign a manager for a user. + + Swagger operation ID: `AssignManager`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique identifier of a user (Ex. 'user@tennant.onmicrosoft.com' + or '5f6ce5c7-b521-4842-9bbe-3f6d5aa5e35b'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/users/{quote(str(id), safe='')}/manager/$ref" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1098,11 +1338,12 @@ async def assign_manager_async( request_url, response.status, response.text, + response=response, ) - async def create_group_async( + def create_group( self, - input: CreateGroupInput, + input: CreateGroupInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1113,10 +1354,26 @@ async def create_group_async( Create group Create a group in your Microsoft Entra ID tenant. + + Swagger operation ID: `CreateGroup`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/groups" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1130,6 +1387,7 @@ async def create_group_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1137,9 +1395,9 @@ async def create_group_async( return json.loads(response.text) - async def check_member_groups_async( + def check_member_groups( self, - input: CheckMemberGroupsRequest, + input: CheckMemberGroupsRequest | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -1152,13 +1410,31 @@ async def check_member_groups_async( If the user is a member of the given group, the result will contain the given id. Otherwise the result will be empty. + + Swagger operation ID: `CheckMemberGroupsV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique identifier of a user (Ex. 'user@tennant.onmicrosoft.com' + or '5f6ce5c7-b521-4842-9bbe-3f6d5aa5e35b'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v2/v1.0/users/{quote(str(id), safe='')}/checkMemberGroups" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1172,6 +1448,7 @@ async def check_member_groups_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1179,43 +1456,86 @@ async def check_member_groups_async( return json.loads(response.text) - async def get_member_groups_async( + def list_member_groups( self, - input: GetMemberGroupsRequest, + input: GetMemberGroupsRequest | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[str]: """ Get groups of a user Get the groups a user is a member of. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMemberGroupsV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique identifier of a user (Ex. 'user@tennant.onmicrosoft.com' + or '5f6ce5c7-b521-4842-9bbe-3f6d5aa5e35b'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[str]: An Azure Core pager over connector results. Consume + it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v2/v1.0/users/{quote(str(id), safe='')}/getMemberGroups" ) + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[str]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/azureautomation.py b/src/azure/connectors/azureautomation.py index 85a5844..37981d9 100644 --- a/src/azure/connectors/azureautomation.py +++ b/src/azure/connectors/azureautomation.py @@ -5,21 +5,34 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "AzureautomationClient", + "AutomationAccountResponse", + "CreateJobInput", + "CreateJobResponse", + "ResourceGroup", + "ResourceGroupListResult", + "RunbookListResults", + "Subscription", + "SubscriptionListResult", +] + # Type Definitions @@ -29,9 +42,9 @@ class CreateJobResponse: Response for Get status of job """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Resource ID of the Job""" - properties: Optional[Dict[str, Any]] = None + properties: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """properties""" @@ -41,7 +54,7 @@ class CreateJobInput: Create job """ - properties: Optional[Dict[str, Any]] = None + properties: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -50,10 +63,16 @@ class SubscriptionListResult: Response for List subscriptions """ - value: Optional[List[Subscription]] = None + value: Optional[ + List[Subscription | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The subscriptions.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -65,10 +84,16 @@ class ResourceGroupListResult: Response for List resource groups """ - value: Optional[List[ResourceGroup]] = None + value: Optional[ + List[ResourceGroup | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of resource groups.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -80,7 +105,7 @@ class AutomationAccountResponse: Response for List Automation accounts """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" @@ -90,7 +115,7 @@ class RunbookListResults: Response for List runbooks """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -99,30 +124,34 @@ class Subscription: Definition: Subscription """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ The fully qualified Id. For example, /subscriptions/00000000-0000-0000-0000-000000000000. """ - subscription_id: Optional[str] = field( + subscription_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "subscriptionId"}, ) """The subscription Id.""" - tenant_id: Optional[str] = field( + tenant_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tenantId"}, ) """The tenant Id.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The subscription display name.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """The subscription state.""" - authorization_source: Optional[str] = field( + authorization_source: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "authorizationSource"}, ) """ @@ -138,14 +167,15 @@ class ResourceGroup: Definition: ResourceGroup """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ The ID of the resource group (e.g. /subscriptions/XXX/resourceGroups/YYY). """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The Name of the resource group.""" - managed_by: Optional[str] = field( + managed_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managedBy"}, ) """Id of the resource that manages this resource group.""" @@ -159,16 +189,16 @@ class AzureautomationClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -179,8 +209,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -188,8 +218,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -201,7 +231,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -223,7 +253,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -255,7 +285,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def get_job_output_async( + def get_job_output( self, subscription_id: str, resource_group_name: str, @@ -271,6 +301,26 @@ async def get_job_output_async( Get job output Get outputs of an Azure Automation job. + + Swagger operation ID: `GetJobOutput`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: The name of the Azure Resource Group. + automation_account: The name of the Azure Automation Account. + job_id: GUID for the ID of the run. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -291,7 +341,7 @@ async def get_job_output_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -305,11 +355,12 @@ async def get_job_output_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_status_of_job_async( + def get_status_of_job( self, subscription_id: str, resource_group_name: str, @@ -325,6 +376,26 @@ async def get_status_of_job_async( Get status of job Get Status of a Job + + Swagger operation ID: `GetStatusOfJob`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: The name of the Azure Resource Group. + automation_account: The name of the Azure Automation Account. + job_id: GUID for the ID of the run. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -344,7 +415,7 @@ async def get_status_of_job_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -358,6 +429,7 @@ async def get_status_of_job_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -365,15 +437,15 @@ async def get_status_of_job_async( return json.loads(response.text) - async def create_job_async( + def create_job( self, - input: CreateJobInput, + input: CreateJobInput | Mapping[str, Any], subscription_id: str, resource_group_name: str, automation_account: str, + *, runbook_name: Optional[str] = None, wait: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -383,6 +455,29 @@ async def create_job_async( Create job Create Job to run on hybrid worker + + Swagger operation ID: `CreateJob`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: The name of the Azure Resource Group. + automation_account: The name of the Azure Automation Account. + runbook_name: Name of the runbook to run. + wait: Wait for the job to finish before completing the action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -411,7 +506,7 @@ async def create_job_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -425,6 +520,7 @@ async def create_job_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -432,32 +528,54 @@ async def create_job_async( return json.loads(response.text) - async def subscriptions_list_async( + def list_subscriptions( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List subscriptions Gets a list of all the subscriptions to which the principal has access. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Subscriptions_List`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/subscriptions" query_params = [] query_params.append("x-ms-api-version=" + quote("2015-11-01", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -470,23 +588,32 @@ async def subscriptions_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def resource_groups_list_async( + return ItemPaged(get_next, extract_data) + + def list_resource_groups( self, subscription_id: str, *, @@ -494,15 +621,33 @@ async def resource_groups_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List resource groups Lists all the resource groups within the subscription. Paginates at 1,000 records. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ResourceGroups_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -514,11 +659,18 @@ async def resource_groups_list_async( query_params.append("x-ms-api-version=" + quote("2015-10-31", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -531,23 +683,32 @@ async def resource_groups_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def automation_accounts_list_async( + return ItemPaged(get_next, extract_data) + + def list_automation_accounts( self, subscription_id: str, resource_group_name: str, @@ -556,11 +717,33 @@ async def automation_accounts_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List Automation accounts Lists Azure Automation accounts in a resource group. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `AutomationAccounts_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: The name of the Azure Resource Group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -576,29 +759,50 @@ async def automation_accounts_list_async( query_params.append("x-ms-api-version=" + quote("2015-10-31", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def runbooks_list_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_runbooks( self, subscription_id: str, resource_group_name: str, @@ -608,11 +812,34 @@ async def runbooks_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List runbooks Lists Azure Automation runbooks in an automation account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Runbooks_List`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: The name of the Azure Resource Group. + automation_account: The name of the Azure Automation Account. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -630,29 +857,50 @@ async def runbooks_list_async( query_params.append("x-ms-api-version=" + quote("2015-10-31", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - async def get_runbook_async( + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_runbook( self, subscription_id: str, resource_group_name: str, @@ -663,11 +911,35 @@ async def get_runbook_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get runbook Get information on an Azure Automation runbook. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetRunbook`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: The name of the Azure Resource Group. + automation_account: The name of the Azure Automation Account. + runbook_name: The name of the Azure Automation runbook. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -686,24 +958,45 @@ async def get_runbook_async( query_params.append("x-ms-api-version=" + quote("2015-10-31", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/azureblob.py b/src/azure/connectors/azureblob.py index 24aaf84..b99010f 100644 --- a/src/azure/connectors/azureblob.py +++ b/src/azure/connectors/azureblob.py @@ -5,21 +5,41 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "AzureblobClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "BlobMetadataPage", + "BlobMetadataResponse", + "DataSetsMetadata", + "DataWithSensitivityLabelInfo", + "ListOfBlobsWithSensitivityLabels", + "ObjectEntity", + "SensitivityLabelMetadata", + "SharedAccessSignature", + "SharedAccessSignatureBlobPolicy", + "StorageAccount", + "StorageAccountList", + "TabularDataSetsMetadata", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,41 +49,66 @@ class BlobMetadata: Response for Copy blob """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The filelocator of the file or folder.""" @@ -75,8 +120,9 @@ class SharedAccessSignature: Response for Create SAS URI by path """ - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebUrl"}, ) """A URL to an object with access token.""" @@ -88,8 +134,9 @@ class SharedAccessSignatureBlobPolicy: Response for Get available access policies """ - group_policy_identifier: Optional[str] = field( + group_policy_identifier: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GroupPolicyIdentifier"}, ) """ @@ -97,37 +144,42 @@ class SharedAccessSignatureBlobPolicy: (e.g. Start time and End time) have precedence over input parameters mentioned in actions. """ - permissions: Optional[str] = field( + permissions: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Permissions"}, ) """The permissions specified on the SAS (Values separated by comma).""" - start_time: Optional[str] = field( + start_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartTime"}, ) """ The date and time at which the SAS becomes valid (example: '2017-11-01T15:30:00+00:00'). Default = now(). """ - expiry_time: Optional[str] = field( + expiry_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpiryTime"}, ) """ The date and time after which the SAS is no longer valid (example: '2017-12-01T15:30:00+00:00'). Default = now() + 24h. """ - access_protocol: Optional[str] = field( + access_protocol: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccessProtocol"}, ) """ The allowed protocols (https only, or http and https). Null if you don't want to restrict protocol. """ - ip_address_or_range: Optional[str] = field( + ip_address_or_range: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IpAddressOrRange"}, ) """ @@ -142,46 +194,74 @@ class DataWithSensitivityLabelInfo: Response for Get Blob Metadata """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The filelocator of the file or folder.""" - sensitivity_label_info: Optional[List[SensitivityLabelMetadata]] = field( + sensitivity_label_info: Optional[ + List[SensitivityLabelMetadata | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SensitivityLabelInfo"}, ) """Sensitivity label metadata info list""" @@ -193,10 +273,16 @@ class ListOfBlobsWithSensitivityLabels: Response for Lists blobs """ - value: Optional[List[DataWithSensitivityLabelInfo]] = None + value: Optional[ + List[DataWithSensitivityLabelInfo | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Blobs""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to retrieve the next page.""" @@ -208,15 +294,22 @@ class BlobMetadataPage: Response for Lists blobs in the root folder """ - value: Optional[List[BlobMetadata]] = None + value: Optional[ + List[BlobMetadata | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Blob metadata collection.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """An Url which can be used to retrieve the next page.""" - next_page_marker: Optional[str] = field( + next_page_marker: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextPageMarker"}, ) """A marker which can be used to retrieve the next page.""" @@ -228,7 +321,12 @@ class StorageAccountList: Response for Get storage accounts """ - value: Optional[List[StorageAccount]] = None + value: Optional[ + List[StorageAccount | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of storage account names""" @@ -238,7 +336,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -251,41 +349,66 @@ class BlobMetadataResponse: Definition: BlobMetadataResponse """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The filelocator of the file or folder.""" @@ -297,41 +420,47 @@ class SensitivityLabelMetadata: Definition: SensitivityLabelMetadata """ - sensitivity_label_id: Optional[str] = field( + sensitivity_label_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelId"}, ) """SensitivityLabel Id.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel name.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """SensitivityLabel displayName info""" - tooltip: Optional[str] = None + tooltip: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel details on tooltip.""" - priority: Optional[int] = None + priority: Optional[int] = dataclass_field(default=None, kw_only=True) """SensitivityLabel priority.""" - color: Optional[str] = None + color: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel color.""" - is_encrypted: Optional[bool] = field( + is_encrypted: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEncrypted"}, ) """ is SensitivityLabel Encrypted.""" - is_enabled: Optional[bool] = field( + is_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEnabled"}, ) """Whether SensitivityLabel is Enabled.""" - is_parent: Optional[bool] = field( + is_parent: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isParent"}, ) """Whether SensitivityLabel is Parent.""" - parent_sensitivity_label_id: Optional[str] = field( + parent_sensitivity_label_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentSensitivityLabelId"}, ) """Parent SensitivityLabel Id.""" @@ -343,10 +472,15 @@ class StorageAccount: Definition: StorageAccount """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the storage account.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the storage account.""" @@ -358,8 +492,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -368,25 +512,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -398,15 +546,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -420,16 +570,16 @@ class AzureblobClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -440,8 +590,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -449,8 +599,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -462,7 +612,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -484,7 +634,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -516,13 +666,13 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def copy_file_async( + def copy_file( self, dataset: str, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -538,6 +688,26 @@ async def copy_file_async( action. If source and destination are present in same storage account, please use relative path. Otherwise, maximum size of a source for copy blob operation is 50 MB. + + Swagger operation ID: `CopyFile_V2`. + + Args: + dataset: Azure Storage account name or blob endpoint. + source: Specify the url to source blob. + destination: Specify the destination blob path, including the + target blob name. + overwrite: Should the destination blob be overwritten + (true/false)?. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -564,7 +734,7 @@ async def copy_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -578,6 +748,7 @@ async def copy_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -585,7 +756,7 @@ async def copy_file_async( return json.loads(response.text) - async def create_block_blob_async( + def create_block_blob( self, input: bytes, storage_account_name: str, @@ -601,6 +772,24 @@ async def create_block_blob_async( Create block blob This operation uploads a block blob to Azure Blob Storage. + + Swagger operation ID: `CreateBlockBlob_V2`. + + Args: + input: The binary request body. + storage_account_name: The storage account name. + folder_path: Specify folder path to upload. + name: Specify name of the blob to create. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -622,7 +811,7 @@ async def create_block_blob_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -639,9 +828,10 @@ async def create_block_blob_async( request_url, response.status, response.text, + response=response, ) - async def create_file_async( + def create_file( self, input: bytes, dataset: str, @@ -657,6 +847,24 @@ async def create_file_async( Create blob This operation uploads a blob to Azure Blob Storage. + + Swagger operation ID: `CreateFile_V2`. + + Args: + input: The binary request body. + dataset: Azure Storage account name or blob endpoint. + folder_path: Specify folder path to upload. + name: Specify name of the blob to create. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -678,7 +886,7 @@ async def create_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -695,6 +903,7 @@ async def create_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -702,9 +911,9 @@ async def create_file_async( return json.loads(response.text) - async def create_share_link_by_path_async( + def create_share_link_by_path( self, - input: SharedAccessSignatureBlobPolicy, + input: SharedAccessSignatureBlobPolicy | Mapping[str, Any], storage_account_name: str, path: str, *, @@ -717,6 +926,24 @@ async def create_share_link_by_path_async( Create SAS URI by path This operation creates a SAS link for a blob using the path. + + Swagger operation ID: `CreateShareLinkByPath_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + storage_account_name: Azure Storage account name or blob endpoint. + path: The unique path of the blob. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -733,7 +960,7 @@ async def create_share_link_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -747,6 +974,7 @@ async def create_share_link_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -754,7 +982,7 @@ async def create_share_link_by_path_async( return json.loads(response.text) - async def delete_file_async( + def delete_file( self, dataset: str, id: str, @@ -768,6 +996,22 @@ async def delete_file_async( Delete blob This operation deletes a blob. + + Swagger operation ID: `DeleteFile_V2`. + + Args: + dataset: Azure Storage account name or blob endpoint. + id: Specify the blob to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -778,7 +1022,7 @@ async def delete_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -792,15 +1036,16 @@ async def delete_file_async( request_url, response.status, response.text, + response=response, ) - async def extract_folder_async( + def extract_folder( self, dataset: str, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -810,6 +1055,25 @@ async def extract_folder_async( Extract archive to folder This operation extracts an archive blob into a folder (example: .zip). + + Swagger operation ID: `ExtractFolder_V3`. + + Args: + dataset: Azure Storage account name or blob endpoint. + source: Specify the path to the archive blob. + destination: Specify the path in Azure Blob Storage to extract the + archive contents. + overwrite: Should destination blob be overwritten (true/false)?. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -836,7 +1100,7 @@ async def extract_folder_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -850,6 +1114,7 @@ async def extract_folder_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -857,7 +1122,7 @@ async def extract_folder_async( return json.loads(response.text) - async def get_access_policies_async( + def list_access_policies( self, storage_account_name: str, path: str, @@ -866,11 +1131,31 @@ async def get_access_policies_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get available access policies This operation gets available shared access policies for a blob. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAccessPolicies_V2`. + + Args: + storage_account_name: Azure Storage account name or blob endpoint. + path: The unique path of the blob. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -886,36 +1171,57 @@ async def get_access_policies_async( query_params.append(f"path={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def get_file_content_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_file_content( self, dataset: str, id: str, + *, infer_content_type: Optional[bool] = None, extract_sensitivity_label: Optional[bool] = None, purview_account_name: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -925,6 +1231,26 @@ async def get_file_content_async( Get blob content This operation retrieves blob contents using id. + + Swagger operation ID: `GetFileContent_V2`. + + Args: + dataset: Azure Storage account name or blob endpoint. + id: Specify the blob. + infer_content_type: Infer content-type based on extension. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -954,7 +1280,7 @@ async def get_file_content_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -968,18 +1294,19 @@ async def get_file_content_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_file_content_by_path_async( + def get_file_content_by_path( self, dataset: str, path: str, + *, infer_content_type: Optional[bool] = None, extract_sensitivity_label: Optional[bool] = None, purview_account_name: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -989,6 +1316,26 @@ async def get_file_content_by_path_async( Get blob content using path This operation retrieves blob contents using path. + + Swagger operation ID: `GetFileContentByPath_V2`. + + Args: + dataset: Azure Storage account name or blob endpoint. + path: Specify unique path to the blob. + infer_content_type: Infer content-type based on extension. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1021,7 +1368,7 @@ async def get_file_content_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1035,17 +1382,18 @@ async def get_file_content_by_path_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_file_metadata_async( + def get_file_metadata( self, dataset: str, id: str, + *, extract_sensitivity_label: Optional[bool] = None, purview_account_name: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1055,6 +1403,25 @@ async def get_file_metadata_async( Get Blob Metadata This operation retrieves blob metadata using blob id. + + Swagger operation ID: `GetFileMetadata_V2`. + + Args: + dataset: Azure Storage account name or blob endpoint. + id: Specify the blob. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1078,7 +1445,7 @@ async def get_file_metadata_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1092,6 +1459,7 @@ async def get_file_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1099,13 +1467,13 @@ async def get_file_metadata_async( return json.loads(response.text) - async def get_file_metadata_by_path_async( + def get_file_metadata_by_path( self, dataset: str, path: str, + *, extract_sensitivity_label: Optional[bool] = None, purview_account_name: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1115,6 +1483,25 @@ async def get_file_metadata_by_path_async( Get Blob Metadata using path This operation retrieves blob metadata using path. + + Swagger operation ID: `GetFileMetadataByPath_V2`. + + Args: + dataset: Azure Storage account name or blob endpoint. + path: Specify unique path to the blob. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1142,7 +1529,7 @@ async def get_file_metadata_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1156,6 +1543,7 @@ async def get_file_metadata_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1163,27 +1551,47 @@ async def get_file_metadata_by_path_async( return json.loads(response.text) - async def list_folder_async( + def list_folder( self, dataset: str, id: str, - next_page_marker: Optional[str] = None, + *, use_flat_listing: Optional[bool] = None, extract_sensitivity_label: Optional[bool] = None, purview_account_name: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Lists blobs This operation lists blobs in a container. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListFolder_V4`. + + Args: + dataset: Azure Storage account name or blob endpoint. + id: Specify the folder. + use_flat_listing: Whether or not to list blobs in flat listing\". + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1194,11 +1602,6 @@ async def list_folder_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) query_params = [] - if next_page_marker is not None: - value = str(next_page_marker) - if isinstance(next_page_marker, bool): - value = value.lower() - query_params.append(f"nextPageMarker={quote(value, safe='')}") if use_flat_listing is not None: value = str(use_flat_listing) if isinstance(use_flat_listing, bool): @@ -1216,11 +1619,18 @@ async def list_folder_async( query_params.append(f"purviewAccountName={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1233,39 +1643,63 @@ async def list_folder_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def list_root_folder_async( + return ItemPaged(get_next, extract_data) + + def list_root_folder( self, dataset: str, - next_page_marker: Optional[str] = None, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Lists blobs in the root folder This operation lists blobs in the Azure Blob Storage root folder. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListRootFolder_V4`. + + Args: + dataset: Azure Storage account name or blob endpoint. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1276,18 +1710,20 @@ async def list_root_folder_async( ) query_params = [] query_params.append("useFlatListing=" + quote("false", safe='')) - if next_page_marker is not None: - value = str(next_page_marker) - if isinstance(next_page_marker, bool): - value = value.lower() - query_params.append(f"nextPageMarker={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1300,23 +1736,32 @@ async def list_root_folder_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def set_blob_tier_by_path_async( + return ItemPaged(get_next, extract_data) + + def set_blob_tier_by_path( self, storage_account_name: str, path: str, @@ -1332,6 +1777,23 @@ async def set_blob_tier_by_path_async( This operation sets a tier for a block blob on a standard storage account using the path. + + Swagger operation ID: `SetBlobTierByPath_V2`. + + Args: + storage_account_name: Azure Storage account name or blob endpoint. + path: The unique path of the blob. + new_tier: The new tier for the blob. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1352,7 +1814,7 @@ async def set_blob_tier_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1366,9 +1828,10 @@ async def set_blob_tier_by_path_async( request_url, response.status, response.text, + response=response, ) - async def update_file_async( + def update_file( self, input: bytes, dataset: str, @@ -1383,6 +1846,23 @@ async def update_file_async( Update blob This operation updates a blob in Azure Blob Storage. + + Swagger operation ID: `UpdateFile_V2`. + + Args: + input: The binary request body. + dataset: Azure Storage account name or blob endpoint. + id: Specify the blob to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1393,7 +1873,7 @@ async def update_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, @@ -1410,6 +1890,7 @@ async def update_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1417,41 +1898,80 @@ async def update_file_async( return json.loads(response.text) - async def get_data_sets_async( + def list_data_sets( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get storage accounts This operation list the user's Azure Storage Account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetDataSets`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/codeless/GetDataSets" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/azuredatafactory.py b/src/azure/connectors/azuredatafactory.py index 593f7b6..456b1cf 100644 --- a/src/azure/connectors/azuredatafactory.py +++ b/src/azure/connectors/azuredatafactory.py @@ -5,21 +5,41 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "AzuredatafactoryClient", + "Activity", + "ActivityFull", + "CreatePipelineRunResponse", + "DataFactory", + "DataFactoryListResult", + "ParameterValueSpecification", + "Pipeline", + "PipelineListResult", + "PipelineRun", + "ResourceGroup", + "ResourceGroupListResult", + "ResourceGroupProperties", + "Subscription", + "SubscriptionListResult", + "SubscriptionPolicies", +] + # Type Definitions @@ -29,8 +49,9 @@ class CreatePipelineRunResponse: Response for Create a pipeline run """ - run_id: Optional[str] = field( + run_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "runId"}, ) """runId""" @@ -42,53 +63,60 @@ class PipelineRun: Response for Get a pipeline run """ - run_id: Optional[str] = field( + run_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "runId"}, ) """Identifier of a run""" - pipeline_name: Optional[str] = field( + pipeline_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pipelineName"}, ) """The pipeline name""" - parameters: Optional[Dict[str, Any]] = None + parameters: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """ The full of partial list of parameter name, value pair used in the pipeline run. """ - invoked_by: Optional[Dict[str, Any]] = field( + invoked_by: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "invokedBy"}, ) """Entity that started the pipeline.""" - run_start: Optional[str] = field( + run_start: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "runStart"}, ) """The start time of a pipeline run in ISO8601 format.""" - run_end: Optional[str] = field( + run_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "runEnd"}, ) """The end time of a pipeline run in ISO8601 format.""" - duration_in_ms: Optional[int] = field( + duration_in_ms: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "durationInMs"}, ) """The duration of a pipeline run in milliseconds.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status of the pipeline run.""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """The message from a pipeline run.""" - last_updated: Optional[str] = field( + last_updated: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastUpdated"}, ) """ The last updated timestamp for the pipeline run event in ISO8601 format. """ - annotations: Optional[List[str]] = None + annotations: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """The annotations for the pipeline run.""" @@ -98,10 +126,16 @@ class SubscriptionListResult: Response for List subscriptions """ - value: Optional[List[Subscription]] = None + value: Optional[ + List[Subscription | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The subscriptions.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -113,10 +147,16 @@ class ResourceGroupListResult: Response for List resource groups """ - value: Optional[List[ResourceGroup]] = None + value: Optional[ + List[ResourceGroup | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of resource groups.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -128,10 +168,16 @@ class DataFactoryListResult: Response for List Factories """ - value: Optional[List[DataFactory]] = None + value: Optional[ + List[DataFactory | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of Data Factories.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -143,10 +189,16 @@ class PipelineListResult: Response for List pipelines """ - value: Optional[List[Pipeline]] = None + value: Optional[ + List[Pipeline | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of Data Factories.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -158,19 +210,23 @@ class DataFactory: Definition: DataFactory """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The resource name.""" - tags: Optional[Dict[str, Any]] = None + tags: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The resource tags.""" - properties: Optional[Dict[str, Any]] = None + properties: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Data Factory additional properties.""" - identity: Optional[Dict[str, Any]] = None + identity: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Managed service identity of the factory.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The resource identitfier.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The resource type.""" - location: Optional[str] = None + location: Optional[str] = dataclass_field(default=None, kw_only=True) """The resource location""" @@ -180,13 +236,13 @@ class Pipeline: Definition: Pipeline """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The resource identifier.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The resource name of the pipeline.""" - properties: Optional[Dict[str, Any]] = None + properties: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The pipeline properties.""" - etag: Optional[str] = None + etag: Optional[str] = dataclass_field(default=None, kw_only=True) """Etag identifies change in the resource.""" @@ -196,7 +252,7 @@ class Activity: Definition: Activity """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -209,20 +265,25 @@ class ActivityFull: Definition: Activity-Full """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """type""" - inputs: Optional[List[Dict[str, Any]]] = None + inputs: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """inputs""" - outputs: Optional[List[Dict[str, Any]]] = None + outputs: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """outputs""" - type_properties: Optional[Dict[str, Any]] = field( + type_properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "typeProperties"}, ) """typeProperties""" - policy: Optional[Dict[str, Any]] = None + policy: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """policy""" @@ -232,7 +293,7 @@ class ParameterValueSpecification: Definition: ParameterValueSpecification """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -245,34 +306,39 @@ class Subscription: Definition: Subscription """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ The fully qualified Id. For example, /subscriptions/00000000-0000-0000-0000-000000000000. """ - subscription_id: Optional[str] = field( + subscription_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "subscriptionId"}, ) """The subscription Id.""" - tenant_id: Optional[str] = field( + tenant_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tenantId"}, ) """The tenant Id.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The subscription display name.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """The subscription state.""" - subscription_policies: Optional[SubscriptionPolicies] = field( + subscription_policies: Optional[SubscriptionPolicies | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "subscriptionPolicies"}, ) - authorization_source: Optional[str] = field( + authorization_source: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "authorizationSource"}, ) """ @@ -288,8 +354,9 @@ class SubscriptionPolicies: Definition: SubscriptionPolicies """ - location_placement_id: Optional[str] = field( + location_placement_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "locationPlacementId"}, ) """ @@ -297,13 +364,15 @@ class SubscriptionPolicies: visible for a subscription. For example, a subscription with a location placement Id of Public_2014-09-01 has access to Azure public regions. """ - quota_id: Optional[str] = field( + quota_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "quotaId"}, ) """The subscription quota Id.""" - spending_limit: Optional[str] = field( + spending_limit: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "spendingLimit"}, ) """The subscription spending limit.""" @@ -315,26 +384,32 @@ class ResourceGroup: Definition: ResourceGroup """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ The ID of the resource group (e.g. /subscriptions/XXX/resourceGroups/YYY). """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The Name of the resource group.""" - location: Optional[str] = None + location: str """ The location of the resource group. It cannot be changed after the resource group has been created. Has to be one of the supported Azure Locations, such as West US, East US, West Europe, East Asia, etc. """ - managed_by: Optional[str] = field( + managed_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managedBy"}, ) """Id of the resource that manages this resource group.""" - tags: Optional[Dict[str, str]] = None + tags: Optional[Dict[str, str]] = dataclass_field(default=None, kw_only=True) """The tags attached to the resource group.""" - properties: Optional[ResourceGroupProperties] = None + properties: Optional[ + ResourceGroupProperties | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -343,8 +418,9 @@ class ResourceGroupProperties: Definition: ResourceGroupProperties """ - provisioning_state: Optional[str] = field( + provisioning_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "provisioningState"}, ) """The provisioning state.""" @@ -358,16 +434,16 @@ class AzuredatafactoryClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -378,8 +454,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -387,8 +463,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -400,7 +476,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -422,7 +498,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -454,15 +530,15 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def create_pipeline_run_async( + def create_pipeline_run( self, - input: ParameterValueSpecification, + input: ParameterValueSpecification | Mapping[str, Any], subscription_id: str, resource_group_name: str, data_factory_name: str, pipeline_name: str, - reference_pipeline_run_id: Optional[str] = None, *, + reference_pipeline_run_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -472,6 +548,31 @@ async def create_pipeline_run_async( Create a pipeline run This operation creates a new pipeline run in your factory + + Swagger operation ID: `CreatePipelineRun`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + data_factory_name: The name of the Data Factory. + pipeline_name: The name of the Data Factory pipeline. + reference_pipeline_run_id: The pipeline run identifier. If run ID + is specified the parameters of the specified run will be used + to create a new run. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -497,7 +598,7 @@ async def create_pipeline_run_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -511,6 +612,7 @@ async def create_pipeline_run_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -518,7 +620,7 @@ async def create_pipeline_run_async( return json.loads(response.text) - async def cancel_pipeline_run_async( + def cancel_pipeline_run( self, subscription_id: str, resource_group_name: str, @@ -534,6 +636,26 @@ async def cancel_pipeline_run_async( Cancel a pipeline run This operation cancels a pipeline run by its run ID. + + Swagger operation ID: `CancelPipelineRun`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + data_factory_name: The name of the Data Factory. + pipeline_run_name: The id of the Data Factory pipeline run. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -553,7 +675,7 @@ async def cancel_pipeline_run_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -567,9 +689,10 @@ async def cancel_pipeline_run_async( request_url, response.status, response.text, + response=response, ) - async def get_pipeline_run_async( + def get_pipeline_run( self, subscription_id: str, resource_group_name: str, @@ -585,6 +708,26 @@ async def get_pipeline_run_async( Get a pipeline run Get a particular pipeline run execution + + Swagger operation ID: `GetPipelineRun`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + data_factory_name: The name of the Data Factory. + pipeline_run_name: The id of the Data Factory pipeline run. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -604,7 +747,7 @@ async def get_pipeline_run_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -618,6 +761,7 @@ async def get_pipeline_run_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -625,32 +769,54 @@ async def get_pipeline_run_async( return json.loads(response.text) - async def list_subscriptions_async( + def list_subscriptions( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List subscriptions Gets a list of all the subscriptions to which the principal has access. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListSubscriptions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/subscriptions" query_params = [] query_params.append("x-ms-api-version=" + quote("2017-09-01-preview", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -663,41 +829,70 @@ async def list_subscriptions_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def list_resource_groups_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def list_resource_groups( self, subscription_id: str, + *, filter: Optional[str] = None, top: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List resource groups Lists all the resource groups within the subscription. The results are paginated at 1,000+ records. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListResourceGroups`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + filter: The filter to apply on the operation. + top: Query parameters. If nothing is passed returns all values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -719,11 +914,18 @@ async def list_resource_groups_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -736,23 +938,32 @@ async def list_resource_groups_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def list_data_factories_async( + def list_data_factories( self, subscription_id: str, resource_group_name: str, @@ -761,14 +972,33 @@ async def list_data_factories_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List Factories Get the list of Data Factories - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListDataFactories`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -784,11 +1014,18 @@ async def list_data_factories_async( query_params.append("x-ms-api-version=" + quote("2017-09-01-preview", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -801,23 +1038,32 @@ async def list_data_factories_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def list_pipelines_async( + def list_pipelines( self, subscription_id: str, resource_group_name: str, @@ -827,14 +1073,34 @@ async def list_pipelines_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List pipelines List the list of pipelines from a particular factory - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListPipelines`. + + Args: + subscription_id: The unique identifier for the Microsoft Azure + subscription. The subscription ID forms part of the ID for + every Azure resource. + resource_group_name: Resource group name. + data_factory_name: The name of the Data Factory. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -852,11 +1118,18 @@ async def list_pipelines_async( query_params.append("x-ms-api-version=" + quote("2017-09-01-preview", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -869,18 +1142,27 @@ async def list_pipelines_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/azuredigitaltwins.py b/src/azure/connectors/azuredigitaltwins.py index fe54ea0..1c2311e 100644 --- a/src/azure/connectors/azuredigitaltwins.py +++ b/src/azure/connectors/azuredigitaltwins.py @@ -5,21 +5,45 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "AzuredigitaltwinsClient", + "AddModelsInput", + "AddRelationshipInput", + "AddTwinInput", + "GetComponentResult", + "GetModelByIdResponse", + "IncomingRelationship", + "ListIncomingRelationshipsResponse", + "ListModelsResponse", + "ListRelationshipsResponse", + "QueryResult", + "QueryTwinsInput", + "SendComponentTelemetryInput", + "SendTelemetryInput", + "TwinRelationship", + "TwinResult", + "UpdateComponentInput", + "UpdateModelInput", + "UpdateRelationshipInput", + "UpdateTwinInput", +] + # Type Definitions @@ -32,15 +56,17 @@ class ListModelsResponse: Response for List Models """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Array values.""" - continuation_token: Optional[str] = field( + continuation_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "continuationToken"}, ) """Continuation Token the next page of Twin Relationship.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of Models.""" @@ -52,19 +78,20 @@ class GetModelByIdResponse: Response for Get Model By Id """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The id of the model as specified in the model definition.""" - upload_time: Optional[str] = field( + upload_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "uploadTime"}, ) """The time the model was uploaded to the service.""" - decommissioned: Optional[bool] = None + decommissioned: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Indicates if the model is decommissioned. Decommissioned models cannot be referenced by newly created digital twins. """ - model: Optional[Dict[str, Any]] = None + model: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Model reference.""" @@ -74,7 +101,7 @@ class UpdateModelInput: Update Model's Property """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Request for the API.""" @@ -84,7 +111,7 @@ class TwinResult: Response for Get Twin by Id """ - result: Optional[str] = None + result: Optional[str] = dataclass_field(default=None, kw_only=True) """Results From the Twin.""" @@ -94,7 +121,7 @@ class AddTwinInput: Add Twin """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Request for the API.""" @@ -104,7 +131,7 @@ class UpdateTwinInput: Update Twin """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Request for the API.""" @@ -114,7 +141,7 @@ class GetComponentResult: Response for Get Component """ - result: Optional[str] = None + result: Optional[str] = dataclass_field(default=None, kw_only=True) """Results From the Twin.""" @@ -124,7 +151,7 @@ class UpdateComponentInput: Update Component """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Request for the API.""" @@ -134,30 +161,39 @@ class TwinRelationship: Response for Get Relationship by Id """ - source_id: Optional[str] = field( + source_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "$sourceId"}, ) """Source Id.""" - relationship_id: Optional[str] = field( + relationship_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "$relationshipId"}, ) """Relationship Id.""" - target_id: Optional[str] = field( + target_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "$targetId"}, ) """Target Id.""" - relationship_name: Optional[str] = field( + relationship_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "$relationshipName"}, ) """Relationship Name.""" - etag: Optional[str] = field(default=None, metadata={"wire_name": "$etag"}) + etag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "$etag"}, + ) """E Tag Link.""" - additional_properties: Optional[str] = field( + additional_properties: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "additionalProperties"}, ) """Property Values.""" @@ -169,7 +205,7 @@ class AddRelationshipInput: Add Relationship """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Request for the API.""" @@ -179,7 +215,7 @@ class UpdateRelationshipInput: Update Relationship """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Request for the API.""" @@ -189,15 +225,17 @@ class ListIncomingRelationshipsResponse: Response for List Incoming Relationships """ - value: Optional[List[IncomingRelationship]] = None + value: List[IncomingRelationship | Mapping[str, Any]] """The collection of Incoming relationships.""" - continuation_token: Optional[str] = field( + continuation_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "continuationToken"}, ) """Continuation Token the next page of Twin Relationship.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of Incoming Relationship.""" @@ -209,7 +247,7 @@ class SendTelemetryInput: Send Telemetry """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Send Telemetry Inputs.""" @@ -219,7 +257,7 @@ class SendComponentTelemetryInput: Send Component Telemetry """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Send Component Telemetry Inputs.""" @@ -229,15 +267,17 @@ class ListRelationshipsResponse: Response for List Relationships """ - value: Optional[List[TwinRelationship]] = None + value: List[TwinRelationship | Mapping[str, Any]] """The collection of twin relationships.""" - continuation_token: Optional[str] = field( + continuation_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "continuationToken"}, ) """Continuation Token the next page of Twin Relationship.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of Twin Relationship.""" @@ -249,10 +289,11 @@ class QueryTwinsInput: Query API """ - query: Optional[str] = None + query: Optional[str] = dataclass_field(default=None, kw_only=True) """Query the Twins.""" - continuation_token: Optional[str] = field( + continuation_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "continuationToken"}, ) """Link to get next set of items.""" @@ -264,10 +305,11 @@ class QueryResult: Response for Query API """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Results From the Twin.""" - continuation_token: Optional[str] = field( + continuation_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "continuationToken"}, ) """Link to get next set of items.""" @@ -279,23 +321,27 @@ class IncomingRelationship: Definition: IncomingRelationship """ - source_id: Optional[str] = field( + source_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "$sourceId"}, ) """Source Id.""" - relationship_id: Optional[str] = field( + relationship_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "$relationshipId"}, ) """Relationship Id.""" - relationship_name: Optional[str] = field( + relationship_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "$relationshipName"}, ) """Relationship Name.""" - relationship_link: Optional[str] = field( + relationship_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "$relationshipLink"}, ) """Relationship Link.""" @@ -309,16 +355,16 @@ class AzuredigitaltwinsClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -329,8 +375,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -338,8 +384,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -351,7 +397,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -373,7 +419,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -405,7 +451,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def add_models_async( + def add_models( self, input: AddModelsInput, *, @@ -419,6 +465,21 @@ async def add_models_async( Uploads one or more models. When any error occurs, no models are uploaded. + + Swagger operation ID: `AddModels`. + + Args: + input: The request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/models" query_params = [] @@ -426,7 +487,7 @@ async def add_models_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -440,6 +501,7 @@ async def add_models_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -447,24 +509,42 @@ async def add_models_async( return json.loads(response.text) - async def list_models_async( + def list_models( self, + *, dependencies_for: Optional[str] = None, include_model_definition: Optional[str] = None, - continuation_token: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List Models Retrieves model metadata and, optionally, model definitions. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListModels`. + + Args: + dependencies_for: The set of the models which will have their + dependencies retrieved. If omitted, all models are retrieved. + include_model_definition: When true the model definition will be + returned as part of the result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/models" query_params = [] @@ -479,18 +559,20 @@ async def list_models_async( if isinstance(include_model_definition, bool): value = value.lower() query_params.append(f"includeModelDefinition={quote(value, safe='')}") - if continuation_token is not None: - value = str(continuation_token) - if isinstance(continuation_token, bool): - value = value.lower() - query_params.append(f"continuationToken={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -503,23 +585,32 @@ async def list_models_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def delete_model_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def delete_model( self, modelid: str, *, @@ -533,6 +624,22 @@ async def delete_model_async( Deletes a model. A model can only be deleted if no other models reference it. + + Swagger operation ID: `DeleteModel`. + + Args: + modelid: The id of the Model. The id is unique within the service + and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -543,7 +650,7 @@ async def delete_model_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -557,13 +664,14 @@ async def delete_model_async( request_url, response.status, response.text, + response=response, ) - async def get_model_by_id_async( + def get_model_by_id( self, modelid: str, - include_model_definition: Optional[str] = None, *, + include_model_definition: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -573,6 +681,24 @@ async def get_model_by_id_async( Get Model By Id Retrieves model metadata and, optionally, the model definition. + + Swagger operation ID: `GetModelById`. + + Args: + modelid: The id of the Model. The id is unique within the service + and case sensitive. + include_model_definition: When true the model definition will be + returned as part of the result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -588,7 +714,7 @@ async def get_model_by_id_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -602,6 +728,7 @@ async def get_model_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -609,9 +736,9 @@ async def get_model_by_id_async( return json.loads(response.text) - async def update_model_async( + def update_model( self, - input: UpdateModelInput, + input: UpdateModelInput | Mapping[str, Any], modelid: str, *, timeout: Optional[float] = None, @@ -623,6 +750,24 @@ async def update_model_async( Update Model's Property Updates the metadata for a model. + + Swagger operation ID: `UpdateModel`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + modelid: The id of the Model. The id is unique within the service + and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -633,7 +778,7 @@ async def update_model_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -647,9 +792,10 @@ async def update_model_async( request_url, response.status, response.text, + response=response, ) - async def get_twin_by_id_async( + def get_twin_by_id( self, twinid: str, *, @@ -662,6 +808,22 @@ async def get_twin_by_id_async( Get Twin by Id Retrieves a digital twin and its data. + + Swagger operation ID: `GetTwinById`. + + Args: + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -672,7 +834,7 @@ async def get_twin_by_id_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -686,6 +848,7 @@ async def get_twin_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -693,7 +856,7 @@ async def get_twin_by_id_async( return json.loads(response.text) - async def delete_twin_async( + def delete_twin( self, twinid: str, *, @@ -707,6 +870,22 @@ async def delete_twin_async( Deletes a digital twin. All relationships referencing the digital twin must already be deleted. + + Swagger operation ID: `DeleteTwin`. + + Args: + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -717,7 +896,7 @@ async def delete_twin_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -731,11 +910,12 @@ async def delete_twin_async( request_url, response.status, response.text, + response=response, ) - async def add_twin_async( + def add_twin( self, - input: AddTwinInput, + input: AddTwinInput | Mapping[str, Any], twinid: str, *, timeout: Optional[float] = None, @@ -747,6 +927,24 @@ async def add_twin_async( Add Twin Adds or replaces a digital twin. + + Swagger operation ID: `AddTwin`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -757,7 +955,7 @@ async def add_twin_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -771,6 +969,7 @@ async def add_twin_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -778,9 +977,9 @@ async def add_twin_async( return json.loads(response.text) - async def update_twin_async( + def update_twin( self, - input: UpdateTwinInput, + input: UpdateTwinInput | Mapping[str, Any], twinid: str, *, timeout: Optional[float] = None, @@ -792,6 +991,24 @@ async def update_twin_async( Update Twin Updates properties on a twin. + + Swagger operation ID: `UpdateTwin`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -802,7 +1019,7 @@ async def update_twin_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -816,9 +1033,10 @@ async def update_twin_async( request_url, response.status, response.text, + response=response, ) - async def get_component_async( + def get_component( self, twinid: str, component_path: str, @@ -832,6 +1050,23 @@ async def get_component_async( Get Component Retrieves a component from a digital twin. + + Swagger operation ID: `GetComponent`. + + Args: + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + component_path: The name of the DTDL component. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -845,7 +1080,7 @@ async def get_component_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -859,6 +1094,7 @@ async def get_component_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -866,9 +1102,9 @@ async def get_component_async( return json.loads(response.text) - async def update_component_async( + def update_component( self, - input: UpdateComponentInput, + input: UpdateComponentInput | Mapping[str, Any], twinid: str, component_path: str, *, @@ -881,6 +1117,25 @@ async def update_component_async( Update Component Updates integer properties on a component of a twin. + + Swagger operation ID: `UpdateComponent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + component_path: The name of the DTDL component. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -894,7 +1149,7 @@ async def update_component_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -908,9 +1163,10 @@ async def update_component_async( request_url, response.status, response.text, + response=response, ) - async def get_relationship_by_id_async( + def get_relationship_by_id( self, twinid: str, relationship_id: str, @@ -924,6 +1180,24 @@ async def get_relationship_by_id_async( Get Relationship by Id Retrieves a relationship between two digital twins. + + Swagger operation ID: `GetRelationshipById`. + + Args: + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + relationship_id: The id of the relationship. The id is unique + within the digital twin and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -937,7 +1211,7 @@ async def get_relationship_by_id_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -951,6 +1225,7 @@ async def get_relationship_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -958,7 +1233,7 @@ async def get_relationship_by_id_async( return json.loads(response.text) - async def delete_relationship_async( + def delete_relationship( self, twinid: str, relationship_id: str, @@ -972,6 +1247,24 @@ async def delete_relationship_async( Delete Relationship Deletes a relationship between two digital twins. + + Swagger operation ID: `DeleteRelationship`. + + Args: + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + relationship_id: The id of the relationship. The id is unique + within the digital twin and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -985,7 +1278,7 @@ async def delete_relationship_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -999,11 +1292,12 @@ async def delete_relationship_async( request_url, response.status, response.text, + response=response, ) - async def add_relationship_async( + def add_relationship( self, - input: AddRelationshipInput, + input: AddRelationshipInput | Mapping[str, Any], twinid: str, relationship_id: str, *, @@ -1016,6 +1310,26 @@ async def add_relationship_async( Add Relationship Adds a relationship between two digital twins. + + Swagger operation ID: `AddRelationship`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + relationship_id: The id of the relationship. The id is unique + within the digital twin and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1029,7 +1343,7 @@ async def add_relationship_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1043,6 +1357,7 @@ async def add_relationship_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1050,9 +1365,9 @@ async def add_relationship_async( return json.loads(response.text) - async def update_relationship_async( + def update_relationship( self, - input: UpdateRelationshipInput, + input: UpdateRelationshipInput | Mapping[str, Any], twinid: str, relationship_id: str, *, @@ -1065,6 +1380,26 @@ async def update_relationship_async( Update Relationship Updates integer properties on a relationship between two digital twins. + + Swagger operation ID: `UpdateRelationship`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + relationship_id: The id of the relationship. The id is unique + within the digital twin and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1078,7 +1413,7 @@ async def update_relationship_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -1092,25 +1427,42 @@ async def update_relationship_async( request_url, response.status, response.text, + response=response, ) - async def list_incoming_relationships_async( + def list_incoming_relationships( self, twinid: str, - continuation_token: Optional[str] = None, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List Incoming Relationships Retrieves all incoming relationships for a digital twin. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListIncomingRelationships`. + + Args: + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1120,18 +1472,20 @@ async def list_incoming_relationships_async( ) query_params = [] query_params.append("api-version=" + quote("2020-10-31", safe='')) - if continuation_token is not None: - value = str(continuation_token) - if isinstance(continuation_token, bool): - value = value.lower() - query_params.append(f"continuationToken={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1144,25 +1498,34 @@ async def list_incoming_relationships_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def send_telemetry_async( + return ItemPaged(get_next, extract_data) + + def send_telemetry( self, - input: SendTelemetryInput, + input: SendTelemetryInput | Mapping[str, Any], twinid: str, *, timeout: Optional[float] = None, @@ -1174,6 +1537,24 @@ async def send_telemetry_async( Send Telemetry Sends telemetry on behalf of a digital twin. + + Swagger operation ID: `SendTelemetry`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1184,7 +1565,7 @@ async def send_telemetry_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1198,11 +1579,12 @@ async def send_telemetry_async( request_url, response.status, response.text, + response=response, ) - async def send_component_telemetry_async( + def send_component_telemetry( self, - input: SendComponentTelemetryInput, + input: SendComponentTelemetryInput | Mapping[str, Any], twinid: str, component_path: str, *, @@ -1215,6 +1597,25 @@ async def send_component_telemetry_async( Send Component Telemetry Sends telemetry on behalf of a component in a digital twin. + + Swagger operation ID: `SendComponentTelemetry`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + component_path: The name of the DTDL component. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1229,7 +1630,7 @@ async def send_component_telemetry_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1243,25 +1644,42 @@ async def send_component_telemetry_async( request_url, response.status, response.text, + response=response, ) - async def list_relationships_async( + def list_relationships( self, twinid: str, - continuation_token: Optional[str] = None, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List Relationships Retrieves all outgoing relationships from a digital twin. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListRelationships`. + + Args: + twinid: The id of the digital twin. The id is unique within the + service and case sensitive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1269,18 +1687,20 @@ async def list_relationships_async( ) query_params = [] query_params.append("api-version=" + quote("2020-10-31", safe='')) - if continuation_token is not None: - value = str(continuation_token) - if isinstance(continuation_token, bool): - value = value.lower() - query_params.append(f"continuationToken={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1293,25 +1713,34 @@ async def list_relationships_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def query_twins_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def query_twins( self, - input: QueryTwinsInput, + input: QueryTwinsInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1323,6 +1752,22 @@ async def query_twins_async( Executes a query that allows traversing relationships and filtering by property values. + + Swagger operation ID: `QueryTwins`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/query" query_params = [] @@ -1330,7 +1775,7 @@ async def query_twins_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1344,6 +1789,7 @@ async def query_twins_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/azureeventgrid.py b/src/azure/connectors/azureeventgrid.py index 9d42dec..69980f8 100644 --- a/src/azure/connectors/azureeventgrid.py +++ b/src/azure/connectors/azureeventgrid.py @@ -5,21 +5,34 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "AzureeventgridClient", + "EventRequest", + "EventSchema", + "EventTypesResponse", + "ResourceNameResponse", + "Subscription", + "SubscriptionListResult", + "TopicTypesResponse", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +42,12 @@ class SubscriptionListResult: Response for List subscriptions """ - value: Optional[List[Subscription]] = None + value: Optional[ + List[Subscription | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The subscriptions available to the user.""" @@ -39,7 +57,7 @@ class TopicTypesResponse: Response for TopicTypes_List """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -48,7 +66,7 @@ class EventRequest: Definition: EventRequest """ - properties: Optional[Dict[str, Any]] = None + properties: Dict[str, Any] EventSchema = List[Dict[str, Any]] @@ -60,7 +78,7 @@ class EventTypesResponse: Definition: EventTypesResponse """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -69,7 +87,7 @@ class ResourceNameResponse: Definition: ResourceNameResponse """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -78,18 +96,20 @@ class Subscription: Definition: Subscription """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ The fully qualified Id. For example, /subscriptions/00000000-0000-0000-0000-000000000000. """ - subscription_id: Optional[str] = field( + subscription_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "subscriptionId"}, ) """The subscription Id.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The subscription display name.""" @@ -103,16 +123,16 @@ class AzureeventgridClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -123,8 +143,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -132,8 +152,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -145,7 +165,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -160,56 +180,152 @@ def __init__( def connector_name(self) -> str: return "azureeventgrid" - async def subscriptions_list_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_subscriptions( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List subscriptions Gets a list of all the subscriptions to which the principal has access. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Subscriptions_List`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/subscriptions" query_params = [] query_params.append("x-ms-api-version=" + quote("2015-11-01", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - if not response.text: - return None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - return json.loads(response.text) + return None, items() - async def topic_types_list_async( + return ItemPaged(get_next, extract_data) + + def list_topic_types( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ TopicTypes_List + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `TopicTypes_List`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -219,27 +335,48 @@ async def topic_types_list_async( query_params.append("x-ms-api-version=" + quote("2017-09-15-preview", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - if not response.text: - return None + return None, items() - return json.loads(response.text) + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/azureiotcentral.py b/src/azure/connectors/azureiotcentral.py index 3d5916a..e7f0fb4 100644 --- a/src/azure/connectors/azureiotcentral.py +++ b/src/azure/connectors/azureiotcentral.py @@ -5,21 +5,106 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "AzureiotcentralClient", + "Action", + "ActionGroupsAction", + "Application", + "ApplicationCollection", + "CloudPropertyJobData", + "CommandJobData", + "DateJobSchedule", + "Device", + "DeviceCloudProperties", + "DeviceCollection", + "DeviceCommand", + "DeviceCommandV1", + "DeviceComponentCommand", + "DeviceComponentTelemetry", + "DeviceGroup", + "DeviceGroupCollection", + "DeviceGroupDeviceCollection", + "DeviceModuleCommand", + "DeviceModuleComponentCommand", + "DeviceModuleComponentTelemetry", + "DeviceModuleTelemetry", + "DeviceProperties", + "DeviceRelationship", + "DeviceRelationshipCollection", + "DeviceRelationshipStatic", + "DeviceTelemetry", + "DeviceTemplate", + "DeviceTemplateCollection", + "DeviceTemplateCollectionV1", + "DeviceTemplateMigrationJobData", + "DeviceTemplateV1", + "DeviceV1", + "DeviceV2", + "DynamicValues", + "EmailAction", + "EmailUser", + "Job", + "JobBatch", + "JobCancellationThreshold", + "JobCollection", + "JobDeviceStatus", + "JobDeviceStatusCollection", + "JobSchedule", + "JobScheduleEnd", + "JobStatic", + "LogicAppsAction", + "ModuleProperties", + "OccurrencesJobSchedule", + "Organization", + "OrganizationCollection", + "OrganizationStatic", + "PowerAutomateAction", + "PropertyJobData", + "Role", + "RoleAssignment", + "RoleCollection", + "Rule", + "RuleCollection", + "ScheduledJob", + "ScheduledJobCollection", + "ScheduledJobJobCollection", + "ScheduledJobPatch", + "ScheduledJobStatic", + "SchemaDeviceCloudPropertiesResponse", + "SchemaDeviceCommandResponse", + "SchemaDevicePropertiesResponse", + "SchemaDeviceTelemetryResponse", + "SchemaJobResponse", + "SchemaScheduledJobResponse", + "SchemaUserResponse", + "ServicePrincipalUser", + "User", + "UserCollection", + "UserPatch", + "UserStatic", + "WebhookAction", + "WebhookActionBody", + "WebhookActionDevice", + "WorkflowTrigger", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,10 +114,11 @@ class DeviceGroupCollection: Response for List device groups """ - value: Optional[List[DeviceGroup]] = None + value: List[DeviceGroup | Mapping[str, Any]] """The collection of device groups.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of device groups.""" @@ -44,20 +130,17 @@ class DeviceGroup: Response for Get a device group """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the device group.""" - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """Display name of the device group.""" - filter: Optional[str] = None + filter: str """Query defining which devices should be in this group.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Short summary of device group.""" - etag: Optional[str] = None + etag: Optional[str] = dataclass_field(default=None, kw_only=True) """ETag used to prevent conflict in device group updates.""" - organizations: Optional[List[str]] = None + organizations: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ List of organizations of the device group, only one organization is supported today, multiple organizations will be supported soon. @@ -70,10 +153,11 @@ class DeviceGroupDeviceCollection: Response for Get devices by device group ID """ - value: Optional[List[DeviceV1]] = None + value: List[DeviceV1 | Mapping[str, Any]] """The collection of devices belonging to the device group.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of devices in the group.""" @@ -85,7 +169,7 @@ class DeviceCloudProperties: Response for Get device cloud properties (deprecated) """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -98,30 +182,33 @@ class DeviceCommand: Response for Execute a device command (deprecated) """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The request ID of the device command execution.""" - request: Optional[Any] = None + request: Optional[Any] = dataclass_field(default=None, kw_only=True) """The payload for the device command.""" - response: Optional[Any] = None + response: Optional[Any] = dataclass_field(default=None, kw_only=True) """The payload of the device command response.""" - connection_timeout: Optional[int] = field( + connection_timeout: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "connectionTimeout"}, ) """ Connection timeout in seconds to wait for a disconnected device to come online. Defaults to 0 seconds. """ - response_timeout: Optional[int] = field( + response_timeout: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseTimeout"}, ) """ Response timeout in seconds to wait for a command completion on a device. Defaults to 30 seconds. """ - response_code: Optional[int] = field( + response_code: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseCode"}, ) """The status code of the device command response.""" @@ -133,10 +220,11 @@ class DeviceRelationshipCollection: Response for List relationships """ - value: Optional[List[DeviceRelationshipStatic]] = None + value: List[DeviceRelationshipStatic | Mapping[str, Any]] """The collection of device relationships.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of device relationships.""" @@ -148,11 +236,11 @@ class DeviceRelationshipStatic: Response for Get device relationship """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the device relationship.""" - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """The device ID of the source (parent) device.""" - target: Optional[str] = None + target: Optional[str] = dataclass_field(default=None, kw_only=True) """The device ID of the source (child) device.""" @@ -162,10 +250,11 @@ class JobCollection: Response for List jobs """ - value: Optional[List[JobStatic]] = None + value: List[JobStatic | Mapping[str, Any]] """The collection of jobs.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of jobs.""" @@ -177,36 +266,37 @@ class JobStatic: Response for Get a job """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the job.""" - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """Display name of the job.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Detailed description of the job.""" - group: Optional[str] = None + group: str """The ID of the device group on which to execute the job.""" - batch: Optional[JobBatch] = None + batch: Optional[JobBatch | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) """The batching configuration for the job.""" - cancellation_threshold: Optional[JobCancellationThreshold] = field( + cancellation_threshold: Optional[ + JobCancellationThreshold | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "cancellationThreshold"}, ) """The cancellation threshold for the job.""" - data: Optional[List[Dict[str, Any]]] = None + data: List[Dict[str, Any]] """ Data related to the operation being performed by this job. All entries must be of the same type. """ - organizations: Optional[List[str]] = None + organizations: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ List of organizations of the job, only one organization is supported today, multiple organizations will be supported soon. """ - scheduled_job_id: Optional[str] = field( + scheduled_job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "scheduledJobId"}, ) """Id of the scheduled job definition that created this job.""" @@ -218,31 +308,32 @@ class Job: Response for Create a job """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the job.""" - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """Display name of the job.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Detailed description of the job.""" - group: Optional[str] = None + group: str """The ID of the device group on which to execute the job.""" - batch: Optional[JobBatch] = None + batch: Optional[JobBatch | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) """The batching configuration for the job.""" - cancellation_threshold: Optional[JobCancellationThreshold] = field( + cancellation_threshold: Optional[ + JobCancellationThreshold | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "cancellationThreshold"}, ) """The cancellation threshold for the job.""" - organizations: Optional[List[str]] = None + organizations: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ List of organizations of the job, only one organization is supported today, multiple organizations will be supported soon. """ - scheduled_job_id: Optional[str] = field( + scheduled_job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "scheduledJobId"}, ) """Id of the scheduled job definition that created this job.""" @@ -254,10 +345,11 @@ class JobDeviceStatusCollection: Response for Get device statuses """ - value: Optional[List[JobDeviceStatus]] = None + value: List[JobDeviceStatus | Mapping[str, Any]] """The collection of job device statuses.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of job device statuses.""" @@ -269,10 +361,11 @@ class OrganizationCollection: Response for List organizations """ - value: Optional[List[Organization]] = None + value: List[Organization | Mapping[str, Any]] """The collection of organizations.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of organizations.""" @@ -284,14 +377,15 @@ class Organization: Response for Get an organization """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the organization.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the organization.""" - parent: Optional[str] = None + parent: Optional[str] = dataclass_field(default=None, kw_only=True) """Display name of the parent organization.""" @@ -301,10 +395,11 @@ class ScheduledJobCollection: Response for List scheduled jobs """ - value: Optional[List[ScheduledJob]] = None + value: List[ScheduledJob | Mapping[str, Any]] """The collection of scheduled jobs.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of scheduled jobs.""" @@ -316,36 +411,36 @@ class ScheduledJob: Response for Get a scheduled job """ - etag: Optional[str] = None + etag: Optional[str] = dataclass_field(default=None, kw_only=True) """ETag used to prevent conflict in scheduled job updates.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the scheduled job.""" - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """Display name of the scheduled job.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Detailed description of the scheduled job.""" - group: Optional[str] = None + group: str """The ID of the device group on which to execute the job.""" - batch: Optional[JobBatch] = None + batch: Optional[JobBatch | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) """The batching configuration for the scheduled job.""" - cancellation_threshold: Optional[JobCancellationThreshold] = field( + cancellation_threshold: Optional[ + JobCancellationThreshold | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "cancellationThreshold"}, ) """The cancellation threshold for the scheduled job.""" - organizations: Optional[List[str]] = None + organizations: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ List of organizations of the job, only one organization is supported today, multiple organizations will be supported soon. """ - schedule: Optional[Dict[str, Any]] = None + schedule: Dict[str, Any] """The schedule at which to execute the job.""" - enabled: Optional[bool] = None + enabled: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the scheduled job is enabled.""" - completed: Optional[bool] = None + completed: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the scheduled job has completed.""" @@ -355,41 +450,41 @@ class ScheduledJobStatic: Response for Update a scheduled job """ - etag: Optional[str] = None + etag: Optional[str] = dataclass_field(default=None, kw_only=True) """ETag used to prevent conflict in scheduled job updates.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the scheduled job.""" - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """Display name of the scheduled job.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Detailed description of the scheduled job.""" - group: Optional[str] = None + group: str """The ID of the device group on which to execute the job.""" - batch: Optional[JobBatch] = None + batch: Optional[JobBatch | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) """The batching configuration for the scheduled job.""" - cancellation_threshold: Optional[JobCancellationThreshold] = field( + cancellation_threshold: Optional[ + JobCancellationThreshold | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "cancellationThreshold"}, ) """The cancellation threshold for the scheduled job.""" - data: Optional[List[Dict[str, Any]]] = None + data: List[Dict[str, Any]] """ Data related to the operation being performed by this job. All entries must be of the same type. """ - organizations: Optional[List[str]] = None + organizations: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ List of organizations of the job, only one organization is supported today, multiple organizations will be supported soon. """ - schedule: Optional[Dict[str, Any]] = None + schedule: Dict[str, Any] """The schedule at which to execute the job.""" - enabled: Optional[bool] = None + enabled: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the scheduled job is enabled.""" - completed: Optional[bool] = None + completed: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the scheduled job has completed.""" @@ -399,10 +494,11 @@ class ScheduledJobJobCollection: Response for Get jobs by scheduled job ID """ - value: Optional[List[JobStatic]] = None + value: List[JobStatic | Mapping[str, Any]] """The collection of jobs.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of jobs.""" @@ -414,11 +510,11 @@ class WorkflowTrigger: Response for When a rule is fired """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the workflow trigger.""" - rule: Optional[str] = None + rule: str """Unique ID of the rule that is tied to the workflow trigger.""" - url: Optional[str] = None + url: str """Callback URL of the workflow Trigger.""" @@ -428,22 +524,23 @@ class DeviceV1: Response for Get a device by ID """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the device.""" - etag: Optional[str] = None + etag: Optional[str] = dataclass_field(default=None, kw_only=True) """ETag used to prevent conflict in device updates.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the device.""" - template: Optional[str] = None + template: Optional[str] = dataclass_field(default=None, kw_only=True) """The device template definition for the device.""" - simulated: Optional[bool] = None + simulated: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the device is simulated.""" - enabled: Optional[bool] = None + enabled: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the device connection to IoT Central has been enabled.""" - provisioned: Optional[bool] = None + provisioned: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether resources have been allocated for the device.""" @@ -453,30 +550,33 @@ class DeviceCommandV1: Response for Get device command response """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The request ID of the device command execution.""" - request: Optional[Any] = None + request: Optional[Any] = dataclass_field(default=None, kw_only=True) """The payload for the device command.""" - response: Optional[Any] = None + response: Optional[Any] = dataclass_field(default=None, kw_only=True) """The payload of the device command response.""" - connection_timeout: Optional[int] = field( + connection_timeout: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "connectionTimeout"}, ) """ Connection timeout in seconds to wait for a disconnected device to come online. Defaults to 0 seconds. """ - response_timeout: Optional[int] = field( + response_timeout: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseTimeout"}, ) """ Response timeout in seconds to wait for a command completion on a device. Defaults to 30 seconds. """ - response_code: Optional[int] = field( + response_code: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseCode"}, ) """The status code of the device command response.""" @@ -488,30 +588,33 @@ class DeviceComponentCommand: Response for Get component command response """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The request ID of the device command execution.""" - request: Optional[Any] = None + request: Optional[Any] = dataclass_field(default=None, kw_only=True) """The payload for the device command.""" - response: Optional[Any] = None + response: Optional[Any] = dataclass_field(default=None, kw_only=True) """The payload of the device command response.""" - connection_timeout: Optional[int] = field( + connection_timeout: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "connectionTimeout"}, ) """ Connection timeout in seconds to wait for a disconnected device to come online. Defaults to 0 seconds. """ - response_timeout: Optional[int] = field( + response_timeout: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseTimeout"}, ) """ Response timeout in seconds to wait for a command completion on a device. Defaults to 30 seconds. """ - response_code: Optional[int] = field( + response_code: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseCode"}, ) """The status code of the device command response.""" @@ -523,9 +626,9 @@ class DeviceComponentTelemetry: Response for Get component telemetry value """ - value: Optional[Any] = None + value: Optional[Any] = dataclass_field(default=None, kw_only=True) """The last known value of this device telemetry.""" - timestamp: Optional[str] = None + timestamp: Optional[str] = dataclass_field(default=None, kw_only=True) """ String-formatted date representing the time when the telemetry value was sent. @@ -538,30 +641,33 @@ class DeviceModuleCommand: Response for Get module command response """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The request ID of the device command execution.""" - request: Optional[Any] = None + request: Optional[Any] = dataclass_field(default=None, kw_only=True) """The payload for the device command.""" - response: Optional[Any] = None + response: Optional[Any] = dataclass_field(default=None, kw_only=True) """The payload of the device command response.""" - connection_timeout: Optional[int] = field( + connection_timeout: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "connectionTimeout"}, ) """ Connection timeout in seconds to wait for a disconnected device to come online. Defaults to 0 seconds. """ - response_timeout: Optional[int] = field( + response_timeout: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseTimeout"}, ) """ Response timeout in seconds to wait for a command completion on a device. Defaults to 30 seconds. """ - response_code: Optional[int] = field( + response_code: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseCode"}, ) """The status code of the device command response.""" @@ -573,30 +679,33 @@ class DeviceModuleComponentCommand: Response for Get module component command response """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The request ID of the device command execution.""" - request: Optional[Any] = None + request: Optional[Any] = dataclass_field(default=None, kw_only=True) """The payload for the device command.""" - response: Optional[Any] = None + response: Optional[Any] = dataclass_field(default=None, kw_only=True) """The payload of the device command response.""" - connection_timeout: Optional[int] = field( + connection_timeout: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "connectionTimeout"}, ) """ Connection timeout in seconds to wait for a disconnected device to come online. Defaults to 0 seconds. """ - response_timeout: Optional[int] = field( + response_timeout: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseTimeout"}, ) """ Response timeout in seconds to wait for a command completion on a device. Defaults to 30 seconds. """ - response_code: Optional[int] = field( + response_code: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseCode"}, ) """The status code of the device command response.""" @@ -608,9 +717,9 @@ class DeviceModuleComponentTelemetry: Response for Get module component telemetry value """ - value: Optional[Any] = None + value: Optional[Any] = dataclass_field(default=None, kw_only=True) """The last known value of this device telemetry.""" - timestamp: Optional[str] = None + timestamp: Optional[str] = dataclass_field(default=None, kw_only=True) """ String-formatted date representing the time when the telemetry value was sent. @@ -623,7 +732,7 @@ class ModuleProperties: Response for Get module properties """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -636,9 +745,9 @@ class DeviceModuleTelemetry: Response for Get module telemetry value """ - value: Optional[Any] = None + value: Optional[Any] = dataclass_field(default=None, kw_only=True) """The last known value of this device telemetry.""" - timestamp: Optional[str] = None + timestamp: Optional[str] = dataclass_field(default=None, kw_only=True) """ String-formatted date representing the time when the telemetry value was sent. @@ -651,7 +760,7 @@ class DeviceProperties: Response for Get device properties """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -664,9 +773,9 @@ class DeviceTelemetry: Response for Get device telemetry value """ - value: Optional[Any] = None + value: Optional[Any] = dataclass_field(default=None, kw_only=True) """The last known value of this device telemetry.""" - timestamp: Optional[str] = None + timestamp: Optional[str] = dataclass_field(default=None, kw_only=True) """ String-formatted date representing the time when the telemetry value was sent. @@ -679,10 +788,11 @@ class DeviceCollection: Response for List devices """ - value: Optional[List[DeviceV1]] = None + value: List[DeviceV1 | Mapping[str, Any]] """The collection of devices.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of devices.""" @@ -694,27 +804,28 @@ class DeviceV2: Response for Create or update a device """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the device.""" - etag: Optional[str] = None + etag: Optional[str] = dataclass_field(default=None, kw_only=True) """ETag used to prevent conflict in device updates.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the device.""" - template: Optional[str] = None + template: Optional[str] = dataclass_field(default=None, kw_only=True) """The device template definition for the device.""" - simulated: Optional[bool] = None + simulated: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the device is simulated.""" - enabled: Optional[bool] = None + enabled: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the device connection to IoT Central has been enabled.""" - organizations: Optional[List[str]] = None + organizations: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ List of organizations of the device, only one organization is supported today, multiple organizations will be supported soon. """ - provisioned: Optional[bool] = None + provisioned: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether resources have been allocated for the device.""" @@ -724,24 +835,27 @@ class DeviceTemplateV1: Response for Get a device template by ID """ - id: Optional[str] = field(default=None, metadata={"wire_name": "@id"}) - """Unique ID of the device template.""" - etag: Optional[str] = None - """ETag used to prevent conflict in device template updates.""" - type_: Optional[List[str]] = field( + id: Optional[str] = dataclass_field( default=None, - metadata={"wire_name": "@type"}, + kw_only=True, + metadata={"wire_name": "@id"}, ) + """Unique ID of the device template.""" + etag: Optional[str] = dataclass_field(default=None, kw_only=True) + """ETag used to prevent conflict in device template updates.""" + type_: List[str] = dataclass_field(metadata={"wire_name": "@type"}) """The JSON-LD types of this device template.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the device template.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Detailed description of the device template.""" - capability_model: Optional[Any] = field( + capability_model: Optional[Any] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "capabilityModel"}, ) """The capability model utilized by this device template.""" @@ -753,10 +867,11 @@ class DeviceTemplateCollectionV1: Response for List device templates """ - value: Optional[List[DeviceTemplateV1]] = None + value: List[DeviceTemplateV1 | Mapping[str, Any]] """The collection of device templates.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of device templates.""" @@ -768,10 +883,11 @@ class Role: Response for Get role """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the role.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the role.""" @@ -783,7 +899,7 @@ class RoleCollection: Response for List roles """ - value: Optional[List[Role]] = None + value: List[Role | Mapping[str, Any]] """The collection of roles.""" @@ -793,7 +909,7 @@ class User: Response for Create user """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -806,11 +922,15 @@ class UserStatic: Response for Get user """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the user.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type of the user.""" - roles: Optional[List[RoleAssignment]] = None + roles: List[RoleAssignment | Mapping[str, Any]] """ List of role assignments that specify the permissions to access the application. @@ -823,7 +943,7 @@ class UserCollection: Response for List users """ - value: Optional[List[UserStatic]] = None + value: List[UserStatic | Mapping[str, Any]] """The collection of users.""" @@ -833,7 +953,7 @@ class UserPatch: Response for Update user """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -846,10 +966,11 @@ class ApplicationCollection: Response for Get the list of applications accessible to the signed-in user """ - value: Optional[List[Application]] = None + value: List[Application | Mapping[str, Any]] """The collection of applications.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of applications.""" @@ -861,10 +982,11 @@ class DeviceTemplateCollection: Response for List device templates """ - value: Optional[List[DeviceTemplate]] = None + value: List[DeviceTemplate | Mapping[str, Any]] """The collection of device templates.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of device templates.""" @@ -879,7 +1001,7 @@ class SchemaDeviceCloudPropertiesResponse: Response for Schema_DeviceCloudProperties """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -892,7 +1014,7 @@ class SchemaDeviceCommandResponse: Response for Schema_DeviceCommand """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -905,7 +1027,7 @@ class SchemaDevicePropertiesResponse: Response for Schema_DeviceProperties """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -918,7 +1040,7 @@ class SchemaDeviceTelemetryResponse: Response for Schema_DeviceTelemetry """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -931,7 +1053,7 @@ class SchemaJobResponse: Response for Schema_Job """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -944,7 +1066,7 @@ class SchemaScheduledJobResponse: Response for Schema_ScheduledJob """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -957,7 +1079,7 @@ class SchemaUserResponse: Response for Schema_User """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -970,16 +1092,17 @@ class Action: Definition: Action """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the action.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the action.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """Type of the action.""" - rules: Optional[List[str]] = None + rules: List[str] """Unique IDs of the rules that are tied to the action.""" @@ -989,16 +1112,17 @@ class EmailAction: Definition: EmailAction """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the email action.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the email action.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """Type of the email action.""" - rules: Optional[List[str]] = None + rules: List[str] """Unique IDs of the rules that are tied to the email action.""" @@ -1008,18 +1132,19 @@ class WebhookAction: Definition: WebhookAction """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the webhook action.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the webhook action.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """Type of the webhook action.""" - rules: Optional[List[str]] = None + rules: List[str] """Unique IDs of the rules that are tied to the webhook action.""" - url: Optional[str] = None + url: str """Callback URL of the webhook.""" @@ -1029,16 +1154,17 @@ class PowerAutomateAction: Definition: PowerAutomateAction """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the Power Automate action.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the Power Automate action.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """Type of the Power Automate action.""" - rules: Optional[List[str]] = None + rules: List[str] """Unique IDs of the rules that are tied to the Power Automate action.""" @@ -1048,16 +1174,17 @@ class LogicAppsAction: Definition: LogicAppsAction """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the Logic Apps action.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the Logic Apps action.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """Type of the Logic Apps action.""" - rules: Optional[List[str]] = None + rules: List[str] """Unique IDs of the rules that are tied to the Logic Apps action.""" @@ -1067,16 +1194,17 @@ class ActionGroupsAction: Definition: ActionGroupsAction """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the Action Groups action.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the Action Groups action.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """Type of the Action Groups action.""" - rules: Optional[List[str]] = None + rules: List[str] """Unique IDs of the rules that are tied to the Action Groups action.""" @@ -1086,16 +1214,17 @@ class Application: Definition: Application """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the application.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the application.""" - subdomain: Optional[str] = None + subdomain: str """The URL subdomain of the application.""" - host: Optional[str] = None + host: str """The URL host of the application.""" @@ -1105,25 +1234,27 @@ class Device: Definition: Device """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the device.""" - etag: Optional[str] = None + etag: Optional[str] = dataclass_field(default=None, kw_only=True) """ETag used to prevent conflict in device updates.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the device.""" - instance_of: Optional[str] = field( + instance_of: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "instanceOf"}, ) """The device template definition for the device.""" - simulated: Optional[bool] = None + simulated: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the device is simulated.""" - approved: Optional[bool] = None + approved: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the device has been approved to connect to IoT Central.""" - provisioned: Optional[bool] = None + provisioned: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether resources have been allocated for the device.""" @@ -1133,9 +1264,9 @@ class DeviceRelationship: Definition: DeviceRelationship """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the device relationship.""" - target: Optional[str] = None + target: str """The device ID of the source (child) device.""" @@ -1145,18 +1276,19 @@ class DeviceTemplate: Definition: DeviceTemplate """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the device template.""" - etag: Optional[str] = None + etag: Optional[str] = dataclass_field(default=None, kw_only=True) """ETag used to prevent conflict in device template updates.""" - types: Optional[List[str]] = None + types: List[str] """The types of device to which this template applies.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the device template.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Detailed description of the device template.""" @@ -1166,7 +1298,7 @@ class PropertyJobData: Definition: PropertyJobData """ - data: Optional[List[Dict[str, Any]]] = None + data: List[Dict[str, Any]] """ Data related to the operation being performed by this job. All entries must be of the same type. @@ -1179,7 +1311,7 @@ class CommandJobData: Definition: CommandJobData """ - data: Optional[List[Dict[str, Any]]] = None + data: List[Dict[str, Any]] """ Data related to the operation being performed by this job. All entries must be of the same type. @@ -1192,7 +1324,7 @@ class CloudPropertyJobData: Definition: CloudPropertyJobData """ - data: Optional[List[Dict[str, Any]]] = None + data: List[Dict[str, Any]] """The collection of job data.""" @@ -1202,7 +1334,7 @@ class DeviceTemplateMigrationJobData: Definition: DeviceTemplateMigrationJobData """ - data: Optional[List[Dict[str, Any]]] = None + data: List[Dict[str, Any]] """The collection of job data.""" @@ -1212,9 +1344,9 @@ class JobDeviceStatus: Definition: JobDeviceStatus """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID of the device whose job status is being provided.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Indicates whether the job is starting, running, etc. for the given device. """ @@ -1226,12 +1358,12 @@ class JobBatch: Definition: JobBatch """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """ Whether batching is done on a specified number of devices or a percentage of the total devices. """ - value: Optional[float] = None + value: float """The number or percentage of devices on which batching is done.""" @@ -1241,17 +1373,17 @@ class JobCancellationThreshold: Definition: JobCancellationThreshold """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """ Whether the cancellation threshold is per a specified number of devices or a percentage of the total devices. """ - value: Optional[float] = None + value: float """ The number or percentage of devices on which the cancellation threshold is applied. """ - batch: Optional[bool] = None + batch: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether the cancellation threshold applies per-batch or to the overall job. """ @@ -1266,10 +1398,11 @@ class Rule: Definition: Rule """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the rule.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the rule.""" @@ -1281,10 +1414,11 @@ class RuleCollection: Definition: RuleCollection """ - value: Optional[List[Rule]] = None + value: List[Rule | Mapping[str, Any]] """The collection of rules.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """URL to get the next page of rules.""" @@ -1296,7 +1430,7 @@ class JobSchedule: Definition: JobSchedule """ - schedule: Optional[Dict[str, Any]] = None + schedule: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The schedule at which to execute the job.""" @@ -1306,7 +1440,7 @@ class DateJobSchedule: Definition: DateJobSchedule """ - schedule: Optional[Dict[str, Any]] = None + schedule: Dict[str, Any] """The schedule at which to execute the job.""" @@ -1316,7 +1450,7 @@ class OccurrencesJobSchedule: Definition: OccurrencesJobSchedule """ - schedule: Optional[Dict[str, Any]] = None + schedule: Dict[str, Any] """The schedule at which to execute the job.""" @@ -1326,11 +1460,15 @@ class JobScheduleEnd: Definition: JobScheduleEnd """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type of the job schedule end.""" - date: Optional[str] = None + date: Optional[str] = dataclass_field(default=None, kw_only=True) """The date when to end the scheduled job (YYYY-MM-DDTHH:MM:SSZ).""" - occurrences: Optional[int] = None + occurrences: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of occurrences after which to end the scheduled job.""" @@ -1340,15 +1478,15 @@ class ScheduledJobPatch: Definition: ScheduledJobPatch """ - etag: Optional[str] = None + etag: Optional[str] = dataclass_field(default=None, kw_only=True) """ETag used to prevent conflict in scheduled job updates.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the scheduled job.""" - schedule: Optional[Dict[str, Any]] = None + schedule: Dict[str, Any] """The schedule at which to execute the job.""" - enabled: Optional[bool] = None + enabled: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the scheduled job is enabled.""" - completed: Optional[bool] = None + completed: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the scheduled job has completed.""" @@ -1358,16 +1496,16 @@ class EmailUser: Definition: EmailUser """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the user.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """Type of the user.""" - roles: Optional[List[RoleAssignment]] = None + roles: List[RoleAssignment | Mapping[str, Any]] """ List of role assignments that specify the permissions to access the application. """ - email: Optional[str] = None + email: str """Email address of the user.""" @@ -1377,24 +1515,18 @@ class ServicePrincipalUser: Definition: ServicePrincipalUser """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the user.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """Type of the user.""" - roles: Optional[List[RoleAssignment]] = None + roles: List[RoleAssignment | Mapping[str, Any]] """ List of role assignments that specify the permissions to access the application. """ - tenant_id: Optional[str] = field( - default=None, - metadata={"wire_name": "tenantId"}, - ) + tenant_id: str = dataclass_field(metadata={"wire_name": "tenantId"}) """The Microsoft Entra ID tenant ID of the service principal.""" - object_id: Optional[str] = field( - default=None, - metadata={"wire_name": "objectId"}, - ) + object_id: str = dataclass_field(metadata={"wire_name": "objectId"}) """The Microsoft Entra ID object ID of the service principal.""" @@ -1404,7 +1536,7 @@ class RoleAssignment: Definition: RoleAssignment """ - role: Optional[str] = None + role: str """ID of the role for this role assignment.""" @@ -1414,34 +1546,37 @@ class WebhookActionDevice: Definition: WebhookActionDevice """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the device.""" - etag: Optional[str] = None + etag: Optional[str] = dataclass_field(default=None, kw_only=True) """ETag used to prevent conflict in device updates.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the device.""" - instance_of: Optional[str] = field( + instance_of: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "instanceOf"}, ) """The device template definition for the device.""" - simulated: Optional[bool] = None + simulated: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the device is simulated.""" - approved: Optional[bool] = None + approved: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the device has been approved to connect to IoT Central.""" - provisioned: Optional[bool] = None + provisioned: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether resources have been allocated for the device.""" - cloud_properties: Optional[Dict[str, Any]] = field( + cloud_properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "cloudProperties"}, ) """Cloud properties that triggered the webhook.""" - properties: Optional[Dict[str, Any]] = None + properties: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Device properties that triggered the webhook.""" - telemetry: Optional[Dict[str, Any]] = None + telemetry: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Device telemetry that triggered the webhook.""" @@ -1451,15 +1586,15 @@ class WebhookActionBody: Definition: WebhookActionBody """ - action: Optional[Action] = None + action: Action | Mapping[str, Any] """Action that triggered the webhook.""" - application: Optional[Application] = None + application: Application | Mapping[str, Any] """Application that triggered the webhook.""" - device: Optional[WebhookActionDevice] = None + device: WebhookActionDevice | Mapping[str, Any] """Device that triggered the webhook.""" - rule: Optional[Rule] = None + rule: Rule | Mapping[str, Any] """Rule that triggered the webhook.""" - timestamp: Optional[str] = None + timestamp: str """Timestamp at which the webhook was triggered.""" @@ -1471,16 +1606,16 @@ class AzureiotcentralClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -1491,8 +1626,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -1500,8 +1635,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -1513,7 +1648,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -1535,7 +1670,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -1567,7 +1702,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def device_groups_list_async( + def list_device_groups( self, application: str, *, @@ -1575,14 +1710,30 @@ async def device_groups_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List device groups Get the list of device groups in an application. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `DeviceGroups_List`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/api/ga_2022_07_31/deviceGroups" @@ -1594,11 +1745,18 @@ async def device_groups_list_async( query_params.append(f"application={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1611,23 +1769,32 @@ async def device_groups_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def device_groups_get_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def device_groups_get( self, device_group_id: str, application: str, @@ -1641,6 +1808,22 @@ async def device_groups_get_async( Get a device group Get details about an existing device group by ID. + + Swagger operation ID: `DeviceGroups_Get`. + + Args: + device_group_id: Unique ID of the device group. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1657,7 +1840,7 @@ async def device_groups_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1671,6 +1854,7 @@ async def device_groups_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1678,9 +1862,9 @@ async def device_groups_get_async( return json.loads(response.text) - async def device_groups_set_async( + def device_groups_set( self, - input: DeviceGroup, + input: DeviceGroup | Mapping[str, Any], device_group_id: str, application: str, *, @@ -1693,6 +1877,24 @@ async def device_groups_set_async( Create a device group Create or update a device group. + + Swagger operation ID: `DeviceGroups_Set`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_group_id: Unique ID of the device group. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1709,7 +1911,7 @@ async def device_groups_set_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1723,6 +1925,7 @@ async def device_groups_set_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1730,7 +1933,7 @@ async def device_groups_set_async( return json.loads(response.text) - async def device_groups_remove_async( + def device_groups_remove( self, device_group_id: str, application: str, @@ -1744,6 +1947,22 @@ async def device_groups_remove_async( Delete device group Delete an existing device group by ID + + Swagger operation ID: `DeviceGroups_Remove`. + + Args: + device_group_id: Unique ID of the device group. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1760,7 +1979,7 @@ async def device_groups_remove_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1774,9 +1993,10 @@ async def device_groups_remove_async( request_url, response.status, response.text, + response=response, ) - async def device_groups_get_devices_async( + def list_device_groups_get_devices( self, device_group_id: str, application: str, @@ -1785,14 +2005,31 @@ async def device_groups_get_devices_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get devices by device group ID Get the list of devices in a device group in an application. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `DeviceGroups_GetDevices`. + + Args: + device_group_id: Unique ID of the device group. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1809,11 +2046,18 @@ async def device_groups_get_devices_async( query_params.append(f"application={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1826,28 +2070,37 @@ async def device_groups_get_devices_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def devices_get_cloud_properties_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def devices_get_cloud_properties( self, device_id: str, application: str, - instance_of: Optional[str] = None, *, + instance_of: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1857,6 +2110,23 @@ async def devices_get_cloud_properties_async( Get device cloud properties (deprecated) Get all cloud property values of a device by device ID (deprecated). + + Swagger operation ID: `Devices_GetCloudProperties`. + + Args: + device_id: Unique ID of the device. + application: Unique ID of the application. + instance_of: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1879,7 +2149,7 @@ async def devices_get_cloud_properties_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1893,6 +2163,7 @@ async def devices_get_cloud_properties_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1900,13 +2171,13 @@ async def devices_get_cloud_properties_async( return json.loads(response.text) - async def devices_update_cloud_properties_async( + def devices_update_cloud_properties( self, - input: DeviceCloudProperties, + input: DeviceCloudProperties | Mapping[str, Any], device_id: str, application: str, - instance_of: Optional[str] = None, *, + instance_of: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1916,6 +2187,25 @@ async def devices_update_cloud_properties_async( Update device cloud properties (deprecated) Update all cloud property values of a device by device ID (deprecated). + + Swagger operation ID: `Devices_UpdateCloudProperties`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + application: Unique ID of the application. + instance_of: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1938,7 +2228,7 @@ async def devices_update_cloud_properties_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1952,6 +2242,7 @@ async def devices_update_cloud_properties_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1959,15 +2250,15 @@ async def devices_update_cloud_properties_async( return json.loads(response.text) - async def devices_execute_component_command_async( + def devices_execute_component_command( self, - input: DeviceCommand, + input: DeviceCommand | Mapping[str, Any], device_id: str, component_name: str, command_name: str, application: str, - instance_of: Optional[str] = None, *, + instance_of: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1977,6 +2268,27 @@ async def devices_execute_component_command_async( Execute a device command (deprecated) Execute a command on a device (deprecated). + + Swagger operation ID: `Devices_ExecuteComponentCommand`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + component_name: Name of the device component. + command_name: Name of this device command. + application: Unique ID of the application. + instance_of: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2002,7 +2314,7 @@ async def devices_execute_component_command_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2016,6 +2328,7 @@ async def devices_execute_component_command_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2023,7 +2336,7 @@ async def devices_execute_component_command_async( return json.loads(response.text) - async def device_relationships_list_async( + def list_device_relationships( self, device_id: str, application: str, @@ -2032,14 +2345,31 @@ async def device_relationships_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List relationships List all relationships based on device ID. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `DeviceRelationships_List`. + + Args: + device_id: Unique ID of the device. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2056,11 +2386,18 @@ async def device_relationships_list_async( query_params.append(f"application={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2073,23 +2410,32 @@ async def device_relationships_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def device_relationships_get_async( + def device_relationships_get( self, device_id: str, relationship_id: str, @@ -2105,6 +2451,23 @@ async def device_relationships_get_async( Get details about an existing device relationship by device ID and by relationship ID. + + Swagger operation ID: `DeviceRelationships_Get`. + + Args: + device_id: Unique ID of the device. + relationship_id: Unique ID of the device relationship. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2123,7 +2486,7 @@ async def device_relationships_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2137,6 +2500,7 @@ async def device_relationships_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2144,9 +2508,9 @@ async def device_relationships_get_async( return json.loads(response.text) - async def device_relationships_set_async( + def device_relationships_set( self, - input: DeviceRelationship, + input: DeviceRelationship | Mapping[str, Any], relationship_id: str, device_id: str, application: str, @@ -2161,6 +2525,25 @@ async def device_relationships_set_async( Create a new device relationship between the given device and a new device given a device ID and a relationship ID. + + Swagger operation ID: `DeviceRelationships_Set`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + relationship_id: Unique ID of the device relationship. + device_id: Unique ID of the device. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2179,7 +2562,7 @@ async def device_relationships_set_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -2193,6 +2576,7 @@ async def device_relationships_set_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2200,9 +2584,9 @@ async def device_relationships_set_async( return json.loads(response.text) - async def device_relationships_update_async( + def device_relationships_update( self, - input: DeviceRelationship, + input: DeviceRelationship | Mapping[str, Any], device_id: str, relationship_id: str, application: str, @@ -2217,6 +2601,25 @@ async def device_relationships_update_async( Update an existing device relationship between the given device and a new device given a device ID and a relationship ID. + + Swagger operation ID: `DeviceRelationships_Update`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + relationship_id: Unique ID of the device relationship. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2235,7 +2638,7 @@ async def device_relationships_update_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -2249,6 +2652,7 @@ async def device_relationships_update_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2256,7 +2660,7 @@ async def device_relationships_update_async( return json.loads(response.text) - async def device_relationships_remove_async( + def device_relationships_remove( self, device_id: str, relationship_id: str, @@ -2272,6 +2676,23 @@ async def device_relationships_remove_async( Delete an existing device relationship by device ID and relationship ID. + + Swagger operation ID: `DeviceRelationships_Remove`. + + Args: + device_id: Unique ID of the device. + relationship_id: Unique ID of the device relationship. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2290,7 +2711,7 @@ async def device_relationships_remove_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2304,9 +2725,10 @@ async def device_relationships_remove_async( request_url, response.status, response.text, + response=response, ) - async def jobs_list_async( + def list_jobs( self, application: str, *, @@ -2314,14 +2736,30 @@ async def jobs_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List jobs Get the list of jobs in an application. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Jobs_List`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/ga_2022_07_31/jobs" query_params = [] @@ -2331,11 +2769,18 @@ async def jobs_list_async( query_params.append(f"application={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2348,23 +2793,32 @@ async def jobs_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def jobs_get_async( + return ItemPaged(get_next, extract_data) + + def jobs_get( self, job_id: str, application: str, @@ -2378,6 +2832,22 @@ async def jobs_get_async( Get a job Get details about an existing job by ID. + + Swagger operation ID: `Jobs_Get`. + + Args: + job_id: Unique ID of the job. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2391,7 +2861,7 @@ async def jobs_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2405,6 +2875,7 @@ async def jobs_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2412,13 +2883,13 @@ async def jobs_get_async( return json.loads(response.text) - async def jobs_set_async( + def jobs_set( self, - input: Job, + input: Job | Mapping[str, Any], job_id: str, application: str, - job_type: Optional[str] = None, *, + job_type: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2428,6 +2899,25 @@ async def jobs_set_async( Create a job Create and execute a new job via its job definition. + + Swagger operation ID: `Jobs_Set`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + job_id: Unique ID of the job. + application: Unique ID of the application. + job_type: Type of the job. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2446,7 +2936,7 @@ async def jobs_set_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -2460,6 +2950,7 @@ async def jobs_set_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2467,7 +2958,7 @@ async def jobs_set_async( return json.loads(response.text) - async def jobs_get_devices_async( + def list_jobs_get_devices( self, job_id: str, application: str, @@ -2476,14 +2967,31 @@ async def jobs_get_devices_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get device statuses Get the list of individual device statuses by job ID. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Jobs_GetDevices`. + + Args: + job_id: Unique ID of the job. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2496,11 +3004,18 @@ async def jobs_get_devices_async( query_params.append(f"application={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2513,23 +3028,32 @@ async def jobs_get_devices_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def jobs_stop_async( + def jobs_stop( self, job_id: str, application: str, @@ -2543,6 +3067,22 @@ async def jobs_stop_async( Stop a running job Stop execution of a job that is currently running. + + Swagger operation ID: `Jobs_Stop`. + + Args: + job_id: Unique ID of the job. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2556,7 +3096,7 @@ async def jobs_stop_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -2570,9 +3110,10 @@ async def jobs_stop_async( request_url, response.status, response.text, + response=response, ) - async def jobs_resume_async( + def jobs_resume( self, job_id: str, application: str, @@ -2586,6 +3127,22 @@ async def jobs_resume_async( Resume a stopped job Resume execution of an existing stopped job. + + Swagger operation ID: `Jobs_Resume`. + + Args: + job_id: Unique ID of the job. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2599,7 +3156,7 @@ async def jobs_resume_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -2613,9 +3170,10 @@ async def jobs_resume_async( request_url, response.status, response.text, + response=response, ) - async def jobs_rerun_async( + def jobs_rerun( self, job_id: str, rerun_id: str, @@ -2630,6 +3188,23 @@ async def jobs_rerun_async( Resume a job on failed devices Execute a rerun of an existing job on all failed devices. + + Swagger operation ID: `Jobs_Rerun`. + + Args: + job_id: Unique ID of the job. + rerun_id: Unique ID of the rerun. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2648,7 +3223,7 @@ async def jobs_rerun_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -2662,6 +3237,7 @@ async def jobs_rerun_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2669,7 +3245,7 @@ async def jobs_rerun_async( return json.loads(response.text) - async def organizations_list_async( + def list_organizations( self, application: str, *, @@ -2677,14 +3253,30 @@ async def organizations_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List organizations Get the list of organizations in an application. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Organizations_List`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/api/ga_2022_07_31/organizations" @@ -2696,11 +3288,18 @@ async def organizations_list_async( query_params.append(f"application={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2713,23 +3312,32 @@ async def organizations_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def organizations_get_async( + def organizations_get( self, organization_id: str, application: str, @@ -2743,6 +3351,22 @@ async def organizations_get_async( Get an organization Get details about an existing organization by ID. + + Swagger operation ID: `Organizations_Get`. + + Args: + organization_id: Unique ID of the organization. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2759,7 +3383,7 @@ async def organizations_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2773,6 +3397,7 @@ async def organizations_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2780,9 +3405,9 @@ async def organizations_get_async( return json.loads(response.text) - async def organizations_set_async( + def organizations_set( self, - input: Organization, + input: Organization | Mapping[str, Any], organization_id: str, application: str, *, @@ -2795,6 +3420,24 @@ async def organizations_set_async( Create an organization Create a new organization. + + Swagger operation ID: `Organizations_Set`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + organization_id: Unique ID of the organization. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2811,7 +3454,7 @@ async def organizations_set_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -2825,6 +3468,7 @@ async def organizations_set_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2832,7 +3476,7 @@ async def organizations_set_async( return json.loads(response.text) - async def organizations_remove_async( + def organizations_remove( self, organization_id: str, application: str, @@ -2846,6 +3490,22 @@ async def organizations_remove_async( Delete organization Delete an existing organization by ID + + Swagger operation ID: `Organizations_Remove`. + + Args: + organization_id: Unique ID of the organization. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2862,7 +3522,7 @@ async def organizations_remove_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2876,9 +3536,10 @@ async def organizations_remove_async( request_url, response.status, response.text, + response=response, ) - async def scheduled_jobs_list_async( + def list_scheduled_jobs( self, application: str, *, @@ -2886,14 +3547,30 @@ async def scheduled_jobs_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List scheduled jobs Get the list of scheduled jobs in an application. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ScheduledJobs_List`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/api/ga_2022_07_31/scheduledJobs" @@ -2905,11 +3582,18 @@ async def scheduled_jobs_list_async( query_params.append(f"application={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2922,23 +3606,32 @@ async def scheduled_jobs_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def scheduled_jobs_get_async( + def scheduled_jobs_get( self, scheduled_job_id: str, application: str, @@ -2952,6 +3645,22 @@ async def scheduled_jobs_get_async( Get a scheduled job Get details about an existing scheduled job by ID. + + Swagger operation ID: `ScheduledJobs_Get`. + + Args: + scheduled_job_id: Unique ID of the scheduled job. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2968,7 +3677,7 @@ async def scheduled_jobs_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2982,6 +3691,7 @@ async def scheduled_jobs_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2989,14 +3699,14 @@ async def scheduled_jobs_get_async( return json.loads(response.text) - async def scheduled_jobs_set_async( + def scheduled_jobs_set( self, - input: ScheduledJob, + input: ScheduledJob | Mapping[str, Any], scheduled_job_id: str, application: str, + *, job_type: Optional[str] = None, scheduled_job_end_type: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3006,6 +3716,27 @@ async def scheduled_jobs_set_async( Create a scheduled job Create and execute a new scheduled job via its job definition. + + Swagger operation ID: `ScheduledJobs_Set`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + scheduled_job_id: Unique ID of the scheduled job. + application: Unique ID of the application. + job_type: Type of the job. + scheduled_job_end_type: How the scheduled job should end (not + applied to device template migrations). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3032,7 +3763,7 @@ async def scheduled_jobs_set_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -3046,6 +3777,7 @@ async def scheduled_jobs_set_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3053,13 +3785,13 @@ async def scheduled_jobs_set_async( return json.loads(response.text) - async def scheduled_jobs_update_async( + def scheduled_jobs_update( self, - input: ScheduledJobPatch, + input: ScheduledJobPatch | Mapping[str, Any], scheduled_job_id: str, application: str, - scheduled_job_end_type: Optional[str] = None, *, + scheduled_job_end_type: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3069,6 +3801,26 @@ async def scheduled_jobs_update_async( Update a scheduled job Update an existing scheduled job by ID. + + Swagger operation ID: `ScheduledJobs_Update`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + scheduled_job_id: Unique ID of the scheduled job. + application: Unique ID of the application. + scheduled_job_end_type: How the scheduled job should end (not + applied to device template migrations). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3090,7 +3842,7 @@ async def scheduled_jobs_update_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -3104,6 +3856,7 @@ async def scheduled_jobs_update_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3111,7 +3864,7 @@ async def scheduled_jobs_update_async( return json.loads(response.text) - async def scheduled_jobs_remove_async( + def scheduled_jobs_remove( self, scheduled_job_id: str, application: str, @@ -3125,6 +3878,22 @@ async def scheduled_jobs_remove_async( Delete a scheduled job Delete an existing scheduled job by ID. + + Swagger operation ID: `ScheduledJobs_Remove`. + + Args: + scheduled_job_id: Unique ID of the scheduled job. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3141,7 +3910,7 @@ async def scheduled_jobs_remove_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -3155,9 +3924,10 @@ async def scheduled_jobs_remove_async( request_url, response.status, response.text, + response=response, ) - async def scheduled_jobs_list_jobs_async( + def list_scheduled_jobs_list_jobs( self, scheduled_job_id: str, application: str, @@ -3166,14 +3936,31 @@ async def scheduled_jobs_list_jobs_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get jobs by scheduled job ID Get the list of jobs for a scheduled job definition. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ScheduledJobs_ListJobs`. + + Args: + scheduled_job_id: Unique ID of the scheduled job. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3190,11 +3977,18 @@ async def scheduled_jobs_list_jobs_async( query_params.append(f"application={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -3207,23 +4001,32 @@ async def scheduled_jobs_list_jobs_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def devices_get_async( + return ItemPaged(get_next, extract_data) + + def devices_get( self, device_id: str, application: str, @@ -3237,6 +4040,22 @@ async def devices_get_async( Get a device by ID Get details about an existing device by device ID. + + Swagger operation ID: `Devices_Get_V1`. + + Args: + device_id: Unique ID of the device. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3250,7 +4069,7 @@ async def devices_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3264,6 +4083,7 @@ async def devices_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3271,13 +4091,13 @@ async def devices_get_async( return json.loads(response.text) - async def devices_get_command_response_async( + def devices_get_command_response( self, device_id: str, command_name: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3287,6 +4107,24 @@ async def devices_get_command_response_async( Get device command response Get the last response for a device command. + + Swagger operation ID: `Devices_GetCommandResponse_V1`. + + Args: + device_id: Unique ID of the device. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3310,7 +4148,7 @@ async def devices_get_command_response_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3324,6 +4162,7 @@ async def devices_get_command_response_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3331,14 +4170,14 @@ async def devices_get_command_response_async( return json.loads(response.text) - async def devices_get_component_command_response_async( + def devices_get_component_command_response( self, device_id: str, component_name: str, command_name: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3348,6 +4187,25 @@ async def devices_get_component_command_response_async( Get component command response Get the last response for a device component command. + + Swagger operation ID: `Devices_GetComponentCommandResponse_V1`. + + Args: + device_id: Unique ID of the device. + component_name: Name of the device component. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3373,7 +4231,7 @@ async def devices_get_component_command_response_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3387,6 +4245,7 @@ async def devices_get_component_command_response_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3394,14 +4253,14 @@ async def devices_get_component_command_response_async( return json.loads(response.text) - async def devices_get_component_telemetry_value_async( + def devices_get_component_telemetry_value( self, device_id: str, component_name: str, telemetry_name: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3411,6 +4270,25 @@ async def devices_get_component_telemetry_value_async( Get component telemetry value Get the last telemetry value from a component. + + Swagger operation ID: `Devices_GetComponentTelemetryValue_V1`. + + Args: + device_id: Unique ID of the device. + component_name: Name of the device component. + telemetry_name: Name of this device telemetry. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3436,7 +4314,7 @@ async def devices_get_component_telemetry_value_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3450,6 +4328,7 @@ async def devices_get_component_telemetry_value_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3457,14 +4336,14 @@ async def devices_get_component_telemetry_value_async( return json.loads(response.text) - async def devices_get_module_command_response_async( + def devices_get_module_command_response( self, device_id: str, module: str, command_name: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3474,6 +4353,25 @@ async def devices_get_module_command_response_async( Get module command response Get the last response for a device module command + + Swagger operation ID: `Devices_GetModuleCommandResponse_V1`. + + Args: + device_id: Unique ID of the device. + module: Name of the device module. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3499,7 +4397,7 @@ async def devices_get_module_command_response_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3513,6 +4411,7 @@ async def devices_get_module_command_response_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3520,15 +4419,15 @@ async def devices_get_module_command_response_async( return json.loads(response.text) - async def devices_get_module_component_command_response_async( + def devices_get_module_component_command_response( self, device_id: str, module: str, component_name: str, command_name: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3538,6 +4437,26 @@ async def devices_get_module_component_command_response_async( Get module component command response Get the last response for a module component command. + + Swagger operation ID: `Devices_GetModuleComponentCommandResponse_V1`. + + Args: + device_id: Unique ID of the device. + module: Name of the device module. + component_name: Name of the device component. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3565,7 +4484,7 @@ async def devices_get_module_component_command_response_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3579,6 +4498,7 @@ async def devices_get_module_component_command_response_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3586,15 +4506,15 @@ async def devices_get_module_component_command_response_async( return json.loads(response.text) - async def devices_get_module_component_telemetry_value_async( + def devices_get_module_component_telemetry_value( self, device_id: str, module: str, component_name: str, telemetry_name: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3604,6 +4524,26 @@ async def devices_get_module_component_telemetry_value_async( Get module component telemetry value Get the last telemetry value from a module component. + + Swagger operation ID: `Devices_GetModuleComponentTelemetryValue_V1`. + + Args: + device_id: Unique ID of the device. + module: Name of the device module. + component_name: Name of the device component. + telemetry_name: Name of this device telemetry. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3631,7 +4571,7 @@ async def devices_get_module_component_telemetry_value_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3645,6 +4585,7 @@ async def devices_get_module_component_telemetry_value_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3652,13 +4593,13 @@ async def devices_get_module_component_telemetry_value_async( return json.loads(response.text) - async def devices_get_module_properties_async( + def devices_get_module_properties( self, device_id: str, module: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3668,6 +4609,24 @@ async def devices_get_module_properties_async( Get module properties Get all property values of a module. + + Swagger operation ID: `Devices_GetModuleProperties_V1`. + + Args: + device_id: Unique ID of the device. + module: Name of the device module. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3692,7 +4651,7 @@ async def devices_get_module_properties_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3706,6 +4665,7 @@ async def devices_get_module_properties_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3713,14 +4673,14 @@ async def devices_get_module_properties_async( return json.loads(response.text) - async def devices_get_module_telemetry_value_async( + def devices_get_module_telemetry_value( self, device_id: str, module: str, telemetry_name: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3730,7 +4690,26 @@ async def devices_get_module_telemetry_value_async( Get module telemetry value Get the last telemetry value from a module. - """ + + Swagger operation ID: `Devices_GetModuleTelemetryValue_V1`. + + Args: + device_id: Unique ID of the device. + module: Name of the device module. + telemetry_name: Name of this device telemetry. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ request_url = ( f"{self._connection_runtime_url}" f"/api" @@ -3755,7 +4734,7 @@ async def devices_get_module_telemetry_value_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3769,6 +4748,7 @@ async def devices_get_module_telemetry_value_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3776,12 +4756,12 @@ async def devices_get_module_telemetry_value_async( return json.loads(response.text) - async def devices_get_properties_async( + def devices_get_properties( self, device_id: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3791,6 +4771,23 @@ async def devices_get_properties_async( Get device properties Get all property values of a device by device ID. + + Swagger operation ID: `Devices_GetProperties_V1`. + + Args: + device_id: Unique ID of the device. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3809,7 +4806,7 @@ async def devices_get_properties_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3823,6 +4820,7 @@ async def devices_get_properties_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3830,13 +4828,13 @@ async def devices_get_properties_async( return json.loads(response.text) - async def devices_get_telemetry_value_async( + def devices_get_telemetry_value( self, device_id: str, telemetry_name: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3846,6 +4844,24 @@ async def devices_get_telemetry_value_async( Get device telemetry value Get the last telemetry value from a device. + + Swagger operation ID: `Devices_GetTelemetryValue_V1`. + + Args: + device_id: Unique ID of the device. + telemetry_name: Name of this device telemetry. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3869,7 +4885,7 @@ async def devices_get_telemetry_value_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3883,6 +4899,7 @@ async def devices_get_telemetry_value_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3890,7 +4907,7 @@ async def devices_get_telemetry_value_async( return json.loads(response.text) - async def devices_list_async( + def list_devices( self, application: str, *, @@ -3898,14 +4915,30 @@ async def devices_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List devices Get the list of devices in an application. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Devices_List_V1`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/v1/devices" query_params = [] @@ -3915,11 +4948,18 @@ async def devices_list_async( query_params.append(f"application={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -3932,23 +4972,32 @@ async def devices_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def devices_remove_async( + def devices_remove( self, device_id: str, application: str, @@ -3962,6 +5011,22 @@ async def devices_remove_async( Delete a device Delete an existing device by device ID. + + Swagger operation ID: `Devices_Remove_V1`. + + Args: + device_id: Unique ID of the device. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3975,7 +5040,7 @@ async def devices_remove_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -3989,16 +5054,17 @@ async def devices_remove_async( request_url, response.status, response.text, + response=response, ) - async def devices_run_command_async( + def devices_run_command( self, - input: DeviceCommandV1, + input: DeviceCommandV1 | Mapping[str, Any], device_id: str, command_name: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4008,6 +5074,26 @@ async def devices_run_command_async( Run a device command Run a command on a device. + + Swagger operation ID: `Devices_RunCommand_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4031,7 +5117,7 @@ async def devices_run_command_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4045,6 +5131,7 @@ async def devices_run_command_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4052,15 +5139,15 @@ async def devices_run_command_async( return json.loads(response.text) - async def devices_run_component_command_async( + def devices_run_component_command( self, - input: DeviceComponentCommand, + input: DeviceComponentCommand | Mapping[str, Any], device_id: str, component_name: str, command_name: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4070,6 +5157,27 @@ async def devices_run_component_command_async( Run a component command Run a command on a component. + + Swagger operation ID: `Devices_RunComponentCommand_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + component_name: Name of the device component. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4095,7 +5203,7 @@ async def devices_run_component_command_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4109,6 +5217,7 @@ async def devices_run_component_command_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4116,15 +5225,15 @@ async def devices_run_component_command_async( return json.loads(response.text) - async def devices_run_module_command_async( + def devices_run_module_command( self, - input: DeviceModuleCommand, + input: DeviceModuleCommand | Mapping[str, Any], device_id: str, module: str, command_name: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4134,6 +5243,27 @@ async def devices_run_module_command_async( Run a module command Run a command on a module. + + Swagger operation ID: `Devices_RunModuleCommand_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + module: Name of the device module. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4159,7 +5289,7 @@ async def devices_run_module_command_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4173,6 +5303,7 @@ async def devices_run_module_command_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4180,16 +5311,16 @@ async def devices_run_module_command_async( return json.loads(response.text) - async def devices_run_module_component_command_async( + def devices_run_module_component_command( self, - input: DeviceModuleComponentCommand, + input: DeviceModuleComponentCommand | Mapping[str, Any], device_id: str, module: str, component_name: str, command_name: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4199,6 +5330,28 @@ async def devices_run_module_component_command_async( Run a module component command Run a command on a module component. + + Swagger operation ID: `Devices_RunModuleComponentCommand_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + module: Name of the device module. + component_name: Name of the device component. + command_name: Name of this device command. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4226,7 +5379,7 @@ async def devices_run_module_component_command_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4240,6 +5393,7 @@ async def devices_run_module_component_command_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4247,9 +5401,9 @@ async def devices_run_module_component_command_async( return json.loads(response.text) - async def devices_set_async( + def devices_set( self, - input: DeviceV2, + input: DeviceV2 | Mapping[str, Any], device_id: str, application: str, *, @@ -4262,6 +5416,24 @@ async def devices_set_async( Create or update a device Create a new device or update an existing one by device ID. + + Swagger operation ID: `Devices_Set_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4275,7 +5447,7 @@ async def devices_set_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -4289,6 +5461,7 @@ async def devices_set_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4296,14 +5469,14 @@ async def devices_set_async( return json.loads(response.text) - async def devices_update_module_properties_async( + def devices_update_module_properties( self, - input: ModuleProperties, + input: ModuleProperties | Mapping[str, Any], device_id: str, module: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4313,6 +5486,26 @@ async def devices_update_module_properties_async( Update module properties Update all property values of a module. + + Swagger operation ID: `Devices_UpdateModuleProperties_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + module: Name of the device module. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4337,7 +5530,7 @@ async def devices_update_module_properties_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -4351,6 +5544,7 @@ async def devices_update_module_properties_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4358,13 +5552,13 @@ async def devices_update_module_properties_async( return json.loads(response.text) - async def devices_update_properties_async( + def devices_update_properties( self, - input: DeviceProperties, + input: DeviceProperties | Mapping[str, Any], device_id: str, application: str, - template: Optional[str] = None, *, + template: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4374,6 +5568,25 @@ async def devices_update_properties_async( Update device properties Update all property values of a device by device ID. + + Swagger operation ID: `Devices_UpdateProperties_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + device_id: Unique ID of the device. + application: Unique ID of the application. + template: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4392,7 +5605,7 @@ async def devices_update_properties_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -4406,6 +5619,7 @@ async def devices_update_properties_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4413,7 +5627,7 @@ async def devices_update_properties_async( return json.loads(response.text) - async def device_templates_get_async( + def device_templates_get( self, template_id: str, application: str, @@ -4427,6 +5641,22 @@ async def device_templates_get_async( Get a device template by ID Get details about an existing device template by ID. + + Swagger operation ID: `DeviceTemplates_Get_V1`. + + Args: + template_id: Unique ID of the template. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4440,7 +5670,7 @@ async def device_templates_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4454,6 +5684,7 @@ async def device_templates_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4461,7 +5692,7 @@ async def device_templates_get_async( return json.loads(response.text) - async def device_templates_list_async( + def list_device_templates( self, application: str, *, @@ -4469,14 +5700,30 @@ async def device_templates_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List device templates Get the list of device templates in an application. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `DeviceTemplates_List_V1`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/v1/deviceTemplates" query_params = [] @@ -4486,11 +5733,18 @@ async def device_templates_list_async( query_params.append(f"application={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -4503,23 +5757,32 @@ async def device_templates_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def device_templates_remove_async( + def device_templates_remove( self, template_id: str, application: str, @@ -4533,6 +5796,22 @@ async def device_templates_remove_async( Delete a device template Delete an existing device template by ID. + + Swagger operation ID: `DeviceTemplates_Remove_V1`. + + Args: + template_id: Unique ID of the template. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4546,7 +5825,7 @@ async def device_templates_remove_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -4560,9 +5839,10 @@ async def device_templates_remove_async( request_url, response.status, response.text, + response=response, ) - async def roles_get_async( + def roles_get( self, role_id: str, application: str, @@ -4576,6 +5856,22 @@ async def roles_get_async( Get role Get a role by ID. + + Swagger operation ID: `Roles_Get_V1`. + + Args: + role_id: Unique ID for the role. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4589,7 +5885,7 @@ async def roles_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4603,6 +5899,7 @@ async def roles_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4610,7 +5907,7 @@ async def roles_get_async( return json.loads(response.text) - async def roles_list_async( + def list_roles( self, application: str, *, @@ -4618,11 +5915,30 @@ async def roles_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List roles Get the list of roles in an application. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Roles_List_V1`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/v1/roles" query_params = [] @@ -4632,35 +5948,56 @@ async def roles_list_async( query_params.append(f"application={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def users_create_async( + return ItemPaged(get_next, extract_data) + + def users_create( self, - input: User, + input: User | Mapping[str, Any], user_id: str, application: str, - user_type: Optional[str] = None, *, + user_type: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4670,6 +6007,25 @@ async def users_create_async( Create user Create a user in the application + + Swagger operation ID: `Users_Create_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + user_id: Unique ID of the user. + application: Unique ID of the application. + user_type: Type of the user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4688,7 +6044,7 @@ async def users_create_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -4702,6 +6058,7 @@ async def users_create_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4709,7 +6066,7 @@ async def users_create_async( return json.loads(response.text) - async def users_get_async( + def users_get( self, user_id: str, application: str, @@ -4723,6 +6080,22 @@ async def users_get_async( Get user Get a user by ID + + Swagger operation ID: `Users_Get_V1`. + + Args: + user_id: Unique ID of the user. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4736,7 +6109,7 @@ async def users_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4750,6 +6123,7 @@ async def users_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4757,7 +6131,7 @@ async def users_get_async( return json.loads(response.text) - async def users_list_async( + def list_users( self, application: str, *, @@ -4765,11 +6139,30 @@ async def users_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List users Get the list of users in an application + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Users_List_V1`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/v1/users" query_params = [] @@ -4779,29 +6172,50 @@ async def users_list_async( query_params.append(f"application={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def users_remove_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def users_remove( self, user_id: str, application: str, @@ -4815,6 +6229,22 @@ async def users_remove_async( Delete user Delete a user + + Swagger operation ID: `Users_Remove_V1`. + + Args: + user_id: Unique ID of the user. + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4828,7 +6258,7 @@ async def users_remove_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -4842,15 +6272,16 @@ async def users_remove_async( request_url, response.status, response.text, + response=response, ) - async def users_update_async( + def users_update( self, - input: UserPatch, + input: UserPatch | Mapping[str, Any], user_id: str, application: str, - user_type: Optional[str] = None, *, + user_type: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4860,6 +6291,25 @@ async def users_update_async( Update user Update a user in the application via patch + + Swagger operation ID: `Users_Update_V1`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + user_id: Unique ID of the user. + application: Unique ID of the application. + user_type: Type of the user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4878,7 +6328,7 @@ async def users_update_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -4892,6 +6342,7 @@ async def users_update_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4899,28 +6350,50 @@ async def users_update_async( return json.loads(response.text) - async def applications_list_async( + def list_applications( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get the list of applications accessible to the signed-in user - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Applications_List`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/api/preview/applications" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -4933,23 +6406,32 @@ async def applications_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def device_templates_list_2_async( + return ItemPaged(get_next, extract_data) + + def list_device_templates_2( self, application: str, *, @@ -4957,14 +6439,30 @@ async def device_templates_list_2_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List device templates Get the list of device templates in an application. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `DeviceTemplates_List`. + + Args: + application: Unique ID of the application. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/api/preview/deviceTemplates" @@ -4976,11 +6474,18 @@ async def device_templates_list_2_async( query_params.append(f"application={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -4993,35 +6498,65 @@ async def device_templates_list_2_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def workflow_get_components_async( + return ItemPaged(get_next, extract_data) + + def list_workflow_get_components( self, application: str, template: str, - module: Optional[str] = None, *, + module: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Workflow_GetComponents + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Workflow_GetComponents`. + + Args: + application: Unique ID of the application. + template: template. + module: module. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5043,43 +6578,87 @@ async def workflow_get_components_async( query_params.append(f"module={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def workflow_get_capabilities_async( + def list_workflow_get_capabilities( self, application: str, template: str, + *, component: Optional[str] = None, module: Optional[str] = None, type_: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Workflow_GetCapabilities + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Workflow_GetCapabilities`. + + Args: + application: Unique ID of the application. + template: template. + component: component. + module: module. + type_: type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5111,43 +6690,87 @@ async def workflow_get_capabilities_async( query_params.append(f"type={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - async def workflow_get_capabilities_v1_async( + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_workflow_get_capabilities_v1( self, application: str, template: str, + *, component: Optional[str] = None, module: Optional[str] = None, type_: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Workflow_GetCapabilities_V1 + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Workflow_GetCapabilities_V1`. + + Args: + application: Unique ID of the application. + template: template. + component: component. + module: module. + type_: type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5179,41 +6802,83 @@ async def workflow_get_capabilities_v1_async( query_params.append(f"type={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def workflow_get_components_v1_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_workflow_get_components_v1( self, application: str, template: str, - module: Optional[str] = None, *, + module: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Workflow_GetComponents_V1 + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Workflow_GetComponents_V1`. + + Args: + application: Unique ID of the application. + template: template. + module: module. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5235,29 +6900,50 @@ async def workflow_get_components_v1_async( query_params.append(f"module={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - async def workflow_get_modules_async( + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_workflow_get_modules( self, application: str, template: str, @@ -5266,9 +6952,29 @@ async def workflow_get_modules_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Workflow_GetModules + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Workflow_GetModules_V1`. + + Args: + application: Unique ID of the application. + template: template. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/api/v1/_internal/workflow/modules" @@ -5284,33 +6990,54 @@ async def workflow_get_modules_async( query_params.append(f"template={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def schema_device_cloud_properties_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def schema_device_cloud_properties( self, application: str, - instance_of: Optional[str] = None, *, + instance_of: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5318,6 +7045,22 @@ async def schema_device_cloud_properties_async( ) -> dict[str, Any] | None: """ Schema_DeviceCloudProperties + + Swagger operation ID: `Schema_DeviceCloudProperties`. + + Args: + application: Unique ID of the application. + instance_of: The device template definition for the device. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5336,7 +7079,7 @@ async def schema_device_cloud_properties_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5350,6 +7093,7 @@ async def schema_device_cloud_properties_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5357,13 +7101,13 @@ async def schema_device_cloud_properties_async( return json.loads(response.text) - async def schema_device_command_async( + def schema_device_command( self, application: str, + *, instance_of: Optional[str] = None, component: Optional[str] = None, capability: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5371,6 +7115,24 @@ async def schema_device_command_async( ) -> dict[str, Any] | None: """ Schema_DeviceCommand + + Swagger operation ID: `Schema_DeviceCommand`. + + Args: + application: Unique ID of the application. + instance_of: The device template definition for the device. + component: component. + capability: capability. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5399,7 +7161,7 @@ async def schema_device_command_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5413,6 +7175,7 @@ async def schema_device_command_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5420,14 +7183,14 @@ async def schema_device_command_async( return json.loads(response.text) - async def schema_device_command_v1_async( + def schema_device_command_v1( self, application: str, + *, template: Optional[str] = None, module: Optional[str] = None, component: Optional[str] = None, capability: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5435,6 +7198,25 @@ async def schema_device_command_v1_async( ) -> dict[str, Any] | None: """ Schema_DeviceCommand_V1 + + Swagger operation ID: `Schema_DeviceCommand_V1`. + + Args: + application: Unique ID of the application. + template: The device template definition for the device. + module: module. + component: component. + capability: capability. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5468,7 +7250,7 @@ async def schema_device_command_v1_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5482,6 +7264,7 @@ async def schema_device_command_v1_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5489,12 +7272,12 @@ async def schema_device_command_v1_async( return json.loads(response.text) - async def schema_device_properties_async( + def schema_device_properties( self, application: str, + *, template: Optional[str] = None, module: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5502,6 +7285,23 @@ async def schema_device_properties_async( ) -> dict[str, Any] | None: """ Schema_DeviceProperties + + Swagger operation ID: `Schema_DeviceProperties_V1`. + + Args: + application: Unique ID of the application. + template: The device template definition for the device. + module: module. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5525,7 +7325,7 @@ async def schema_device_properties_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5539,6 +7339,7 @@ async def schema_device_properties_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5546,14 +7347,14 @@ async def schema_device_properties_async( return json.loads(response.text) - async def schema_device_telemetry_async( + def schema_device_telemetry( self, application: str, + *, template: Optional[str] = None, module: Optional[str] = None, component: Optional[str] = None, capability: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5561,6 +7362,25 @@ async def schema_device_telemetry_async( ) -> dict[str, Any] | None: """ Schema_DeviceTelemetry + + Swagger operation ID: `Schema_DeviceTelemetry_V1`. + + Args: + application: Unique ID of the application. + template: The device template definition for the device. + module: module. + component: component. + capability: capability. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5594,7 +7414,7 @@ async def schema_device_telemetry_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5608,6 +7428,7 @@ async def schema_device_telemetry_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5615,11 +7436,11 @@ async def schema_device_telemetry_async( return json.loads(response.text) - async def schema_job_async( + def schema_job( self, application: str, - job_type: Optional[str] = None, *, + job_type: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5627,6 +7448,22 @@ async def schema_job_async( ) -> dict[str, Any] | None: """ Schema_Job + + Swagger operation ID: `Schema_Job`. + + Args: + application: Unique ID of the application. + job_type: job_type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5645,7 +7482,7 @@ async def schema_job_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5659,6 +7496,7 @@ async def schema_job_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5666,13 +7504,13 @@ async def schema_job_async( return json.loads(response.text) - async def schema_scheduled_job_async( + def schema_scheduled_job( self, application: str, + *, scheduled_job_end_type: Optional[str] = None, job_type: Optional[str] = None, patch: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5680,6 +7518,24 @@ async def schema_scheduled_job_async( ) -> dict[str, Any] | None: """ Schema_ScheduledJob + + Swagger operation ID: `Schema_ScheduledJob`. + + Args: + application: Unique ID of the application. + scheduled_job_end_type: scheduled_job_end_type. + job_type: job_type. + patch: patch. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5708,7 +7564,7 @@ async def schema_scheduled_job_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5722,6 +7578,7 @@ async def schema_scheduled_job_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5729,12 +7586,12 @@ async def schema_scheduled_job_async( return json.loads(response.text) - async def schema_user_async( + def schema_user( self, application: str, + *, user_type: Optional[str] = None, patch: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5742,6 +7599,23 @@ async def schema_user_async( ) -> dict[str, Any] | None: """ Schema_User + + Swagger operation ID: `Schema_User_V1`. + + Args: + application: Unique ID of the application. + user_type: user_type. + patch: patch. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5765,7 +7639,7 @@ async def schema_user_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5779,6 +7653,7 @@ async def schema_user_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5786,11 +7661,11 @@ async def schema_user_async( return json.loads(response.text) - async def schema_webhook_action_body_async( + def schema_webhook_action_body( self, application: str, - rule: Optional[str] = None, *, + rule: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5798,6 +7673,22 @@ async def schema_webhook_action_body_async( ) -> None: """ Schema_WebhookActionBody + + Swagger operation ID: `Schema_WebhookActionBody`. + + Args: + application: Unique ID of the application. + rule: rule. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5816,7 +7707,7 @@ async def schema_webhook_action_body_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5830,6 +7721,7 @@ async def schema_webhook_action_body_async( request_url, response.status, response.text, + response=response, ) diff --git a/src/azure/connectors/azuremonitorlogs.py b/src/azure/connectors/azuremonitorlogs.py index 7da1740..137afaa 100644 --- a/src/azure/connectors/azuremonitorlogs.py +++ b/src/azure/connectors/azuremonitorlogs.py @@ -5,21 +5,43 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "AzuremonitorlogsClient", + "ObjectEntity", + "PartialQueryError", + "QueryDataInput", + "QuerySchemaInput", + "ResourceGroup", + "ResourceGroupListResult", + "ResourceItem", + "ResourceItemListResult", + "Row", + "Subscription", + "SubscriptionListResult", + "Table", + "TimeRangeItem", + "TimeRangeListResult", + "TimeRangeTypesListResult", + "VisualizeQueryInput", + "VisualizeResults", +] + # Type Definitions @@ -29,11 +51,11 @@ class QueryDataInput: Run query and list results """ - query: Optional[str] = None + query: str """Specify the query you would like to run. """ - timerangetype: Optional[str] = None + timerangetype: str """Select Time Range type. """ - timerange: Optional[Dict[str, Any]] = None + timerange: Dict[str, Any] """Time Range""" @@ -43,8 +65,18 @@ class Table: Response for Run query and list results """ - value: Optional[List[Row]] = None - error: Optional[PartialQueryError] = None + value: Optional[ + List[Row | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + error: Optional[ + PartialQueryError | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -53,11 +85,11 @@ class VisualizeQueryInput: Run query and visualize results """ - query: Optional[str] = None + query: str """Specify the query you would like to run. """ - timerangetype: Optional[str] = None + timerangetype: str """Select Time Range type. """ - timerange: Optional[Dict[str, Any]] = None + timerange: Dict[str, Any] """Time Range""" @@ -67,16 +99,23 @@ class VisualizeResults: Response for Run query and visualize results """ - body: Optional[str] = None - attachment_content: Optional[str] = field( + body: Optional[str] = dataclass_field(default=None, kw_only=True) + attachment_content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "attachmentContent"}, ) - attachment_name: Optional[str] = field( + attachment_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "attachmentName"}, ) - error: Optional[PartialQueryError] = None + error: Optional[ + PartialQueryError | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -85,10 +124,16 @@ class SubscriptionListResult: Response for List subscriptions """ - value: Optional[List[Subscription]] = None + value: Optional[ + List[Subscription | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The subscriptions .""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results. """ @@ -100,10 +145,16 @@ class ResourceGroupListResult: Response for List resource groups """ - value: Optional[List[ResourceGroup]] = None + value: Optional[ + List[ResourceGroup | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of resource groups. """ - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results. """ @@ -115,10 +166,16 @@ class ResourceItemListResult: Response for List resources """ - value: Optional[List[ResourceItem]] = None + value: Optional[ + List[ResourceItem | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of resource items. """ - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results. """ @@ -133,7 +190,7 @@ class ObjectEntity: Response for Get query schema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -146,7 +203,7 @@ class Row: Definition: Row """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -159,7 +216,7 @@ class PartialQueryError: Definition: PartialQueryError """ - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -168,18 +225,20 @@ class Subscription: Definition: Subscription """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ The fully qualified Id. For example, /subscriptions/00000000-0000-0000-0000-000000000000. """ - subscription_id: Optional[str] = field( + subscription_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "subscriptionId"}, ) """The subscription Id. """ - authorization_source: Optional[str] = field( + authorization_source: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "authorizationSource"}, ) """ @@ -195,11 +254,11 @@ class ResourceGroup: Definition: ResourceGroup """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ The ID of the resource group (e.g. /subscriptions/XXX/resourceGroups/YYY). """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The Name of the resource group. """ @@ -209,9 +268,9 @@ class ResourceItem: Definition: ResourceItem """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the resource. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The Name of the resource .""" @@ -221,10 +280,16 @@ class TimeRangeTypesListResult: Definition: TimeRangeTypesListResult """ - value: Optional[List[TimeRangeItem]] = None + value: Optional[ + List[TimeRangeItem | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of time range types (Relative\\Absolute\\SetInQuery). """ - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results. """ @@ -236,10 +301,16 @@ class TimeRangeListResult: Definition: TimeRangeListResult """ - value: Optional[List[TimeRangeItem]] = None + value: Optional[ + List[TimeRangeItem | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of time range. """ - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results. """ @@ -251,9 +322,9 @@ class TimeRangeItem: Definition: TimeRangeItem """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The ID of the item. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The Name of the item. """ @@ -265,16 +336,16 @@ class AzuremonitorlogsClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -285,8 +356,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -294,8 +365,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -307,7 +378,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -329,7 +400,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -361,9 +432,9 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def query_data_async( + def query_data( self, - input: QueryDataInput, + input: QueryDataInput | Mapping[str, Any], subscriptions: str, resourcegroups: str, resourcetype: str, @@ -379,6 +450,26 @@ async def query_data_async( Returns each row as its own object. Use this action when you want to work with each row separately in the rest of the workflow. + + Swagger operation ID: `QueryDataV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscriptions: Select subscription. + resourcegroups: Select resource group. + resourcetype: Select Resource Type. + resourcename: Select Resource. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/queryDataV2" query_params = [] @@ -401,7 +492,7 @@ async def query_data_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -415,6 +506,7 @@ async def query_data_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -422,9 +514,9 @@ async def query_data_async( return json.loads(response.text) - async def visualize_query_async( + def visualize_query( self, - input: VisualizeQueryInput, + input: VisualizeQueryInput | Mapping[str, Any], subscriptions: str, resourcegroups: str, resourcetype: str, @@ -442,6 +534,27 @@ async def visualize_query_async( Returns all rows in the result set as a single formatted object. Use this action when you want to use the result set together in the rest of the workflow. + + Swagger operation ID: `VisualizeQueryV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + subscriptions: Select subscription. + resourcegroups: Select resource group. + resourcetype: Select Resource Type. + resourcename: Select Resource. + vis_type: Specify the resulting chart type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/visualizeQueryV2" query_params = [] @@ -468,7 +581,7 @@ async def visualize_query_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -482,6 +595,7 @@ async def visualize_query_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -489,28 +603,50 @@ async def visualize_query_async( return json.loads(response.text) - async def list_subscriptions_async( + def list_subscriptions( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List subscriptions Gets a list of all the subscriptions to which the principal has access. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListSubscriptions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/listSubscriptions" + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -523,23 +659,32 @@ async def list_subscriptions_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def list_resource_groups_async( + return ItemPaged(get_next, extract_data) + + def list_resource_groups( self, subscriptions: str, *, @@ -547,14 +692,30 @@ async def list_resource_groups_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List resource groups Lists all the resource groups within the subscription. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListResourceGroups`. + + Args: + subscriptions: Select subscription. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/listResourceGroups" query_params = [] @@ -564,11 +725,18 @@ async def list_resource_groups_async( query_params.append(f"subscriptions={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -581,23 +749,32 @@ async def list_resource_groups_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def list_resources_async( + return ItemPaged(get_next, extract_data) + + def list_resources( self, subscriptions: str, resourcegroups: str, @@ -607,14 +784,32 @@ async def list_resources_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List resources Lists all the resource groups within the resource group. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListResources`. + + Args: + subscriptions: Select subscription. + resourcegroups: Select resource group. + resourcetype: Select Resource Type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/listResources" query_params = [] @@ -632,11 +827,18 @@ async def list_resources_async( query_params.append(f"resourcetype={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -649,23 +851,32 @@ async def list_resources_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def query_schema_async( + return ItemPaged(get_next, extract_data) + + def query_schema( self, input: QuerySchemaInput, subscriptions: str, @@ -682,6 +893,25 @@ async def query_schema_async( Get query schema Gets the schema for a specific query. + + Swagger operation ID: `QuerySchemaV2`. + + Args: + input: The request body. + subscriptions: Select subscription. + resourcegroups: Select resource group. + resourcetype: Select Resource Type. + resourcename: Select Resource. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/querySchemaV2" query_params = [] @@ -704,7 +934,7 @@ async def query_schema_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -718,6 +948,7 @@ async def query_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -725,7 +956,7 @@ async def query_schema_async( return json.loads(response.text) - async def get_time_range_selection_control_async( + def get_time_range_selection_control( self, timerangetype: str, *, @@ -738,6 +969,21 @@ async def get_time_range_selection_control_async( Returns the control schema according to to the given time range type Returns the Relative\\Absolute\\Set in query time range control. + + Swagger operation ID: `getTimeRangeSelectionControl`. + + Args: + timerangetype: The Time Range type that the control represents. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/getTimeRangeSelectionControl" @@ -750,7 +996,7 @@ async def get_time_range_selection_control_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -764,6 +1010,7 @@ async def get_time_range_selection_control_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/azurequeues.py b/src/azure/connectors/azurequeues.py index 3ac187e..512373f 100644 --- a/src/azure/connectors/azurequeues.py +++ b/src/azure/connectors/azurequeues.py @@ -5,21 +5,36 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "AzurequeuesClient", + "MessagePost", + "Messages", + "PutMessageInput", + "QueueArray", + "QueueInfo", + "QueueMessage", + "QueueMessagesList", + "StorageAccount", + "StorageAccountList", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,13 +44,14 @@ class Messages: Response for Get messages """ - queue_messages_list: Optional[QueueMessagesList] = field( + queue_messages_list: Optional[QueueMessagesList | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "QueueMessagesList"}, ) -QueueArray = List["QueueInfo"] +QueueArray = List["QueueInfo | Mapping[str, Any]"] PutMessageInput = str @@ -47,7 +63,12 @@ class StorageAccountList: Response for Get storage accounts """ - value: Optional[List[StorageAccount]] = None + value: Optional[ + List[StorageAccount | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of storage account names""" @@ -57,10 +78,15 @@ class StorageAccount: Definition: StorageAccount """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name or queue endpoint of the storage account.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the storage account.""" @@ -72,7 +98,11 @@ class QueueInfo: Definition: Queue """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the queue.""" @@ -82,10 +112,7 @@ class MessagePost: Definition: MessagePost """ - message: Optional[str] = field( - default=None, - metadata={"wire_name": "Message"}, - ) + message: str = dataclass_field(metadata={"wire_name": "Message"}) """The message to put in the queue.""" @@ -95,38 +122,45 @@ class QueueMessage: Definition: QueueMessage """ - message_id: Optional[str] = field( + message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageId"}, ) """The unique identifier of the message.""" - insertion_time: Optional[str] = field( + insertion_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InsertionTime"}, ) """The time the message was inserted into the queue.""" - expiration_time: Optional[str] = field( + expiration_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpirationTime"}, ) """The time the message will expire from the queue.""" - pop_receipt: Optional[str] = field( + pop_receipt: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PopReceipt"}, ) """Used to delete the message after popping it off the queue.""" - next_visible_time: Optional[str] = field( + next_visible_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TimeNextVisible"}, ) """The time the message will be visible to other consumers.""" - message_text: Optional[str] = field( + message_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageText"}, ) """The text of the message.""" - dequeue_count: Optional[str] = field( + dequeue_count: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DequeueCount"}, ) """The number of times the message has been dequeued.""" @@ -138,8 +172,9 @@ class QueueMessagesList: Definition: QueueMessagesList """ - queue_message: Optional[List[QueueMessage]] = field( + queue_message: Optional[List[QueueMessage | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "QueueMessage"}, ) @@ -152,16 +187,16 @@ class AzurequeuesClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -172,8 +207,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -181,8 +216,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -194,7 +229,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -209,7 +244,46 @@ def __init__( def connector_name(self) -> str: return "azurequeues" - async def delete_message_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def delete_message( self, storage_account_name: str, queue_name: str, @@ -225,6 +299,25 @@ async def delete_message_async( Delete message Delete a specific message from the queue. + + Swagger operation ID: `DeleteMessage_V2`. + + Args: + storage_account_name: Azure Storage account name or queue endpoint. + queue_name: The queue to delete a message from. + message_id: The ID of the message to delete. + popreceipt: A valid pop receipt value returned from an earlier call + to the Get Messages. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -244,7 +337,7 @@ async def delete_message_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -258,15 +351,16 @@ async def delete_message_async( request_url, response.status, response.text, + response=response, ) - async def get_messages_async( + def get_messages( self, storage_account_name: str, queue_name: str, + *, numofmessages: Optional[str] = None, visibilitytimeout: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -277,6 +371,26 @@ async def get_messages_async( Get a specific set of messages from the queue. The messages will be hidden but remain on the queue until the delete action is used. + + Swagger operation ID: `GetMessages_V2`. + + Args: + storage_account_name: Azure Storage account name or queue endpoint. + queue_name: The queue to get Messages from. + numofmessages: The number of messages to grab from the queue + (default 1). + visibilitytimeout: The time in seconds that messages will be + invisible to other consumers (default 30). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -301,7 +415,7 @@ async def get_messages_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -315,6 +429,7 @@ async def get_messages_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -322,7 +437,7 @@ async def get_messages_async( return json.loads(response.text) - async def list_queues_async( + def list_queues( self, storage_account_name: str, *, @@ -330,11 +445,30 @@ async def list_queues_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List queues List all the queues for your storage account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListQueues_V2`. + + Args: + storage_account_name: Azure Storage account name or queue endpoint. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -344,29 +478,50 @@ async def list_queues_async( f"/queues" f"/list" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def put_message_async( + return ItemPaged(get_next, extract_data) + + def put_message( self, input: PutMessageInput, storage_account_name: str, @@ -381,6 +536,23 @@ async def put_message_async( Put a message on a queue Adds a message to the given queue. + + Swagger operation ID: `PutMessage_V2`. + + Args: + input: The request body. + storage_account_name: Azure Storage account name or queue endpoint. + queue_name: The queue to put a message to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -392,7 +564,7 @@ async def put_message_async( f"/messages" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -406,9 +578,10 @@ async def put_message_async( request_url, response.status, response.text, + response=response, ) - async def put_queue_async( + def put_queue( self, storage_account_name: str, queue_name: str, @@ -422,6 +595,22 @@ async def put_queue_async( Create a new queue Adds a queue to your account. + + Swagger operation ID: `PutQueue_V2`. + + Args: + storage_account_name: Azure Storage account name or queue endpoint. + queue_name: The name of the queue to create. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -439,7 +628,7 @@ async def put_queue_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -453,6 +642,7 @@ async def put_queue_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -460,41 +650,80 @@ async def put_queue_async( return json.loads(response.text) - async def get_storage_accounts_async( + def list_storage_accounts( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get storage accounts This operation list the user's Azure Storage Account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetStorageAccounts`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/GetStorageAccounts" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/azuretables.py b/src/azure/connectors/azuretables.py index f3cd1d6..25cc4a0 100644 --- a/src/azure/connectors/azuretables.py +++ b/src/azure/connectors/azuretables.py @@ -5,21 +5,41 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core import MatchConditions +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "AzuretablesClient", + "CreateEntityInput", + "CreateTableInput", + "EntityItem", + "GetEntitiesResponse", + "GetEntityResponse", + "GetTableResponse", + "GetTablesResponse", + "InsertEntityResponse", + "InsertMergeEntityInput", + "InsertReplaceEntityInput", + "MergeEntityInput", + "ReplaceEntityInput", + "StorageAccount", + "StorageAccountList", +] + # Type Definitions @@ -29,7 +49,7 @@ class CreateEntityInput: Insert Entity """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -42,23 +62,27 @@ class InsertEntityResponse: Response for Insert Entity """ - odata_metadata: Optional[str] = field( + odata_metadata: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "odata.metadata"}, ) """Entity Metadata location""" - partition_key: Optional[str] = field( + partition_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PartitionKey"}, ) """Partition Key""" - row_key: Optional[str] = field( + row_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RowKey"}, ) """Row Key""" - additional_properties: Optional[str] = field( + additional_properties: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "additionalProperties"}, ) """Dynamic entity columns returned by the service.""" @@ -73,13 +97,15 @@ class GetTableResponse: Response for Create table """ - odata_id: Optional[str] = field( + odata_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "odata.id"}, ) """URL to the Table data""" - table_name: Optional[str] = field( + table_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableName"}, ) """Table Name""" @@ -91,15 +117,22 @@ class GetEntitiesResponse: Response for Get entities """ - odata_metadata: Optional[str] = field( + odata_metadata: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "odata.metadata"}, ) """Table Metadata location""" - value: Optional[List[EntityItem]] = None + value: Optional[ + List[EntityItem | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Entities""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to retrieve the next page.""" @@ -111,23 +144,27 @@ class GetEntityResponse: Response for Get entity """ - odata_metadata: Optional[str] = field( + odata_metadata: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "odata.metadata"}, ) """Table Metadata location""" - partition_key: Optional[str] = field( + partition_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PartitionKey"}, ) """Partition Key""" - row_key: Optional[str] = field( + row_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RowKey"}, ) """Row Key""" - additional_properties: Optional[str] = field( + additional_properties: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "additionalProperties"}, ) """Dynamic entity columns returned by the service.""" @@ -139,12 +176,13 @@ class GetTablesResponse: Response for List tables """ - odata_metadata: Optional[str] = field( + odata_metadata: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "odata.metadata"}, ) """URL to the account metadata""" - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of tables""" @@ -154,7 +192,7 @@ class InsertMergeEntityInput: Insert or Merge Entity """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -167,7 +205,7 @@ class InsertReplaceEntityInput: Insert or Replace Entity """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -180,7 +218,7 @@ class MergeEntityInput: Merge Entity """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -193,7 +231,7 @@ class ReplaceEntityInput: Replace Entity """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -206,7 +244,12 @@ class StorageAccountList: Response for Get storage accounts """ - value: Optional[List[StorageAccount]] = None + value: Optional[ + List[StorageAccount | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of storage account names""" @@ -216,10 +259,15 @@ class StorageAccount: Definition: StorageAccount """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the storage account.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the storage account.""" @@ -231,18 +279,21 @@ class EntityItem: Definition: Item """ - partition_key: Optional[str] = field( + partition_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PartitionKey"}, ) """Partition Key""" - row_key: Optional[str] = field( + row_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RowKey"}, ) """Row Key""" - additional_properties: Optional[str] = field( + additional_properties: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "additionalProperties"}, ) """Dynamic entity columns returned by the service.""" @@ -256,16 +307,16 @@ class AzuretablesClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -276,8 +327,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -285,8 +336,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -298,7 +349,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -313,6 +364,43 @@ def __init__( def connector_name(self) -> str: return "azuretables" + @staticmethod + def _prepare_match_headers( + headers: Optional[Mapping[str, str]], + etag: Optional[str], + match_condition: Optional[MatchConditions], + *, + if_match_required: bool, + ) -> Optional[Mapping[str, str]]: + request_headers = dict(headers) if headers is not None else {} + existing_if_match = next( + (name for name in request_headers if name.lower() == "if-match"), + None, + ) + if etag is None and match_condition is None: + if if_match_required and existing_if_match is None: + request_headers["If-Match"] = "*" + return request_headers or None + + if existing_if_match is not None: + del request_headers[existing_if_match] + if match_condition is None: + assert etag is not None + request_headers["If-Match"] = etag + elif match_condition == MatchConditions.IfNotModified: + if etag is None: + raise ValueError( + "etag is required for MatchConditions.IfNotModified." + ) + request_headers["If-Match"] = etag + elif match_condition == MatchConditions.Unconditionally: + request_headers["If-Match"] = "*" + else: + raise ValueError( + "If-Match operations support only IfNotModified or Unconditionally." + ) + return request_headers or None + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: parsed_next_link = urlsplit(next_link) if not parsed_next_link.scheme or not parsed_next_link.netloc: @@ -320,7 +408,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -352,9 +440,9 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def create_entity_async( + def create_entity( self, - input: CreateEntityInput, + input: CreateEntityInput | Mapping[str, Any], storage_account_name: str, table_name: str, *, @@ -367,6 +455,24 @@ async def create_entity_async( Insert Entity Operation to add an entity to a table. + + Swagger operation ID: `CreateEntity_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -378,7 +484,7 @@ async def create_entity_async( f"/entities" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -392,6 +498,7 @@ async def create_entity_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -399,7 +506,7 @@ async def create_entity_async( return json.loads(response.text) - async def create_table_async( + def create_table( self, input: CreateTableInput, storage_account_name: str, @@ -413,6 +520,22 @@ async def create_table_async( Create table This operation adds a table to the storage account. + + Swagger operation ID: `CreateTable_V2`. + + Args: + input: The request body. + storage_account_name: Azure Storage account name or table endpoint. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -422,7 +545,7 @@ async def create_table_async( f"/tables" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -436,6 +559,7 @@ async def create_table_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -443,13 +567,15 @@ async def create_table_async( return json.loads(response.text) - async def delete_entity_async( + def delete_entity( self, storage_account_name: str, table_name: str, partition_key: str, row_key: str, *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -459,7 +585,34 @@ async def delete_entity_async( Delete Entity Operation to delete an entity. + + Swagger operation ID: `DeleteEntity_V2`. + + Args: + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + partition_key: The partition id containing this entity. + row_key: The row id containing this entity. + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=False, + ) + request_url = ( f"{self._connection_runtime_url}" f"/v2" @@ -475,7 +628,7 @@ async def delete_entity_async( f"')" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -489,9 +642,10 @@ async def delete_entity_async( request_url, response.status, response.text, + response=response, ) - async def delete_table_async( + def delete_table( self, storage_account_name: str, table_name: str, @@ -505,6 +659,22 @@ async def delete_table_async( Delete a table Delete a table. + + Swagger operation ID: `DeleteTable_V2`. + + Args: + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -515,7 +685,7 @@ async def delete_table_async( f"/{quote(str(table_name), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -529,27 +699,50 @@ async def delete_table_async( request_url, response.status, response.text, + response=response, ) - async def get_entities_async( + def list_entities( self, storage_account_name: str, table_name: str, + *, filter: Optional[str] = None, select: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get entities This operation queries the entities in a table. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetEntities_V2`. + + Args: + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + filter: OData filter query for which entities to return. Example: + Column eq 'Value' and Column2 ne 2. Invalid OData queries, such + as not wrapping string values in quotes will return 501. + select: OData select query for the columns to be returned. Example: + Column, PartitionKey. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -573,11 +766,18 @@ async def get_entities_async( query_params.append(f"$select={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -590,30 +790,39 @@ async def get_entities_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_entity_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def get_entity( self, storage_account_name: str, table_name: str, partition_key: str, row_key: str, - select: Optional[str] = None, *, + select: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -624,6 +833,26 @@ async def get_entity_async( This operation gets the entity in a table based on the partition and row key. + + Swagger operation ID: `GetEntity_V2`. + + Args: + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + partition_key: The partition id containing this entity. + row_key: The row id containing this entity. + select: OData select query for the columns to be returned. Example: + Column, PartitionKey. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -647,7 +876,7 @@ async def get_entity_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -661,6 +890,7 @@ async def get_entity_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -668,7 +898,7 @@ async def get_entity_async( return json.loads(response.text) - async def get_table_async( + def get_table( self, storage_account_name: str, table_name: str, @@ -682,6 +912,22 @@ async def get_table_async( Get a table This operation gets the metadata of a table. + + Swagger operation ID: `GetTable_V2`. + + Args: + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -692,7 +938,7 @@ async def get_table_async( f"/{quote(str(table_name), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -706,6 +952,7 @@ async def get_table_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -713,7 +960,7 @@ async def get_table_async( return json.loads(response.text) - async def get_tables_async( + def list_tables( self, storage_account_name: str, *, @@ -721,11 +968,30 @@ async def get_tables_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List tables List all the tables for your storage account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTables_V2`. + + Args: + storage_account_name: Azure Storage account name or table endpoint. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -734,31 +1000,52 @@ async def get_tables_async( f"/{quote(quote(str(storage_account_name), safe=''), safe='')}" f"/tables" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def insert_merge_entity_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def insert_merge_entity( self, - input: InsertMergeEntityInput, + input: InsertMergeEntityInput | Mapping[str, Any], storage_account_name: str, table_name: str, partition_key: str, @@ -774,6 +1061,26 @@ async def insert_merge_entity_async( Operation to merge data with an entity in a table, creating a new entity if needed. + + Swagger operation ID: `InsertMergeEntity_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + partition_key: The partition id containing this entity. + row_key: The row id containing this entity. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -789,7 +1096,7 @@ async def insert_merge_entity_async( f"')" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -803,11 +1110,12 @@ async def insert_merge_entity_async( request_url, response.status, response.text, + response=response, ) - async def insert_replace_entity_async( + def insert_replace_entity( self, - input: InsertReplaceEntityInput, + input: InsertReplaceEntityInput | Mapping[str, Any], storage_account_name: str, table_name: str, partition_key: str, @@ -823,6 +1131,26 @@ async def insert_replace_entity_async( Operation to replace an entity in a table, creating a new entity if needed. + + Swagger operation ID: `InsertReplaceEntity_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + partition_key: The partition id containing this entity. + row_key: The row id containing this entity. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -838,7 +1166,7 @@ async def insert_replace_entity_async( f"')" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -852,16 +1180,19 @@ async def insert_replace_entity_async( request_url, response.status, response.text, + response=response, ) - async def merge_entity_async( + def merge_entity( self, - input: MergeEntityInput, + input: MergeEntityInput | Mapping[str, Any], storage_account_name: str, table_name: str, partition_key: str, row_key: str, *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -871,7 +1202,36 @@ async def merge_entity_async( Merge Entity Operation to merge data with an entity in a table. + + Swagger operation ID: `MergeEntity_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + partition_key: The partition id containing this entity. + row_key: The row id containing this entity. + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + request_url = ( f"{self._connection_runtime_url}" f"/v2" @@ -887,7 +1247,7 @@ async def merge_entity_async( f"')" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -901,16 +1261,19 @@ async def merge_entity_async( request_url, response.status, response.text, + response=response, ) - async def replace_entity_async( + def replace_entity( self, - input: ReplaceEntityInput, + input: ReplaceEntityInput | Mapping[str, Any], storage_account_name: str, table_name: str, partition_key: str, row_key: str, *, + etag: Optional[str] = "*", + match_condition: Optional[MatchConditions] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -920,7 +1283,36 @@ async def replace_entity_async( Replace Entity Operation to replace an entity in a table. + + Swagger operation ID: `ReplaceEntity_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + storage_account_name: Azure Storage account name or table endpoint. + table_name: Specify the table. + partition_key: The partition id containing this entity. + row_key: The row id containing this entity. + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + request_url = ( f"{self._connection_runtime_url}" f"/v2" @@ -936,7 +1328,7 @@ async def replace_entity_async( f"')" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -950,40 +1342,80 @@ async def replace_entity_async( request_url, response.status, response.text, + response=response, ) - async def get_storage_accounts_async( + def list_storage_accounts( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get storage accounts This operation list the user's Azure Storage Account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetStorageAccounts`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/GetStorageAccounts" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/azurevm.py b/src/azure/connectors/azurevm.py index 17085a0..2afa8dd 100644 --- a/src/azure/connectors/azurevm.py +++ b/src/azure/connectors/azurevm.py @@ -5,21 +5,39 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "AzurevmClient", + "ResourceGroup", + "ResourceGroupListResult", + "Subscription", + "SubscriptionListResult", + "VirtualMachine", + "VirtualMachineInScaleSet", + "VirtualMachineInScaleSetListResult", + "VirtualMachineInScaleSetProperties", + "VirtualMachineListResult", + "VirtualMachineProperties", + "VirtualMachineScaleSet", + "VirtualMachineScaleSetListResult", + "VirtualMachineScaleSetProperties", +] + # Type Definitions @@ -29,16 +47,22 @@ class VirtualMachineInScaleSet: Response for Get virtual machine in a VM scale set """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the virtual machine.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The Name of the virtual machine.""" - instance_id: Optional[str] = field( + instance_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "instanceId"}, ) """The instance Id of the virtual machine.""" - properties: Optional[VirtualMachineInScaleSetProperties] = None + properties: Optional[ + VirtualMachineInScaleSetProperties | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -47,11 +71,16 @@ class VirtualMachine: Response for Get virtual machine """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the virtual machine.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The Name of the virtual machine.""" - properties: Optional[VirtualMachineProperties] = None + properties: Optional[ + VirtualMachineProperties | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -60,10 +89,16 @@ class SubscriptionListResult: Response for List subscriptions """ - value: Optional[List[Subscription]] = None + value: Optional[ + List[Subscription | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The subscriptions.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -75,10 +110,16 @@ class ResourceGroupListResult: Response for List resource groups """ - value: Optional[List[ResourceGroup]] = None + value: Optional[ + List[ResourceGroup | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of resource groups.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -90,10 +131,16 @@ class VirtualMachineScaleSetListResult: Response for List virtual machine scale sets """ - value: Optional[List[VirtualMachineScaleSet]] = None + value: Optional[ + List[VirtualMachineScaleSet | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of virtual machine scale sets.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -105,10 +152,16 @@ class VirtualMachineInScaleSetListResult: Response for List virtual machines in a VM scale set """ - value: Optional[List[VirtualMachineInScaleSet]] = None + value: Optional[ + List[VirtualMachineInScaleSet | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of virtual machines in a VM scale set.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -120,10 +173,16 @@ class VirtualMachineListResult: Response for List virtual machines """ - value: Optional[List[VirtualMachine]] = None + value: Optional[ + List[VirtualMachine | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of virtual machines.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to get the next set of results.""" @@ -135,27 +194,31 @@ class Subscription: Definition: Subscription """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The fully qualified Id.""" - subscription_id: Optional[str] = field( + subscription_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "subscriptionId"}, ) """The subscription Id.""" - tenant_id: Optional[str] = field( + tenant_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tenantId"}, ) """The tenant Id.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The subscription display name.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """The subscription state.""" - authorization_source: Optional[str] = field( + authorization_source: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "authorizationSource"}, ) """ @@ -171,12 +234,13 @@ class ResourceGroup: Definition: ResourceGroup """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the resource group.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The Name of the resource group.""" - managed_by: Optional[str] = field( + managed_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managedBy"}, ) """Id of the resource that manages this resource group.""" @@ -188,11 +252,16 @@ class VirtualMachineScaleSet: Definition: VirtualMachineScaleSet """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the virtual machine scale set.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The Name of the virtual machine scale set.""" - properties: Optional[VirtualMachineScaleSetProperties] = None + properties: Optional[ + VirtualMachineScaleSetProperties | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -201,8 +270,9 @@ class VirtualMachineScaleSetProperties: Definition: VirtualMachineScaleSetProperties """ - provisioning_state: Optional[str] = field( + provisioning_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "provisioningState"}, ) """The state of the virtual machine scale set.""" @@ -214,8 +284,9 @@ class VirtualMachineInScaleSetProperties: Definition: VirtualMachineInScaleSetProperties """ - provisioning_state: Optional[str] = field( + provisioning_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "provisioningState"}, ) """The state of the virtual machine.""" @@ -227,8 +298,9 @@ class VirtualMachineProperties: Definition: VirtualMachineProperties """ - provisioning_state: Optional[str] = field( + provisioning_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "provisioningState"}, ) """The state of the virtual machine.""" @@ -242,16 +314,16 @@ class AzurevmClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -262,8 +334,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -271,8 +343,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -284,7 +356,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -306,7 +378,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -338,7 +410,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def virtual_machine_in_scale_set_get_async( + def virtual_machine_in_scale_set_get( self, subscription_id: str, resource_group_name: str, @@ -354,6 +426,26 @@ async def virtual_machine_in_scale_set_get_async( Get virtual machine in a VM scale set Gets a virtual machine in a VM scale set. + + Swagger operation ID: `VirtualMachineInScaleSet_Get`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + virtual_machine_in_scale_set_instance_id: The name of the virtual + machine in a VM scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -373,7 +465,7 @@ async def virtual_machine_in_scale_set_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -387,6 +479,7 @@ async def virtual_machine_in_scale_set_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -394,7 +487,7 @@ async def virtual_machine_in_scale_set_get_async( return json.loads(response.text) - async def virtual_machine_in_scale_set_deallocate_async( + def virtual_machine_in_scale_set_deallocate( self, subscription_id: str, resource_group_name: str, @@ -413,6 +506,26 @@ async def virtual_machine_in_scale_set_deallocate_async( the virtual machine and releases the compute resources it uses. You are not billed for the compute resources of this virtual machine once it is deallocated. + + Swagger operation ID: `VirtualMachineInScaleSet_Deallocate`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + virtual_machine_in_scale_set_instance_id: The name of the virtual + machine in a VM scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -433,7 +546,7 @@ async def virtual_machine_in_scale_set_deallocate_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -447,9 +560,10 @@ async def virtual_machine_in_scale_set_deallocate_async( request_url, response.status, response.text, + response=response, ) - async def virtual_machine_in_scale_set_power_off_async( + def virtual_machine_in_scale_set_power_off( self, subscription_id: str, resource_group_name: str, @@ -467,6 +581,26 @@ async def virtual_machine_in_scale_set_power_off_async( Power off (stop) a virtual machine in a VM scale set. Note that resources are still attached and you are getting charged for the resources. + + Swagger operation ID: `VirtualMachineInScaleSet_PowerOff`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + virtual_machine_in_scale_set_instance_id: The name of the virtual + machine in a VM scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -487,7 +621,7 @@ async def virtual_machine_in_scale_set_power_off_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -501,9 +635,10 @@ async def virtual_machine_in_scale_set_power_off_async( request_url, response.status, response.text, + response=response, ) - async def virtual_machine_in_scale_set_redeploy_async( + def virtual_machine_in_scale_set_redeploy( self, subscription_id: str, resource_group_name: str, @@ -520,6 +655,26 @@ async def virtual_machine_in_scale_set_redeploy_async( Shuts down the virtual machine in the VM scale set, moves it to a new node, and powers it back on. + + Swagger operation ID: `VirtualMachineInScaleSet_Redeploy`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + virtual_machine_in_scale_set_instance_id: The name of the virtual + machine in a VM scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -540,7 +695,7 @@ async def virtual_machine_in_scale_set_redeploy_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -554,9 +709,10 @@ async def virtual_machine_in_scale_set_redeploy_async( request_url, response.status, response.text, + response=response, ) - async def virtual_machine_in_scale_set_reimage_async( + def virtual_machine_in_scale_set_reimage( self, subscription_id: str, resource_group_name: str, @@ -573,6 +729,26 @@ async def virtual_machine_in_scale_set_reimage_async( Reimages (upgrade the operating system) a specific virtual machine in a VM scale set. + + Swagger operation ID: `VirtualMachineInScaleSet_Reimage`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + virtual_machine_in_scale_set_instance_id: The name of the virtual + machine in a VM scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -593,7 +769,7 @@ async def virtual_machine_in_scale_set_reimage_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -607,9 +783,10 @@ async def virtual_machine_in_scale_set_reimage_async( request_url, response.status, response.text, + response=response, ) - async def virtual_machine_in_scale_set_restart_async( + def virtual_machine_in_scale_set_restart( self, subscription_id: str, resource_group_name: str, @@ -625,6 +802,26 @@ async def virtual_machine_in_scale_set_restart_async( Restart virtual machine in a VM scale set Restarts a virtual machine in a VM scale set. + + Swagger operation ID: `VirtualMachineInScaleSet_Restart`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + virtual_machine_in_scale_set_instance_id: The name of the virtual + machine in a VM scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -645,7 +842,7 @@ async def virtual_machine_in_scale_set_restart_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -659,9 +856,10 @@ async def virtual_machine_in_scale_set_restart_async( request_url, response.status, response.text, + response=response, ) - async def virtual_machine_in_scale_set_start_async( + def virtual_machine_in_scale_set_start( self, subscription_id: str, resource_group_name: str, @@ -677,6 +875,26 @@ async def virtual_machine_in_scale_set_start_async( Start virtual machine in a VM scale set Starts a virtual machine in a VM scale set. + + Swagger operation ID: `VirtualMachineInScaleSet_Start`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + virtual_machine_in_scale_set_instance_id: The name of the virtual + machine in a VM scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -697,7 +915,7 @@ async def virtual_machine_in_scale_set_start_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -711,9 +929,10 @@ async def virtual_machine_in_scale_set_start_async( request_url, response.status, response.text, + response=response, ) - async def virtual_machine_get_async( + def virtual_machine_get( self, subscription_id: str, resource_group_name: str, @@ -728,6 +947,23 @@ async def virtual_machine_get_async( Get virtual machine Gets a virtual machine. + + Swagger operation ID: `VirtualMachine_Get`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_name: The name of the virtual machine. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -745,7 +981,7 @@ async def virtual_machine_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -759,6 +995,7 @@ async def virtual_machine_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -766,7 +1003,7 @@ async def virtual_machine_get_async( return json.loads(response.text) - async def virtual_machine_start_async( + def virtual_machine_start( self, subscription_id: str, resource_group_name: str, @@ -781,6 +1018,23 @@ async def virtual_machine_start_async( Start virtual machine Starts a virtual machine. + + Swagger operation ID: `VirtualMachine_Start`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_name: The name of the virtual machine. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -799,7 +1053,7 @@ async def virtual_machine_start_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -813,9 +1067,10 @@ async def virtual_machine_start_async( request_url, response.status, response.text, + response=response, ) - async def virtual_machine_deallocate_async( + def virtual_machine_deallocate( self, subscription_id: str, resource_group_name: str, @@ -832,6 +1087,23 @@ async def virtual_machine_deallocate_async( Shuts down the virtual machine and releases the compute resources. You are not billed for the compute resources that this virtual machine uses. + + Swagger operation ID: `VirtualMachine_Deallocate`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_name: The name of the virtual machine. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -850,7 +1122,7 @@ async def virtual_machine_deallocate_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -864,9 +1136,10 @@ async def virtual_machine_deallocate_async( request_url, response.status, response.text, + response=response, ) - async def virtual_machine_poweroff_async( + def virtual_machine_poweroff( self, subscription_id: str, resource_group_name: str, @@ -883,6 +1156,23 @@ async def virtual_machine_poweroff_async( Power off (stop) a virtual machine. The virtual machine can be restarted with the same provisioned resources. You are still charged for this virtual machine. + + Swagger operation ID: `VirtualMachine_Poweroff`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_name: The name of the virtual machine. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -901,7 +1191,7 @@ async def virtual_machine_poweroff_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -915,9 +1205,10 @@ async def virtual_machine_poweroff_async( request_url, response.status, response.text, + response=response, ) - async def virtual_machine_reapply_async( + def virtual_machine_reapply( self, subscription_id: str, resource_group_name: str, @@ -932,6 +1223,23 @@ async def virtual_machine_reapply_async( Reapply virtual machine Reapply a virtual machine's state. + + Swagger operation ID: `VirtualMachine_Reapply`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_name: The name of the virtual machine. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -950,7 +1258,7 @@ async def virtual_machine_reapply_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -964,9 +1272,10 @@ async def virtual_machine_reapply_async( request_url, response.status, response.text, + response=response, ) - async def virtual_machine_redeploy_async( + def virtual_machine_redeploy( self, subscription_id: str, resource_group_name: str, @@ -982,6 +1291,23 @@ async def virtual_machine_redeploy_async( Shuts down the virtual machine, moves it to a new node, and powers it back on. + + Swagger operation ID: `VirtualMachine_Redeploy`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_name: The name of the virtual machine. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1000,7 +1326,7 @@ async def virtual_machine_redeploy_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1014,9 +1340,10 @@ async def virtual_machine_redeploy_async( request_url, response.status, response.text, + response=response, ) - async def virtual_machine_restart_async( + def virtual_machine_restart( self, subscription_id: str, resource_group_name: str, @@ -1031,6 +1358,23 @@ async def virtual_machine_restart_async( Restart virtual machine Restarts a virtual machine. + + Swagger operation ID: `VirtualMachine_Restart`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_name: The name of the virtual machine. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1049,7 +1393,7 @@ async def virtual_machine_restart_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1063,34 +1407,57 @@ async def virtual_machine_restart_async( request_url, response.status, response.text, + response=response, ) - async def subscriptions_list_async( + def list_subscriptions( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List subscriptions Gets a list of all the subscriptions to which the principal has access. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Subscriptions_List`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/subscriptions" query_params = [] query_params.append("x-ms-api-version=" + quote("2020-01-01", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1103,23 +1470,32 @@ async def subscriptions_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def resource_groups_list_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def list_resource_groups( self, subscription_id: str, *, @@ -1127,14 +1503,30 @@ async def resource_groups_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List resource groups Lists all the resource groups within the subscription. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ResourceGroups_List`. + + Args: + subscription_id: Microsoft Azure subscription. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1146,11 +1538,18 @@ async def resource_groups_list_async( query_params.append("x-ms-api-version=" + quote("2020-01-01", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1163,23 +1562,32 @@ async def resource_groups_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def virtual_machine_scale_sets_list_async( + def list_virtual_machine_scale_sets( self, subscription_id: str, resource_group_name: str, @@ -1188,14 +1596,31 @@ async def virtual_machine_scale_sets_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List virtual machine scale sets Lists all the virtual machine scale sets within the resource group. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `VirtualMachineScaleSets_List`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1211,11 +1636,18 @@ async def virtual_machine_scale_sets_list_async( query_params.append("x-ms-api-version=" + quote("2019-12-01", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1228,23 +1660,32 @@ async def virtual_machine_scale_sets_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def virtual_machines_in_scale_set_list_async( + return ItemPaged(get_next, extract_data) + + def list_virtual_machines_in_scale_set( self, subscription_id: str, resource_group_name: str, @@ -1254,14 +1695,33 @@ async def virtual_machines_in_scale_set_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List virtual machines in a VM scale set Lists all the virtual machines in a VM scale set. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `VirtualMachinesInScaleSet_List`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + virtual_machine_scale_set_name: The name of the virtual machine + scale set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1279,11 +1739,18 @@ async def virtual_machines_in_scale_set_list_async( query_params.append("x-ms-api-version=" + quote("2019-12-01", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1296,23 +1763,32 @@ async def virtual_machines_in_scale_set_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def virtual_machines_list_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def list_virtual_machines( self, subscription_id: str, resource_group_name: str, @@ -1321,14 +1797,31 @@ async def virtual_machines_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List virtual machines Lists all the virtual machines within the resource group. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `VirtualMachines_List`. + + Args: + subscription_id: Microsoft Azure subscription. + resource_group_name: The name of the resource group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1344,11 +1837,18 @@ async def virtual_machines_list_async( query_params.append("x-ms-api-version=" + quote("2019-12-01", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1361,18 +1861,27 @@ async def virtual_machines_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/box.py b/src/azure/connectors/box.py index 8e46e34..f4ed828 100644 --- a/src/azure/connectors/box.py +++ b/src/azure/connectors/box.py @@ -5,21 +5,34 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "BoxClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "BlobMetadataPage", + "BlobMetadataResponse", + "DataSetsMetadata", + "ObjectEntity", + "TabularDataSetsMetadata", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,46 +42,72 @@ class BlobMetadata: Response for Get file metadata using id """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The filelocator of the file or folder.""" - last_modified_by: Optional[str] = field( + last_modified_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModifiedBy"}, ) """The user who last modified the file or folder.""" @@ -80,8 +119,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -90,25 +139,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -120,15 +173,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -140,7 +195,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -153,41 +208,66 @@ class BlobMetadataResponse: Definition: BlobMetadataResponse """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The filelocator of the file or folder.""" @@ -199,7 +279,12 @@ class BlobMetadataPage: Definition: BlobMetadataPage """ - value: Optional[List[BlobMetadata]] = None + value: Optional[ + List[BlobMetadata | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Blob metadata collection.""" @@ -211,16 +296,16 @@ class BoxClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -231,8 +316,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -240,8 +325,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -253,7 +338,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -268,7 +353,46 @@ def __init__( def connector_name(self) -> str: return "box" - async def get_file_metadata_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def get_file_metadata( self, id: str, *, @@ -281,6 +405,21 @@ async def get_file_metadata_async( Get file metadata using id Retrieves the file metadata from Box using file id. + + Swagger operation ID: `GetFileMetadata`. + + Args: + id: The unique identifier of the file in Box. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -290,7 +429,7 @@ async def get_file_metadata_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -304,6 +443,7 @@ async def get_file_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -311,7 +451,7 @@ async def get_file_metadata_async( return json.loads(response.text) - async def update_file_async( + def update_file( self, input: bytes, id: str, @@ -325,6 +465,22 @@ async def update_file_async( Update file Updates an existing file in Box. + + Swagger operation ID: `UpdateFile`. + + Args: + input: The binary request body. + id: The unique identifier of the file to update in Box. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -334,7 +490,7 @@ async def update_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, @@ -351,6 +507,7 @@ async def update_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -358,7 +515,7 @@ async def update_file_async( return json.loads(response.text) - async def delete_file_async( + def delete_file( self, id: str, *, @@ -371,6 +528,21 @@ async def delete_file_async( Delete file Deletes an existing file from Box. + + Swagger operation ID: `DeleteFile`. + + Args: + id: The unique identifier of the file to delete from Box. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -380,7 +552,7 @@ async def delete_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -394,9 +566,10 @@ async def delete_file_async( request_url, response.status, response.text, + response=response, ) - async def get_file_metadata_by_path_async( + def get_file_metadata_by_path( self, path: str, *, @@ -409,6 +582,21 @@ async def get_file_metadata_by_path_async( Get file metadata using path Retrieves the file metadata from Box using path. + + Swagger operation ID: `GetFileMetadataByPath`. + + Args: + path: The unique path to the file in Box. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/GetFileByPath" @@ -422,7 +610,7 @@ async def get_file_metadata_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -436,6 +624,7 @@ async def get_file_metadata_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -443,11 +632,11 @@ async def get_file_metadata_by_path_async( return json.loads(response.text) - async def get_file_content_by_path_async( + def get_file_content_by_path( self, path: str, - infer_content_type: Optional[bool] = None, *, + infer_content_type: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -457,6 +646,23 @@ async def get_file_content_by_path_async( Get file content using path Retrieves the file contents from Box using path. + + Swagger operation ID: `GetFileContentByPath`. + + Args: + path: The unique path to the file in Box. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -476,7 +682,7 @@ async def get_file_content_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -490,15 +696,16 @@ async def get_file_content_by_path_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_file_content_async( + def get_file_content( self, id: str, - infer_content_type: Optional[bool] = None, *, + infer_content_type: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -508,6 +715,23 @@ async def get_file_content_async( Get file content using id Retrieves the file content from Box using id. + + Swagger operation ID: `GetFileContent`. + + Args: + id: The unique identifier of the file in Box. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -526,7 +750,7 @@ async def get_file_content_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -540,11 +764,12 @@ async def get_file_content_async( request_url, response.status, response.text, + response=response, ) return response.content - async def create_file_async( + def create_file( self, input: bytes, folder_path: str, @@ -559,6 +784,23 @@ async def create_file_async( Create file Uploads a file to Box. + + Swagger operation ID: `CreateFile`. + + Args: + input: The binary request body. + folder_path: The folder path to upload the file to Box. + name: The name of the file to create in Box. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/datasets/default/files" query_params = [] @@ -574,7 +816,7 @@ async def create_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -591,6 +833,7 @@ async def create_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -598,12 +841,12 @@ async def create_file_async( return json.loads(response.text) - async def copy_file_async( + def copy_file( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -613,6 +856,24 @@ async def copy_file_async( Copy file Copy a file to a file path in Box. + + Swagger operation ID: `CopyFile`. + + Args: + source: The url to source file. + destination: The destination file path in Box, including target + filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/copyFile" @@ -635,7 +896,7 @@ async def copy_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -649,6 +910,7 @@ async def copy_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -656,7 +918,7 @@ async def copy_file_async( return json.loads(response.text) - async def list_folder_async( + def list_folder( self, id: str, *, @@ -664,11 +926,30 @@ async def list_folder_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List files and folders in folder Lists the files and folders in a Box folder. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListFolder`. + + Args: + id: The unique identifier of the folder in Box. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -677,72 +958,132 @@ async def list_folder_async( f"/folders" f"/{quote(quote(str(id), safe=''), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def list_root_folder_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_root_folder( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List files and folders in root folder Lists the files and folders in the Box root folder. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListRootFolder`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/folders" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def extract_folder_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def extract_folder( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -752,6 +1093,23 @@ async def extract_folder_async( Extract archive to folder Extracts an archive file into a folder in Box (example: .zip). + + Swagger operation ID: `ExtractFolderV2`. + + Args: + source: The path to the archive file. + destination: The path in Box to extract the archive contents. + overwrite: Overwrites the destination files if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/extractFolderV2" @@ -774,7 +1132,7 @@ async def extract_folder_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -788,6 +1146,7 @@ async def extract_folder_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/campfire.py b/src/azure/connectors/campfire.py index fb4e417..11d0564 100644 --- a/src/azure/connectors/campfire.py +++ b/src/azure/connectors/campfire.py @@ -5,21 +5,38 @@ from __future__ import annotations -from dataclasses import dataclass -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "CampfireClient", + "Account", + "AccountsResponse", + "CreateMessageResponse", + "CreateUploadResponse", + "Message", + "MessagesResponse", + "Room", + "RoomsResponse", + "Upload", + "UploadResponse", + "UserResponse", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +46,7 @@ class CreateMessageResponse: Response for Create a message """ - message: Optional[Dict[str, Any]] = None + message: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """A Campfire message""" @@ -39,7 +56,7 @@ class RoomsResponse: Response for When a room is created """ - rooms: Optional[List[Dict[str, Any]]] = None + rooms: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Collection of Rooms""" @@ -49,7 +66,7 @@ class MessagesResponse: Response for When a new message is received """ - messages: Optional[List[Dict[str, Any]]] = None + messages: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Collection Of messages""" @@ -59,7 +76,7 @@ class UploadResponse: Response for When a file is uploaded """ - uploads: Optional[List[Dict[str, Any]]] = None + uploads: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Collection of Uploads""" @@ -69,7 +86,7 @@ class UserResponse: Response for Get user by ID """ - user: Optional[Dict[str, Any]] = None + user: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -78,7 +95,7 @@ class AccountsResponse: Response for List accounts """ - accounts: Optional[List[Dict[str, Any]]] = None + accounts: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Collection Of Accounts""" @@ -88,13 +105,13 @@ class Account: Definition: Account """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the account""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the account""" - app_href: Optional[str] = None + app_href: Optional[str] = dataclass_field(default=None, kw_only=True) """Link to the account""" - account_url: Optional[str] = None + account_url: Optional[str] = dataclass_field(default=None, kw_only=True) """Account Url""" @@ -104,13 +121,13 @@ class Room: Definition: Room """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Room name.""" - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Room Id.""" - locked: Optional[bool] = None + locked: Optional[bool] = dataclass_field(default=None, kw_only=True) """Boolean value, True if a room is locked.""" - topic: Optional[str] = None + topic: Optional[str] = dataclass_field(default=None, kw_only=True) """Room topic or description.""" @@ -120,11 +137,11 @@ class Message: Definition: Message """ - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """Message Body.""" - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Message Id.""" - starred: Optional[bool] = None + starred: Optional[bool] = dataclass_field(default=None, kw_only=True) """Boolean value, True if a message is starred.""" @@ -134,17 +151,17 @@ class Upload: Definition: Upload """ - full_url: Optional[str] = None + full_url: Optional[str] = dataclass_field(default=None, kw_only=True) """File Url.""" - room_id: Optional[int] = None + room_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Room Id.""" - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """File Id.""" - content_type: Optional[str] = None + content_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Format of the uploaded file.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name.""" - created_at: Optional[str] = None + created_at: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of upload.""" @@ -154,7 +171,7 @@ class CreateUploadResponse: Definition: CreateUploadResponse """ - upload: Optional[Upload] = None + upload: Optional[Upload | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) # Client Class @@ -165,16 +182,16 @@ class CampfireClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -185,8 +202,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -194,8 +211,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -207,7 +224,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -222,7 +239,46 @@ def __init__( def connector_name(self) -> str: return "campfire" - async def create_message_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def create_message( self, room_id: str, account: str, @@ -237,6 +293,23 @@ async def create_message_async( Create a message Sends a message to the given room. + + Swagger operation ID: `CreateMessage`. + + Args: + room_id: A room associated with the account. + account: Account in Campfire. + message: Message text to be created. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -254,7 +327,7 @@ async def create_message_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -268,6 +341,7 @@ async def create_message_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -275,7 +349,7 @@ async def create_message_async( return json.loads(response.text) - async def get_user_async( + def get_user( self, user_id: int, account: str, @@ -289,6 +363,22 @@ async def get_user_async( Get user by ID Retrieves information about a user by given ID + + Swagger operation ID: `GetUser`. + + Args: + user_id: User ID. + account: Account in Campfire. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -302,7 +392,7 @@ async def get_user_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -316,6 +406,7 @@ async def get_user_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -323,19 +414,38 @@ async def get_user_async( return json.loads(response.text) - async def list_accounts_async( + def list_accounts( self, - parent_operation: Optional[str] = None, *, + parent_operation: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List accounts Retrieves the list of accounts this user has access too + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListAccounts`. + + Args: + parent_operation: parentOperation. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/authorization.json" query_params = [] @@ -346,29 +456,50 @@ async def list_accounts_async( query_params.append(f"parentOperation={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("accounts", []): + yield item - async def list_rooms_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_rooms( self, account: str, *, @@ -376,11 +507,30 @@ async def list_rooms_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List Rooms Retrieves the list of rooms in an account + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListRooms`. + + Args: + account: Account in Campfire. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/rooms.json" query_params = [] @@ -390,27 +540,48 @@ async def list_rooms_async( query_params.append(f"account={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("rooms", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/clicksendsms.py b/src/azure/connectors/clicksendsms.py index 491f0d1..4003139 100644 --- a/src/azure/connectors/clicksendsms.py +++ b/src/azure/connectors/clicksendsms.py @@ -5,14 +5,13 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, Dict, List, Any, Mapping from urllib.parse import quote import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, @@ -20,6 +19,35 @@ ConnectorResponseHook, ) +__all__ = [ + "ClicksendsmsClient", + "CreateListContactInput", + "CreateListContactResponse", + "CreateListInput", + "CreateListResponse", + "DeleteListContactResponse", + "DeleteListResponse", + "GetContactListsResponse", + "SearchContactListResponse", + "SendFaxInput", + "SendFaxResponse", + "SendLetterInput", + "SendLetterResponse", + "SendMmsInput", + "SendMmsResponse", + "SendPostcardInput", + "SendPostcardResponse", + "SendVoiceInput", + "SendVoiceResponse", + "SmsInboundAutomationInput", + "SmsSendInput", + "SmsSendResponse", + "UploadMediaInput", + "UploadMediaResponse", + "ViewListContactsResponse", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +57,7 @@ class SmsSendInput: Send SMS """ - messages: Optional[List[Dict[str, Any]]] = None + messages: List[Dict[str, Any]] """Message""" @@ -39,13 +67,13 @@ class SmsSendResponse: Response for Send SMS """ - http_code: Optional[int] = None + http_code: Optional[int] = dataclass_field(default=None, kw_only=True) """Http Code""" - response_code: Optional[str] = None + response_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Code""" - response_msg: Optional[str] = None + response_msg: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Msg""" - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -55,7 +83,7 @@ class CreateListInput: Create New Contact List """ - list_name: Optional[str] = None + list_name: str """Your contact list name""" @@ -65,13 +93,13 @@ class CreateListResponse: Response for Create New Contact List """ - http_code: Optional[int] = None + http_code: Optional[int] = dataclass_field(default=None, kw_only=True) """Http Code""" - response_code: Optional[str] = None + response_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Code""" - response_msg: Optional[str] = None + response_msg: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Message""" - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -81,13 +109,13 @@ class GetContactListsResponse: Response for Get Contact Lists """ - http_code: Optional[int] = None + http_code: Optional[int] = dataclass_field(default=None, kw_only=True) """Http Code""" - response_code: Optional[str] = None + response_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Code""" - response_msg: Optional[str] = None + response_msg: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Message""" - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -97,7 +125,7 @@ class SendVoiceInput: Send Voice Message """ - messages: Optional[List[Dict[str, Any]]] = None + messages: List[Dict[str, Any]] """Message""" @@ -107,13 +135,13 @@ class SendVoiceResponse: Response for Send Voice Message """ - http_code: Optional[int] = None + http_code: Optional[int] = dataclass_field(default=None, kw_only=True) """Http Code""" - response_code: Optional[str] = None + response_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Code""" - response_msg: Optional[str] = None + response_msg: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Message""" - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -123,11 +151,11 @@ class DeleteListResponse: Response for Delete List """ - http_code: Optional[int] = None + http_code: Optional[int] = dataclass_field(default=None, kw_only=True) """Http Code""" - response_code: Optional[str] = None + response_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Code""" - response_msg: Optional[str] = None + response_msg: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Message""" @@ -137,52 +165,58 @@ class CreateListContactInput: Create New Contact """ - first_name: Optional[str] = None + first_name: str """Contact's first name.""" - last_name: Optional[str] = None + last_name: str """Contact's last name.""" - phone_number: Optional[str] = None + phone_number: str """The contact phone in local or international format e.g. +61411111111.""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """Contact's email address.""" - fax_number: Optional[str] = None + fax_number: Optional[str] = dataclass_field(default=None, kw_only=True) """Contact's fax number.""" - organization_name: Optional[str] = None + organization_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Contact's organization name.""" - address_country: Optional[str] = None + address_country: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's country.""" - address_state: Optional[str] = None + address_state: Optional[str] = dataclass_field(default=None, kw_only=True) """State""" - address_city: Optional[str] = None + address_city: Optional[str] = dataclass_field(default=None, kw_only=True) """Address City""" - custom1: Optional[str] = field( + custom1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "custom_1"}, ) """Custom 1""" - custom3: Optional[str] = field( + custom3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "custom_3"}, ) """Custom 3""" - address_postal_code: Optional[str] = None - custom2: Optional[str] = field( + address_postal_code: Optional[str] = dataclass_field(default=None, kw_only=True) + custom2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "custom_2"}, ) """Custom 2""" - custom4: Optional[str] = field( + custom4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "custom_4"}, ) """Custom 4""" - address_line1: Optional[str] = field( + address_line1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "address_line_1"}, ) """Address Line 1""" - address_line2: Optional[str] = field( + address_line2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "address_line_2"}, ) """Address Line 2""" @@ -194,13 +228,13 @@ class CreateListContactResponse: Response for Create New Contact """ - http_code: Optional[int] = None + http_code: Optional[int] = dataclass_field(default=None, kw_only=True) """Http Code""" - response_code: Optional[str] = None + response_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Code""" - response_msg: Optional[str] = None + response_msg: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Message""" - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -210,13 +244,13 @@ class ViewListContactsResponse: Response for Get Contacts in a List """ - http_code: Optional[int] = None + http_code: Optional[int] = dataclass_field(default=None, kw_only=True) """Http Code""" - response_code: Optional[str] = None + response_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Code""" - response_msg: Optional[str] = None + response_msg: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Message""" - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -226,11 +260,11 @@ class DeleteListContactResponse: Response for Delete a Contact """ - http_code: Optional[int] = None + http_code: Optional[int] = dataclass_field(default=None, kw_only=True) """Http Code""" - response_code: Optional[str] = None + response_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Code""" - response_msg: Optional[str] = None + response_msg: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Message""" @@ -240,9 +274,9 @@ class SendMmsInput: Send MMS """ - messages: Optional[List[Dict[str, Any]]] = None + messages: List[Dict[str, Any]] """Message""" - media_file: Optional[str] = None + media_file: str """ Supports maximum file size of 250kB, Gif can only be supported if it below 100 kB file size @@ -255,13 +289,13 @@ class SendMmsResponse: Response for Send MMS """ - http_code: Optional[int] = None + http_code: Optional[int] = dataclass_field(default=None, kw_only=True) """Http Code""" - response_code: Optional[str] = None + response_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Code""" - response_msg: Optional[str] = None + response_msg: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Message""" - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -271,9 +305,9 @@ class SendFaxInput: Send Fax """ - messages: Optional[List[Dict[str, Any]]] = None + messages: List[Dict[str, Any]] """Message""" - file_url: Optional[str] = None + file_url: str """ Maximum file size is 4 MB. All pages should be in portrait. Chat with ClickSend Support for complete specifications @@ -286,13 +320,13 @@ class SendFaxResponse: Response for Send Fax """ - http_code: Optional[int] = None + http_code: Optional[int] = dataclass_field(default=None, kw_only=True) """Http Code""" - response_code: Optional[str] = None + response_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Code""" - response_msg: Optional[str] = None + response_msg: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Message""" - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -302,7 +336,7 @@ class UploadMediaInput: Convert Media File Format """ - content: Optional[str] = None + content: str """File Content (base64)""" @@ -312,13 +346,13 @@ class UploadMediaResponse: Response for Convert Media File Format """ - http_code: Optional[int] = None + http_code: Optional[int] = dataclass_field(default=None, kw_only=True) """Http Code""" - response_code: Optional[str] = None + response_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Code""" - response_msg: Optional[str] = None + response_msg: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Message""" - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -328,13 +362,13 @@ class SearchContactListResponse: Response for Search Contact Lists """ - http_code: Optional[int] = None + http_code: Optional[int] = dataclass_field(default=None, kw_only=True) """Http Code""" - response_code: Optional[str] = None + response_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Code""" - response_msg: Optional[str] = None + response_msg: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Message""" - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -344,27 +378,27 @@ class SendLetterInput: Send Letter """ - file_url: Optional[str] = None + file_url: str """ Maximum file size is 10 MB. All pages should be in portrait. Chat with ClickSend Support for complete specifications. """ - template_used: Optional[int] = None + template_used: Optional[int] = dataclass_field(default=None, kw_only=True) """ Whether using letter template. Flag value must be 1 for yes or 0 for no. """ - colour: Optional[int] = None + colour: int """Choose to use colour or B&W printing. (Black & White = 0, Colour = 1)""" - duplex: Optional[int] = None + duplex: int """ Choose to use Duplex = 1 (double-sided) or Simplex = 0(single sided) printing. """ - priority_post: Optional[int] = None + priority_post: Optional[int] = dataclass_field(default=None, kw_only=True) """Whether letter is priority, Flag value must be 1 for yes or 0 for no.""" - recipients: Optional[List[Dict[str, Any]]] = None + recipients: List[Dict[str, Any]] """Recipient""" - source: Optional[str] = None + source: str """Source""" @@ -374,13 +408,13 @@ class SendLetterResponse: Response for Send Letter """ - http_code: Optional[int] = None + http_code: Optional[int] = dataclass_field(default=None, kw_only=True) """Http Code""" - response_code: Optional[str] = None + response_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Code""" - response_msg: Optional[str] = None + response_msg: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Message""" - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -390,9 +424,9 @@ class SendPostcardInput: Send Postcard """ - recipients: Optional[List[Dict[str, Any]]] = None + recipients: List[Dict[str, Any]] """item""" - file_urls: Optional[List[str]] = None + file_urls: List[str] """PDF File URL""" @@ -402,13 +436,13 @@ class SendPostcardResponse: Response for Send Postcard """ - http_code: Optional[int] = None + http_code: Optional[int] = dataclass_field(default=None, kw_only=True) """Http Code""" - response_code: Optional[str] = None + response_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Code""" - response_msg: Optional[str] = None + response_msg: Optional[str] = dataclass_field(default=None, kw_only=True) """Response Message""" - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -418,28 +452,28 @@ class SmsInboundAutomationInput: SMS Inbound Automation """ - message_search_type: Optional[int] = None + message_search_type: int """ Message Search Type: 0=Any message, 1=starts with, 2=contains, 3=does not contain. """ - message_search_term: Optional[str] = None + message_search_term: str """word or phrase in the SMS""" - action_address: Optional[str] = None + action_address: str """Action address""" - dedicated_number: Optional[str] = None + dedicated_number: str """Decicated Number. Can be '*' to apply to all numbers.""" - rule_name: Optional[str] = None + rule_name: str """Rule Name""" - webhook_type: Optional[str] = None + webhook_type: str """Webhook Type""" - action: Optional[str] = None + action: str """ Action to be taken (AUTO_REPLY, EMAIL_USER, EMAIL_FIXED, URL, SMS, POLL, GROUP_SMS, MOVE_CONTACT, CREATE_CONTACT, CREATE_CONTACT_PLUS_EMAIL, CREATE_CONTACT_PLUS_NAME_EMAIL CREATE_CONTACT_PLUS_NAME, SMPP, NONE). """ - enabled: Optional[int] = None + enabled: int """enabled""" @@ -451,16 +485,16 @@ class ClicksendsmsClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -471,8 +505,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -480,8 +514,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -493,7 +527,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -508,9 +542,9 @@ def __init__( def connector_name(self) -> str: return "clicksendsms" - async def sms_send_async( + def sms_send( self, - input: SmsSendInput, + input: SmsSendInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -521,10 +555,26 @@ async def sms_send_async( Send SMS Each 160 characters = 1 SMS. Can send up to 1,224 standard characters. + + Swagger operation ID: `sms_send`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/sms/send" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -538,6 +588,7 @@ async def sms_send_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -545,9 +596,9 @@ async def sms_send_async( return json.loads(response.text) - async def create_list_async( + def create_list( self, - input: CreateListInput, + input: CreateListInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -558,10 +609,26 @@ async def create_list_async( Create New Contact List Create New Contact List + + Swagger operation ID: `create_list`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/lists" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -575,6 +642,7 @@ async def create_list_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -582,11 +650,11 @@ async def create_list_async( return json.loads(response.text) - async def get_contact_lists_async( + def get_contact_lists( self, + *, page: Optional[int] = None, limit: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -596,6 +664,22 @@ async def get_contact_lists_async( Get Contact Lists Get all contact lists unless specified in the advance options + + Swagger operation ID: `get_contact_lists`. + + Args: + page: Page number. + limit: Number of records per page. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/lists" query_params = [] @@ -612,7 +696,7 @@ async def get_contact_lists_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -626,6 +710,7 @@ async def get_contact_lists_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -633,9 +718,9 @@ async def get_contact_lists_async( return json.loads(response.text) - async def send_voice_async( + def send_voice( self, - input: SendVoiceInput, + input: SendVoiceInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -647,10 +732,26 @@ async def send_voice_async( Each 300 characters = 1 voice message. Can send up to 1,200 standard characters + + Swagger operation ID: `send_voice`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/voice/send" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -664,6 +765,7 @@ async def send_voice_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -671,7 +773,7 @@ async def send_voice_async( return json.loads(response.text) - async def delete_list_async( + def delete_list( self, list_id: int, *, @@ -684,13 +786,29 @@ async def delete_list_async( Delete List Delete a specific contact list + + Swagger operation ID: `delete_list`. + + Args: + list_id: You may use the Search Contact List action OR Get Contact + List action to get the List ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/lists/{quote(str(list_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -704,6 +822,7 @@ async def delete_list_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -711,9 +830,9 @@ async def delete_list_async( return json.loads(response.text) - async def create_list_contact_async( + def create_list_contact( self, - input: CreateListContactInput, + input: CreateListContactInput | Mapping[str, Any], list_id: int, *, timeout: Optional[float] = None, @@ -725,13 +844,31 @@ async def create_list_contact_async( Create New Contact Create New Contact + + Swagger operation ID: `create_list_contact`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + list_id: You may use the Search Contact List action OR Get Contact + List action to get the List ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/lists/{quote(str(list_id), safe='')}/contacts" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -745,6 +882,7 @@ async def create_list_contact_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -752,7 +890,7 @@ async def create_list_contact_async( return json.loads(response.text) - async def view_list_contacts_async( + def view_list_contacts( self, list_id: int, *, @@ -765,13 +903,29 @@ async def view_list_contacts_async( Get Contacts in a List Get all Contacts in a List + + Swagger operation ID: `view_list_contacts`. + + Args: + list_id: You may use the Search Contact List action OR Get Contact + List action to get the List ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/lists/{quote(str(list_id), safe='')}/contacts" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -785,6 +939,7 @@ async def view_list_contacts_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -792,7 +947,7 @@ async def view_list_contacts_async( return json.loads(response.text) - async def delete_list_contact_async( + def delete_list_contact( self, list_id: int, contact_id: int, @@ -806,6 +961,23 @@ async def delete_list_contact_async( Delete a Contact Delete a Contact + + Swagger operation ID: `delete_list_contact`. + + Args: + list_id: You may use the Search Contact List action OR Get Contact + List action to get the List ID. + contact_id: Contact ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -815,7 +987,7 @@ async def delete_list_contact_async( f"/{quote(str(contact_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -829,6 +1001,7 @@ async def delete_list_contact_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -836,9 +1009,9 @@ async def delete_list_contact_async( return json.loads(response.text) - async def send_mms_async( + def send_mms( self, - input: SendMmsInput, + input: SendMmsInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -849,10 +1022,26 @@ async def send_mms_async( Send MMS Send MMS + + Swagger operation ID: `send_mms`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/mms/send" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -866,6 +1055,7 @@ async def send_mms_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -873,9 +1063,9 @@ async def send_mms_async( return json.loads(response.text) - async def send_fax_async( + def send_fax( self, - input: SendFaxInput, + input: SendFaxInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -886,10 +1076,26 @@ async def send_fax_async( Send Fax Send Fax + + Swagger operation ID: `send_fax`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/fax/send" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -903,6 +1109,7 @@ async def send_fax_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -910,9 +1117,9 @@ async def send_fax_async( return json.loads(response.text) - async def upload_media_async( + def upload_media( self, - input: UploadMediaInput, + input: UploadMediaInput | Mapping[str, Any], convert: str, *, timeout: Optional[float] = None, @@ -924,6 +1131,23 @@ async def upload_media_async( Convert Media File Format Convert Media File Format + + Swagger operation ID: `upload_media`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + convert: Select action the file is needed for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/uploads" query_params = [] @@ -934,7 +1158,7 @@ async def upload_media_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -948,6 +1172,7 @@ async def upload_media_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -955,7 +1180,7 @@ async def upload_media_async( return json.loads(response.text) - async def search_contact_list_async( + def search_contact_list( self, q: str, *, @@ -968,6 +1193,21 @@ async def search_contact_list_async( Search Contact Lists Get list of searched contact list + + Swagger operation ID: `search_contact_list`. + + Args: + q: Search for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/search/contacts-lists" query_params = [] @@ -978,7 +1218,7 @@ async def search_contact_list_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -992,6 +1232,7 @@ async def search_contact_list_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -999,9 +1240,9 @@ async def search_contact_list_async( return json.loads(response.text) - async def send_letter_async( + def send_letter( self, - input: SendLetterInput, + input: SendLetterInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1012,10 +1253,26 @@ async def send_letter_async( Send Letter Send Letter + + Swagger operation ID: `send_letter`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/post/letters/send" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1029,6 +1286,7 @@ async def send_letter_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1036,9 +1294,9 @@ async def send_letter_async( return json.loads(response.text) - async def send_postcard_async( + def send_postcard( self, - input: SendPostcardInput, + input: SendPostcardInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1049,10 +1307,26 @@ async def send_postcard_async( Send Postcard Send one or more postcards + + Swagger operation ID: `send_postcard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/post/postcards/send" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1066,6 +1340,7 @@ async def send_postcard_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/cloudconvert.py b/src/azure/connectors/cloudconvert.py index 3ec9022..219fd4a 100644 --- a/src/azure/connectors/cloudconvert.py +++ b/src/azure/connectors/cloudconvert.py @@ -5,14 +5,13 @@ from __future__ import annotations -from dataclasses import dataclass +from dataclasses import dataclass, field as dataclass_field from typing import Optional, Dict, Any, Mapping from urllib.parse import quote import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, @@ -20,6 +19,19 @@ ConnectorResponseHook, ) +__all__ = [ + "CloudconvertClient", + "CaptureWebsiteInput", + "ConvertFileInput", + "GetCaptureWebsiteOptionsResponse", + "GetConvertOptionsResponse", + "GetMergeInputsResponse", + "GetMergeOptionsResponse", + "GetOptimizeOptionsResponse", + "MergeFilesInput", + "OptimizeFileInput", +] + # Type Definitions @@ -29,7 +41,7 @@ class ConvertFileInput: Convert File """ - tasks: Optional[Dict[str, Any]] = None + tasks: Dict[str, Any] """tasks""" @@ -39,7 +51,7 @@ class OptimizeFileInput: Compress File """ - tasks: Optional[Dict[str, Any]] = None + tasks: Dict[str, Any] """tasks""" @@ -49,7 +61,7 @@ class CaptureWebsiteInput: Create Website Screenshot """ - tasks: Optional[Dict[str, Any]] = None + tasks: Dict[str, Any] """tasks""" @@ -59,10 +71,10 @@ class MergeFilesInput: Merge Files """ - number_of_inputs: Optional[int] = None + number_of_inputs: int """Number of input files to merge.""" - additional_inputs: Optional[Dict[str, Any]] = None - tasks: Optional[Dict[str, Any]] = None + additional_inputs: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + tasks: Dict[str, Any] """tasks""" @@ -72,7 +84,7 @@ class GetConvertOptionsResponse: Response for Get Convert Options """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -81,7 +93,7 @@ class GetOptimizeOptionsResponse: Response for Get Optimize Options """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -90,7 +102,7 @@ class GetCaptureWebsiteOptionsResponse: Response for Get Capture Website Options """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -99,7 +111,7 @@ class GetMergeInputsResponse: Response for Get Merge Inputs """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -108,7 +120,7 @@ class GetMergeOptionsResponse: Response for Get Merge Options """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) # Client Class @@ -119,16 +131,16 @@ class CloudconvertClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -139,8 +151,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -148,8 +160,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -161,7 +173,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -176,9 +188,9 @@ def __init__( def connector_name(self) -> str: return "cloudconvert" - async def convert_file_async( + def convert_file( self, - input: ConvertFileInput, + input: ConvertFileInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -189,10 +201,26 @@ async def convert_file_async( Convert File Convert a file to another format + + Swagger operation ID: `ConvertFile`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/flow/jobs/convertfile" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -206,13 +234,14 @@ async def convert_file_async( request_url, response.status, response.text, + response=response, ) return response.content - async def optimize_file_async( + def optimize_file( self, - input: OptimizeFileInput, + input: OptimizeFileInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -223,10 +252,26 @@ async def optimize_file_async( Compress File Compress a PDF, PNG or JPG file + + Swagger operation ID: `OptimizeFile`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/flow/jobs/optimize" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -240,13 +285,14 @@ async def optimize_file_async( request_url, response.status, response.text, + response=response, ) return response.content - async def capture_website_async( + def capture_website( self, - input: CaptureWebsiteInput, + input: CaptureWebsiteInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -257,12 +303,28 @@ async def capture_website_async( Create Website Screenshot Create a website screenshot as PDF, PNG or JPG + + Swagger operation ID: `CaptureWebsite`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/jobs/capture-website" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -276,13 +338,14 @@ async def capture_website_async( request_url, response.status, response.text, + response=response, ) return response.content - async def merge_files_async( + def merge_files( self, - input: MergeFilesInput, + input: MergeFilesInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -293,10 +356,26 @@ async def merge_files_async( Merge Files Merge multiple files in one PDF + + Swagger operation ID: `MergeFiles`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/flow/jobs/merge" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -310,15 +389,16 @@ async def merge_files_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_convert_options_async( + def get_convert_options( self, + *, input_format: Optional[str] = None, output_format: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -326,6 +406,22 @@ async def get_convert_options_async( ) -> dict[str, Any] | None: """ Get Convert Options + + Swagger operation ID: `GetConvertOptions`. + + Args: + input_format: input_format. + output_format: output_format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/flow/options/convert" query_params = [] @@ -342,7 +438,7 @@ async def get_convert_options_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -356,6 +452,7 @@ async def get_convert_options_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -363,10 +460,10 @@ async def get_convert_options_async( return json.loads(response.text) - async def get_optimize_options_async( + def get_optimize_options( self, - input_format: Optional[str] = None, *, + input_format: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -374,6 +471,21 @@ async def get_optimize_options_async( ) -> dict[str, Any] | None: """ Get Optimize Options + + Swagger operation ID: `GetOptimizeOptions`. + + Args: + input_format: input_format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/flow/options/optimize" query_params = [] @@ -385,7 +497,7 @@ async def get_optimize_options_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -399,6 +511,7 @@ async def get_optimize_options_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -406,10 +519,10 @@ async def get_optimize_options_async( return json.loads(response.text) - async def get_capture_website_options_async( + def get_capture_website_options( self, - output_format: Optional[str] = None, *, + output_format: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -417,6 +530,21 @@ async def get_capture_website_options_async( ) -> dict[str, Any] | None: """ Get Capture Website Options + + Swagger operation ID: `GetCaptureWebsiteOptions`. + + Args: + output_format: output_format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/options/capture-website" @@ -430,7 +558,7 @@ async def get_capture_website_options_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -444,6 +572,7 @@ async def get_capture_website_options_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -451,10 +580,10 @@ async def get_capture_website_options_async( return json.loads(response.text) - async def get_merge_inputs_async( + def get_merge_inputs( self, - number_of_inputs: Optional[int] = None, *, + number_of_inputs: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -462,6 +591,21 @@ async def get_merge_inputs_async( ) -> dict[str, Any] | None: """ Get Merge Inputs + + Swagger operation ID: `GetMergeInputs`. + + Args: + number_of_inputs: number_of_inputs. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/flow/inputs/merge" query_params = [] @@ -473,7 +617,7 @@ async def get_merge_inputs_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -487,6 +631,7 @@ async def get_merge_inputs_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -494,10 +639,10 @@ async def get_merge_inputs_async( return json.loads(response.text) - async def get_merge_options_async( + def get_merge_options( self, - output_format: Optional[str] = None, *, + output_format: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -505,6 +650,21 @@ async def get_merge_options_async( ) -> dict[str, Any] | None: """ Get Merge Options + + Swagger operation ID: `GetMergeOptions`. + + Args: + output_format: output_format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/flow/options/merge" query_params = [] @@ -516,7 +676,7 @@ async def get_merge_options_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -530,6 +690,7 @@ async def get_merge_options_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/cloudmersiveconvert.py b/src/azure/connectors/cloudmersiveconvert.py index c2ea094..b022941 100644 --- a/src/azure/connectors/cloudmersiveconvert.py +++ b/src/azure/connectors/cloudmersiveconvert.py @@ -5,13 +5,12 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, Dict, List, Any, Mapping import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, @@ -19,6 +18,203 @@ ConnectorResponseHook, ) +__all__ = [ + "CloudmersiveconvertClient", + "AddPdfAnnotationRequest", + "AlternateFileFormatCandidate", + "AutodetectDocumentValidationResult", + "AutodetectGetInfoResult", + "AutodetectToPngResult", + "Base64DecodeRequest", + "Base64DecodeResponse", + "Base64DetectRequest", + "Base64DetectResponse", + "Base64EncodeRequest", + "Base64EncodeResponse", + "ChangeLineEndingResponse", + "ClearXlsxCellRequest", + "ClearXlsxCellResponse", + "ConvertDataJsonToXmlInput", + "ConvertWebHtmlToPngResponse", + "ConvertedPngPage", + "CreateBlankDocxRequest", + "CreateBlankDocxResponse", + "CreateBlankSpreadsheetRequest", + "CreateBlankSpreadsheetResponse", + "CreateSpreadsheetFromDataRequest", + "CreateSpreadsheetFromDataResponse", + "CreateZipArchiveRequest", + "DeleteDocxTableRowRangeRequest", + "DeleteDocxTableRowRangeResponse", + "DeleteDocxTableRowRequest", + "DeleteDocxTableRowResponse", + "DetectLineEndingsResponse", + "DocumentValidationError", + "DocumentValidationResult", + "DocxBody", + "DocxCellStyle", + "DocxComment", + "DocxFooter", + "DocxHeader", + "DocxImage", + "DocxInsertCommentOnParagraphRequest", + "DocxInsertImageRequest", + "DocxInsertImageResponse", + "DocxPage", + "DocxParagraph", + "DocxRemoveObjectRequest", + "DocxRemoveObjectResponse", + "DocxRun", + "DocxSection", + "DocxSetFooterAddPageNumberRequest", + "DocxSetFooterRequest", + "DocxSetFooterResponse", + "DocxSetHeaderRequest", + "DocxSetHeaderResponse", + "DocxStyle", + "DocxTable", + "DocxTableCell", + "DocxTableRow", + "DocxTemplateApplicationRequest", + "DocxTemplateOperation", + "DocxText", + "DocxTopLevelComment", + "EditDocumentXlsxDeleteWorksheetResponse", + "ExifValue", + "FindRegexMatch", + "FindStringMatch", + "FindStringRegexRequest", + "FindStringRegexResponse", + "FindStringSimpleRequest", + "FindStringSimpleResponse", + "FinishEditingRequest", + "GetDocxBodyRequest", + "GetDocxBodyResponse", + "GetDocxCommentsHierarchicalResponse", + "GetDocxCommentsResponse", + "GetDocxGetCommentsHierarchicalRequest", + "GetDocxGetCommentsRequest", + "GetDocxHeadersAndFootersRequest", + "GetDocxHeadersAndFootersResponse", + "GetDocxImagesRequest", + "GetDocxImagesResponse", + "GetDocxPagesRequest", + "GetDocxPagesResponse", + "GetDocxSectionsRequest", + "GetDocxSectionsResponse", + "GetDocxStylesRequest", + "GetDocxStylesResponse", + "GetDocxTableByIndexRequest", + "GetDocxTableByIndexResponse", + "GetDocxTableRowRequest", + "GetDocxTableRowResponse", + "GetDocxTablesRequest", + "GetDocxTablesResponse", + "GetImageInfoResult", + "GetPdfAnnotationsResult", + "GetXlsxCellByIdentifierRequest", + "GetXlsxCellByIdentifierResponse", + "GetXlsxCellRequest", + "GetXlsxCellResponse", + "GetXlsxColumnsRequest", + "GetXlsxColumnsResponse", + "GetXlsxImagesRequest", + "GetXlsxImagesResponse", + "GetXlsxRowsAndCellsRequest", + "GetXlsxRowsAndCellsResponse", + "GetXlsxStylesRequest", + "GetXlsxStylesResponse", + "GetXlsxWorksheetsRequest", + "GetXlsxWorksheetsResponse", + "HtmlMdResult", + "HtmlTemplateApplicationRequest", + "HtmlTemplateApplicationResponse", + "HtmlTemplateOperation", + "HtmlToOfficeRequest", + "HtmlToPdfRequest", + "HtmlToPngRequest", + "HtmlToTextRequest", + "HtmlToTextResponse", + "InsertDocxCommentOnParagraphResponse", + "InsertDocxInsertParagraphRequest", + "InsertDocxInsertParagraphResponse", + "InsertDocxTableRowRequest", + "InsertDocxTableRowResponse", + "InsertDocxTablesRequest", + "InsertDocxTablesResponse", + "InsertXlsxWorksheetRequest", + "InsertXlsxWorksheetResponse", + "MultipageImageFormatConversionResult", + "PageConversionResult", + "PdfAnnotation", + "PdfDocument", + "PdfFormField", + "PdfFormFields", + "PdfMetadata", + "PdfPageText", + "PdfTextByPageResult", + "PdfToPngResult", + "PresentationResult", + "RemoveDocxHeadersAndFootersRequest", + "RemoveDocxHeadersAndFootersResponse", + "RemoveDocxPagesRequest", + "RemoveHtmlFromTextRequest", + "RemoveHtmlFromTextResponse", + "RemovePptxSlidesRequest", + "RemoveWhitespaceFromTextRequest", + "RemoveWhitespaceFromTextResponse", + "RemoveXlsxWorksheetRequest", + "ReplaceStringRegexRequest", + "ReplaceStringRegexResponse", + "ReplaceStringRequest", + "ReplaceStringSimpleRequest", + "ReplaceStringSimpleResponse", + "ScreenshotRequest", + "SetFormFieldValue", + "SetPdfFormFieldsRequest", + "SetPdfMetadataRequest", + "SetXlsxCellByIdentifierRequest", + "SetXlsxCellByIdentifierResponse", + "SetXlsxCellRequest", + "SetXlsxCellResponse", + "SplitDocumentResult", + "SplitDocxDocumentResult", + "SplitPdfResult", + "SplitPptxPresentationResult", + "SplitTextDocumentByLinesResult", + "SplitTextDocumentByStringResult", + "SplitXlsxWorksheetResult", + "TextConversionResult", + "TextDocumentElement", + "TextDocumentLine", + "TextEncodingDetectResponse", + "UpdateDocxTableCellRequest", + "UpdateDocxTableCellResponse", + "UpdateDocxTableRowRequest", + "UpdateDocxTableRowResponse", + "UrlToTextRequest", + "UrlToTextResponse", + "ViewerResponse", + "WorksheetResult", + "XlsxImage", + "XlsxSpreadsheetCell", + "XlsxSpreadsheetColumn", + "XlsxSpreadsheetRow", + "XlsxWorksheet", + "XmlAddAttributeWithXPathResult", + "XmlAddChildWithXPathResult", + "XmlFilterWithXPathResult", + "XmlQueryWithXQueryMultiResult", + "XmlQueryWithXQueryResult", + "XmlRemoveAllChildrenWithXPathResult", + "XmlRemoveWithXPathResult", + "XmlReplaceWithXPathResult", + "XmlSetValueWithXPathResult", + "ZipDirectory", + "ZipExtractResponse", + "ZipFile", +] + # Type Definitions @@ -28,16 +224,18 @@ class CreateBlankDocxResponse: Response for Create a blank Word DOCX document """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited XLSX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -49,16 +247,18 @@ class DeleteDocxTableRowResponse: Response for Deletes a table row in an existing table in a Word DOCX document """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited DOCX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -70,16 +270,18 @@ class DeleteDocxTableRowRangeResponse: Response for Deletes a range of multiple table rows in an existing table in a Word """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited DOCX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -91,13 +293,15 @@ class GetDocxBodyResponse: Response for Get body from a Word DOCX document """ - body: Optional[DocxBody] = field( + body: Optional[DocxBody | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Body"}, ) """Body in the DOCX document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -109,18 +313,21 @@ class GetDocxCommentsHierarchicalResponse: Response for Get comments from a Word DOCX document hierarchically """ - comments: Optional[List[DocxTopLevelComment]] = field( + comments: Optional[List[DocxTopLevelComment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Comments in the document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" - top_level_comment_count: Optional[int] = field( + top_level_comment_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TopLevelCommentCount"}, ) """The number of comments in the document""" @@ -132,16 +339,19 @@ class GetDocxHeadersAndFootersResponse: Response for Get content of a footer from a Word DOCX document """ - footers: Optional[List[DocxFooter]] = field( + footers: Optional[List[DocxFooter | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Footers"}, ) - headers: Optional[List[DocxHeader]] = field( + headers: Optional[List[DocxHeader | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Headers"}, ) - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -153,13 +363,15 @@ class GetDocxImagesResponse: Response for Get images from a Word DOCX document """ - images: Optional[List[DocxImage]] = field( + images: Optional[List[DocxImage | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Images"}, ) """Images in the DOCX document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -171,18 +383,21 @@ class GetDocxPagesResponse: Response for Get pages and content from a Word DOCX document """ - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PageCount"}, ) """Count of pages""" - pages: Optional[List[DocxPage]] = field( + pages: Optional[List[DocxPage | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Pages"}, ) """Pages in the document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -194,13 +409,15 @@ class GetDocxSectionsResponse: Response for Get sections from a Word DOCX document """ - sections: Optional[List[DocxSection]] = field( + sections: Optional[List[DocxSection | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sections"}, ) """Sections in the DOCX document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -212,13 +429,15 @@ class GetDocxStylesResponse: Response for Get styles from a Word DOCX document """ - styles: Optional[List[DocxStyle]] = field( + styles: Optional[List[DocxStyle | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Styles"}, ) """Styles in the DOCX document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -230,13 +449,15 @@ class GetDocxTableRowResponse: Response for Gets the contents of an existing table row in an existing table in a W """ - row_result: Optional[DocxTableRow] = field( + row_result: Optional[DocxTableRow | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RowResult"}, ) """Contents of the table row that was requested""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -248,13 +469,15 @@ class GetDocxTableByIndexResponse: Response for Get a specific table by index in a Word DOCX document """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" - table: Optional[DocxTable] = field( + table: Optional[DocxTable | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Table"}, ) """Requested Table in the DOCX file""" @@ -266,13 +489,15 @@ class GetDocxTablesResponse: Response for Get all tables in Word DOCX document """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" - tables: Optional[List[DocxTable]] = field( + tables: Optional[List[DocxTable | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Tables"}, ) """Tables in the DOCX file""" @@ -284,16 +509,18 @@ class InsertDocxCommentOnParagraphResponse: Response for Insert a new comment into a Word DOCX document attached to a paragraph """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited DOCX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -305,16 +532,18 @@ class DocxInsertImageResponse: Response for Insert image into a Word DOCX document """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited DOCX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -326,16 +555,18 @@ class InsertDocxInsertParagraphResponse: Response for Insert a new paragraph into a Word DOCX document """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited DOCX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -347,16 +578,18 @@ class InsertDocxTablesResponse: Response for Insert a new table into a Word DOCX document """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited DOCX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -368,16 +601,18 @@ class InsertDocxTableRowResponse: Response for Insert a new row into an existing table in a Word DOCX document """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited DOCX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -389,8 +624,9 @@ class RemoveDocxHeadersAndFootersResponse: Response for Remove headers and footers from Word DOCX document """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ @@ -399,8 +635,9 @@ class RemoveDocxHeadersAndFootersResponse: in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -412,16 +649,18 @@ class DocxRemoveObjectResponse: Response for Delete any object in a Word DOCX document """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited DOCX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -433,16 +672,18 @@ class DocxSetFooterResponse: Response for Set the footer in a Word DOCX document """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited DOCX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -454,16 +695,18 @@ class DocxSetHeaderResponse: Response for Set the header in a Word DOCX document """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited DOCX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -475,16 +718,18 @@ class UpdateDocxTableCellResponse: Response for Update, set contents of a table cell in an existing table in a Word DO """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited DOCX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -496,16 +741,18 @@ class UpdateDocxTableRowResponse: Response for Update, set contents of a table row in an existing table in a Word DOCX document """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited DOCX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -517,16 +764,18 @@ class ClearXlsxCellResponse: Response for Clear cell contents in an Excel XLSX spreadsheet, worksheet by index """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited XLSX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -538,16 +787,18 @@ class CreateBlankSpreadsheetResponse: Response for Create a blank Excel XLSX spreadsheet """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited XLSX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -559,16 +810,18 @@ class CreateSpreadsheetFromDataResponse: Response for Create a new Excel XLSX spreadsheet from column and row data """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited XLSX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -580,7 +833,7 @@ class EditDocumentXlsxDeleteWorksheetResponse: Response for Delete, remove worksheet from an Excel XLSX spreadsheet document """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -593,13 +846,15 @@ class GetXlsxCellByIdentifierResponse: Response for Get cell from an Excel XLSX spreadsheet, worksheet by cell identifier """ - cell: Optional[XlsxSpreadsheetCell] = field( + cell: Optional[XlsxSpreadsheetCell | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Cell"}, ) """Requested Cell in the Excel XLSX document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -611,13 +866,15 @@ class GetXlsxCellResponse: Response for Get cell from an Excel XLSX spreadsheet, worksheet by index """ - cell: Optional[XlsxSpreadsheetCell] = field( + cell: Optional[XlsxSpreadsheetCell | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Cell"}, ) """Requested Cell in the Excel XLSX document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -629,13 +886,15 @@ class GetXlsxColumnsResponse: Response for Get rows and cells from a Excel XLSX spreadsheet, worksheet """ - columns: Optional[List[XlsxSpreadsheetColumn]] = field( + columns: Optional[List[XlsxSpreadsheetColumn | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Columns"}, ) """Spreadsheet Columns in the XLSX document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -647,13 +906,15 @@ class GetXlsxImagesResponse: Response for Get images from a Excel XLSX spreadsheet, worksheet """ - images: Optional[List[XlsxImage]] = field( + images: Optional[List[XlsxImage | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Images"}, ) """Spreadsheet Images in the XLSX document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -665,13 +926,15 @@ class GetXlsxRowsAndCellsResponse: Response for Get rows and cells from a Excel XLSX spreadsheet, worksheet """ - rows: Optional[List[XlsxSpreadsheetRow]] = field( + rows: Optional[List[XlsxSpreadsheetRow | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Rows"}, ) """Spreadsheet Rows in the Excel XLSX document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -683,13 +946,15 @@ class GetXlsxStylesResponse: Response for Get styles from a Excel XLSX spreadsheet, worksheet """ - cell_styles: Optional[List[DocxCellStyle]] = field( + cell_styles: Optional[List[DocxCellStyle | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellStyles"}, ) """Cell styles""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -701,13 +966,15 @@ class GetXlsxWorksheetsResponse: Response for Get worksheets from a Excel XLSX spreadsheet """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" - worksheets: Optional[List[XlsxWorksheet]] = field( + worksheets: Optional[List[XlsxWorksheet | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Worksheets"}, ) """Worksheets in the Excel XLSX spreadsheet""" @@ -719,16 +986,18 @@ class InsertXlsxWorksheetResponse: Response for Insert a new worksheet into an Excel XLSX spreadsheet """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited XLSX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -740,16 +1009,18 @@ class SetXlsxCellByIdentifierResponse: Response for Set, update cell contents in an Excel XLSX spreadsheet, worksheet by c """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited XLSX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -761,16 +1032,18 @@ class SetXlsxCellResponse: Response for Set, update cell contents in an Excel XLSX spreadsheet, worksheet by index """ - edited_document_u_r_l: Optional[str] = field( + edited_document_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EditedDocumentURL"}, ) """ URL to the edited XLSX file; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the result document contents. """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -782,7 +1055,7 @@ class ConvertDataJsonToXmlInput: Convert JSON to XML conversion """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -795,13 +1068,15 @@ class HtmlTemplateApplicationResponse: Response for Apply HTML template """ - final_html: Optional[str] = field( + final_html: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FinalHtml"}, ) """Final HTML result of all operations on input""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -813,7 +1088,7 @@ class ConvertWebHtmlToPngResponse: Response for Convert HTML string to PNG screenshot """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -826,13 +1101,15 @@ class HtmlToTextResponse: Response for Convert HTML string to text (txt) """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" - text_content_result: Optional[str] = field( + text_content_result: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContentResult"}, ) """Text content result from the HTML input""" @@ -844,13 +1121,15 @@ class UrlToTextResponse: Response for Convert website URL page to text (txt) """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" - text_content_result: Optional[str] = field( + text_content_result: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContentResult"}, ) """Text content result from the URL website input""" @@ -862,13 +1141,15 @@ class AddPdfAnnotationRequest: Definition: AddPdfAnnotationRequest """ - annotations_to_add: Optional[List[PdfAnnotation]] = field( + annotations_to_add: Optional[List[PdfAnnotation | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AnnotationsToAdd"}, ) """Annotations to add to the PDF file""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Input file contents bytes for the file to modify""" @@ -880,18 +1161,21 @@ class AlternateFileFormatCandidate: Definition: AlternateFileFormatCandidate """ - detected_file_extension: Optional[str] = field( + detected_file_extension: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DetectedFileExtension"}, ) """Detected file extension of the file format, with a leading period""" - detected_mime_type: Optional[str] = field( + detected_mime_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DetectedMimeType"}, ) """MIME type of this file extension""" - probability: Optional[float] = field( + probability: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Probability"}, ) """ @@ -906,27 +1190,34 @@ class AutodetectDocumentValidationResult: Definition: AutodetectDocumentValidationResult """ - document_is_valid: Optional[bool] = field( + document_is_valid: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DocumentIsValid"}, ) """True if the document is valid and has no errors, false otherwise""" - error_count: Optional[int] = field( + error_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ErrorCount"}, ) """Number of validation errors found in the document""" - errors_and_warnings: Optional[List[DocumentValidationError]] = field( + errors_and_warnings: Optional[ + List[DocumentValidationError | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ErrorsAndWarnings"}, ) """Details of errors and warnings found""" - file_format_extension: Optional[str] = field( + file_format_extension: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileFormatExtension"}, ) - warning_count: Optional[int] = field( + warning_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WarningCount"}, ) """Number of validation warnings found in the document""" @@ -938,39 +1229,47 @@ class AutodetectGetInfoResult: Definition: AutodetectGetInfoResult """ - alternate_file_type_candidates: Optional[List[AlternateFileFormatCandidate]] = field( + alternate_file_type_candidates: Optional[ + List[AlternateFileFormatCandidate | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AlternateFileTypeCandidates"}, ) """Alternate file type options and their probability""" - author: Optional[str] = field( + author: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Author"}, ) """ User name of the creator/author of the document, if available, null if not available """ - date_modified: Optional[str] = field( + date_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) """ The timestamp that the document was last modified, if available, null if not available """ - detected_file_extension: Optional[str] = field( + detected_file_extension: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DetectedFileExtension"}, ) """Detected file extension of the file format, with a leading period""" - detected_mime_type: Optional[str] = field( + detected_mime_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DetectedMimeType"}, ) """MIME type of this file extension""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PageCount"}, ) """ @@ -979,8 +1278,9 @@ class AutodetectGetInfoResult: Contains 0 when the page count cannot be determined, or if the concept of page count does not apply (e.g. for an image) """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -992,13 +1292,15 @@ class AutodetectToPngResult: Definition: AutodetectToPngResult """ - png_result_pages: Optional[List[ConvertedPngPage]] = field( + png_result_pages: Optional[List[ConvertedPngPage | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PngResultPages"}, ) """Array of converted pages""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -1010,8 +1312,9 @@ class Base64DecodeRequest: Definition: Base64DecodeRequest """ - base64_content_to_decode: Optional[str] = field( + base64_content_to_decode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Base64ContentToDecode"}, ) """Input content to decode from Base 64 into binary""" @@ -1023,13 +1326,15 @@ class Base64DecodeResponse: Definition: Base64DecodeResponse """ - content_result: Optional[str] = field( + content_result: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentResult"}, ) """Result of performing a base 64 decode operation, binary file content""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -1041,8 +1346,9 @@ class Base64DetectRequest: Definition: Base64DetectRequest """ - base64_content_to_detect: Optional[str] = field( + base64_content_to_detect: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Base64ContentToDetect"}, ) """Input content text to detect if it is base 64 encoded""" @@ -1054,13 +1360,15 @@ class Base64DetectResponse: Definition: Base64DetectResponse """ - is_base64_encoded: Optional[bool] = field( + is_base64_encoded: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsBase64Encoded"}, ) """True if the input string is base 64 encoded, false otherwise""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -1072,8 +1380,9 @@ class Base64EncodeRequest: Definition: Base64EncodeRequest """ - content_to_encode: Optional[str] = field( + content_to_encode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentToEncode"}, ) """Input content to encode into Base 64""" @@ -1085,16 +1394,18 @@ class Base64EncodeResponse: Definition: Base64EncodeResponse """ - base64_text_content_result: Optional[str] = field( + base64_text_content_result: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Base64TextContentResult"}, ) """ Result of performing a base 64 encoding operation, a text string representing the encoded original file content """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -1106,13 +1417,15 @@ class ChangeLineEndingResponse: Definition: ChangeLineEndingResponse """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" - text_content_result: Optional[str] = field( + text_content_result: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContentResult"}, ) """Text content result""" @@ -1124,18 +1437,21 @@ class ClearXlsxCellRequest: Definition: ClearXlsxCellRequest """ - cell_index: Optional[int] = field( + cell_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellIndex"}, ) """0-based index of the cell, 0, 1, 2, ... in the row to clear""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -1144,13 +1460,15 @@ class ClearXlsxCellRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - row_index: Optional[int] = field( + row_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RowIndex"}, ) """0-based index of the row, 0, 1, 2, ... to clear""" - worksheet_to_update: Optional[XlsxWorksheet] = field( + worksheet_to_update: Optional[XlsxWorksheet | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetToUpdate"}, ) """ @@ -1165,12 +1483,17 @@ class ConvertedPngPage: Definition: ConvertedPngPage """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PageNumber"}, ) """Page number of the converted page, starting with 1""" - u_r_l: Optional[str] = field(default=None, metadata={"wire_name": "URL"}) + u_r_l: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "URL"}, + ) """ URL to the PNG file of this page; file is stored in an in-memory cache and will be deleted @@ -1183,8 +1506,9 @@ class CreateBlankDocxRequest: Definition: CreateBlankDocxRequest """ - initial_text: Optional[str] = field( + initial_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InitialText"}, ) """Optional; initial text to include in the document""" @@ -1196,8 +1520,9 @@ class CreateBlankSpreadsheetRequest: Definition: CreateBlankSpreadsheetRequest """ - worksheet_name: Optional[str] = field( + worksheet_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetName"}, ) """ @@ -1212,13 +1537,15 @@ class CreateSpreadsheetFromDataRequest: Definition: CreateSpreadsheetFromDataRequest """ - rows: Optional[List[XlsxSpreadsheetRow]] = field( + rows: Optional[List[XlsxSpreadsheetRow | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Rows"}, ) """Required; Rows and cells to populate the spreadsheet with""" - worksheet_name: Optional[str] = field( + worksheet_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetName"}, ) """ @@ -1233,16 +1560,18 @@ class CreateZipArchiveRequest: Definition: CreateZipArchiveRequest """ - directories_in_zip: Optional[List[ZipDirectory]] = field( + directories_in_zip: Optional[List[ZipDirectory | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DirectoriesInZip"}, ) """ Top-level directories in the root directory of the zip; directories can contain sub-directories and files """ - files_in_zip: Optional[List[ZipFile]] = field( + files_in_zip: Optional[List[ZipFile | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FilesInZip"}, ) """Top-level files in the root directory fo the zip file""" @@ -1254,13 +1583,15 @@ class DeleteDocxTableRowRangeRequest: Definition: DeleteDocxTableRowRangeRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -1269,21 +1600,24 @@ class DeleteDocxTableRowRangeRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - table_path: Optional[str] = field( + table_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TablePath"}, ) """Path to the table to delete the row from""" - table_row_row_index_end: Optional[int] = field( + table_row_row_index_end: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableRowRowIndexEnd"}, ) """ 0-based index of the row to stop deleting rows (e.g. 0, 1, 2, ...) in the table """ - table_row_row_index_start: Optional[int] = field( + table_row_row_index_start: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableRowRowIndexStart"}, ) """ @@ -1298,13 +1632,15 @@ class DeleteDocxTableRowRequest: Definition: DeleteDocxTableRowRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -1313,13 +1649,15 @@ class DeleteDocxTableRowRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - table_path: Optional[str] = field( + table_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TablePath"}, ) """Path to the table to delete the row from""" - table_row_row_index: Optional[int] = field( + table_row_row_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableRowRowIndex"}, ) """0-based index of the row to delete (e.g. 0, 1, 2, ...) in the table""" @@ -1331,21 +1669,24 @@ class DetectLineEndingsResponse: Definition: DetectLineEndingsResponse """ - input_length: Optional[int] = field( + input_length: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputLength"}, ) """Length of the input string in characters""" - primary_newline_terminator: Optional[str] = field( + primary_newline_terminator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PrimaryNewlineTerminator"}, ) """ Characters used to terminate a newline; can be carriage return, linefeed, or carriage return + linefeed """ - primary_newline_type: Optional[str] = field( + primary_newline_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PrimaryNewlineType"}, ) """ @@ -1353,8 +1694,9 @@ class DetectLineEndingsResponse: uses carriage return only); \"Unix\" (Unix and Linux OSes, and modern Mac OS); \"Windows\" (Windows operating systems) """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -1366,19 +1708,29 @@ class DocumentValidationError: Definition: DocumentValidationError """ - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """Description of the error""" - is_error: Optional[bool] = field( + is_error: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsError"}, ) """True if this is an error, false otherwise""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """XPath to the error""" - uri: Optional[str] = field(default=None, metadata={"wire_name": "Uri"}) + uri: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Uri"}, + ) """URI of the part in question""" @@ -1388,23 +1740,29 @@ class DocumentValidationResult: Definition: DocumentValidationResult """ - document_is_valid: Optional[bool] = field( + document_is_valid: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DocumentIsValid"}, ) """True if the document is valid and has no errors, false otherwise""" - error_count: Optional[int] = field( + error_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ErrorCount"}, ) """Number of validation errors found in the document""" - errors_and_warnings: Optional[List[DocumentValidationError]] = field( + errors_and_warnings: Optional[ + List[DocumentValidationError | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ErrorsAndWarnings"}, ) """Details of errors and warnings found""" - warning_count: Optional[int] = field( + warning_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WarningCount"}, ) """Number of validation warnings found in the document""" @@ -1416,23 +1774,29 @@ class DocxBody: Definition: DocxBody """ - all_paragraphs: Optional[List[DocxParagraph]] = field( + all_paragraphs: Optional[List[DocxParagraph | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AllParagraphs"}, ) """ All paragraphs anywhere in the document; these objects are not sequentially placed but are scatted across document """ - all_tables: Optional[List[DocxTable]] = field( + all_tables: Optional[List[DocxTable | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AllTables"}, ) """ All tables anywhere in the document; these objects are not sequentially placed but are scatted across the document """ - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new tables""" @@ -1442,19 +1806,29 @@ class DocxCellStyle: Definition: DocxCellStyle """ - built_in_id: Optional[int] = field( + built_in_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BuiltInID"}, ) """Built=in ID of the cell style""" - format_id: Optional[int] = field( + format_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FormatID"}, ) """Format ID of the cell style""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Name of the style""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new rows""" @@ -1464,50 +1838,65 @@ class DocxComment: Definition: DocxComment """ - author: Optional[str] = field( + author: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Author"}, ) """Author name of the comment""" - author_initials: Optional[str] = field( + author_initials: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AuthorInitials"}, ) """Initials of the author of the comment""" - comment_date: Optional[str] = field( + comment_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CommentDate"}, ) """Date timestamp of the comment""" - comment_text: Optional[str] = field( + comment_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CommentText"}, ) """Text content of the comment""" - done: Optional[bool] = field(default=None, metadata={"wire_name": "Done"}) + done: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Done"}, + ) """True if this comment is marked as Done in Word, otherwise it is false""" - is_reply: Optional[bool] = field( + is_reply: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsReply"}, ) """True if this comment is a reply to another comment, false otherwise""" - is_top_level: Optional[bool] = field( + is_top_level: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsTopLevel"}, ) """ True if the comment is at the top level, false if this comment is a child reply of another comment """ - parent_comment_path: Optional[str] = field( + parent_comment_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ParentCommentPath"}, ) """ Path to the parent of this comment, if this comment is a reply, otherwise this value will be null """ - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """Path to the comment in the document""" @@ -1517,15 +1906,21 @@ class DocxFooter: Definition: DocxFooter """ - paragraphs: Optional[List[DocxParagraph]] = field( + paragraphs: Optional[List[DocxParagraph | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Paragraphs"}, ) """Paragraphs in this footer""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new tables""" - sections_with_footer: Optional[List[DocxSection]] = field( + sections_with_footer: Optional[List[DocxSection | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SectionsWithFooter"}, ) """Sections that the footer is applied to""" @@ -1537,15 +1932,21 @@ class DocxHeader: Definition: DocxHeader """ - paragraphs: Optional[List[DocxParagraph]] = field( + paragraphs: Optional[List[DocxParagraph | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Paragraphs"}, ) """Paragraphs in this header""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new tables""" - sections_with_header: Optional[List[DocxSection]] = field( + sections_with_header: Optional[List[DocxSection | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SectionsWithHeader"}, ) """Sections that the header is applied to""" @@ -1557,74 +1958,90 @@ class DocxImage: Definition: DocxImage """ - image_contents_u_r_l: Optional[str] = field( + image_contents_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageContentsURL"}, ) """ URL to the image contents; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the contents. """ - image_data_content_type: Optional[str] = field( + image_data_content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageDataContentType"}, ) """Read-only; image data MIME content-type""" - image_data_embed_id: Optional[str] = field( + image_data_embed_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageDataEmbedId"}, ) """Read-only; internal ID for the image contents""" - image_description: Optional[str] = field( + image_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageDescription"}, ) """The Description of the image""" - image_height: Optional[int] = field( + image_height: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageHeight"}, ) """ Height of the image in EMUs (English Metric Units); set to 0 to default to page width and aspect-ratio based height """ - image_id: Optional[int] = field( + image_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageId"}, ) """The Id of the image""" - image_internal_file_name: Optional[str] = field( + image_internal_file_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageInternalFileName"}, ) """Read-only; internal file name/path for the image""" - image_name: Optional[str] = field( + image_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageName"}, ) """The Name of the image""" - image_width: Optional[int] = field( + image_width: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageWidth"}, ) """ Width of the image in EMUs (English Metric Units); set to 0 to default to page width and aspect-ratio based height """ - inline_with_text: Optional[bool] = field( + inline_with_text: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InlineWithText"}, ) """True if the image is inline with the text; false if it is floating""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new tables""" - x_offset: Optional[int] = field( + x_offset: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "XOffset"}, ) """X (horizontal) offset of the image""" - y_offset: Optional[int] = field( + y_offset: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "YOffset"}, ) """Y (vertical) offset of the image""" @@ -1636,18 +2053,21 @@ class DocxInsertCommentOnParagraphRequest: Definition: DocxInsertCommentOnParagraphRequest """ - comment_to_insert: Optional[DocxComment] = field( + comment_to_insert: Optional[DocxComment | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CommentToInsert"}, ) """Comment to insert""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -1656,8 +2076,9 @@ class DocxInsertCommentOnParagraphRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - paragraph_path: Optional[str] = field( + paragraph_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ParagraphPath"}, ) """ @@ -1673,26 +2094,30 @@ class DocxInsertImageRequest: Definition: DocxInsertImageRequest """ - height_in_e_m_us: Optional[int] = field( + height_in_e_m_us: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HeightInEMUs"}, ) """Optional: The height of the image in EMUs""" - image_to_add: Optional[DocxImage] = field( + image_to_add: Optional[DocxImage | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageToAdd"}, ) """ Optional: Image to add; if you supply in this object, do not supply InputImageFileBytes or InputImageFileUrl. """ - input_document_file_bytes: Optional[str] = field( + input_document_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputDocumentFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_document_file_url: Optional[str] = field( + input_document_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputDocumentFileUrl"}, ) """ @@ -1701,16 +2126,18 @@ class DocxInsertImageRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - input_image_file_bytes: Optional[str] = field( + input_image_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputImageFileBytes"}, ) """ Optional: Bytes of the input image file to operate on; if you supply this value do not supply InputImageFileUrl or ImageToAdd. """ - input_image_file_url: Optional[str] = field( + input_image_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputImageFileUrl"}, ) """ @@ -1720,8 +2147,9 @@ class DocxInsertImageRequest: pass in the secure URL result from that operation as the URL here (this URL is not public). """ - insert_path: Optional[str] = field( + insert_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InsertPath"}, ) """ @@ -1729,8 +2157,9 @@ class DocxInsertImageRequest: InsertPath field using the Path value from an existing object. Used with InsertPlacement of BeforeExistingObject or AfterExistingObject """ - insert_placement: Optional[str] = field( + insert_placement: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InsertPlacement"}, ) """ @@ -1741,8 +2170,9 @@ class DocxInsertImageRequest: object), AfterExistingObject (right after an existing object - fill in the InsertPath field using the Path value from an existing object) """ - width_in_e_m_us: Optional[int] = field( + width_in_e_m_us: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WidthInEMUs"}, ) """Optional: The width of the image in EMUs""" @@ -1754,13 +2184,15 @@ class DocxPage: Definition: DocxPage """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PageNumber"}, ) """Page number of this page, 1-based""" - paragraphs: Optional[List[DocxParagraph]] = field( + paragraphs: Optional[List[DocxParagraph | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Paragraphs"}, ) """ @@ -1775,23 +2207,30 @@ class DocxParagraph: Definition: DocxParagraph """ - content_runs: Optional[List[DocxRun]] = field( + content_runs: Optional[List[DocxRun | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentRuns"}, ) """ The content runs in the paragraph - this is where text is stored; similar to a span in HTML """ - paragraph_index: Optional[int] = field( + paragraph_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ParagraphIndex"}, ) """The index of the paragraph; 0-based""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new tables""" - style_id: Optional[str] = field( + style_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StyleID"}, ) """ @@ -1805,13 +2244,15 @@ class DocxRemoveObjectRequest: Definition: DocxRemoveObjectRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -1820,8 +2261,9 @@ class DocxRemoveObjectRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - path_to_object_to_remove: Optional[str] = field( + path_to_object_to_remove: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PathToObjectToRemove"}, ) """ @@ -1836,39 +2278,53 @@ class DocxRun: Definition: DocxRun """ - bold: Optional[bool] = field(default=None, metadata={"wire_name": "Bold"}) + bold: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bold"}, + ) """True to make the text bold, false otherwise""" - font_family: Optional[str] = field( + font_family: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FontFamily"}, ) """Font Family name for the text, e.g. \"Arial\" or \"Times New Roman\"""" - font_size: Optional[str] = field( + font_size: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FontSize"}, ) """Font size in font points (e.g. \"24\")""" - italic: Optional[bool] = field( + italic: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Italic"}, ) """True to make the text italic, false otherwise""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new tables""" - run_index: Optional[int] = field( + run_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RunIndex"}, ) """Index of the run, 0-based""" - text_items: Optional[List[DocxText]] = field( + text_items: Optional[List[DocxText | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextItems"}, ) """ Text items inside the run; this is where the actual text content is stored """ - underline: Optional[str] = field( + underline: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Underline"}, ) """ @@ -1885,10 +2341,15 @@ class DocxSection: Definition: DocxSection """ - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new tables""" - starting_page_numbers: Optional[List[int]] = field( + starting_page_numbers: Optional[List[int]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartingPageNumbers"}, ) """Page numbers that the section starts at, typically just one""" @@ -1900,13 +2361,15 @@ class DocxSetFooterAddPageNumberRequest: Definition: DocxSetFooterAddPageNumberRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -1915,8 +2378,9 @@ class DocxSetFooterAddPageNumberRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - prepend_text: Optional[str] = field( + prepend_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PrependText"}, ) """ @@ -1931,18 +2395,21 @@ class DocxSetFooterRequest: Definition: DocxSetFooterRequest """ - footer_to_apply: Optional[DocxFooter] = field( + footer_to_apply: Optional[DocxFooter | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FooterToApply"}, ) """Footer to apply""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -1959,18 +2426,21 @@ class DocxSetHeaderRequest: Definition: DocxSetHeaderRequest """ - header_to_apply: Optional[DocxHeader] = field( + header_to_apply: Optional[DocxHeader | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HeaderToApply"}, ) """Header to apply""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -1987,32 +2457,45 @@ class DocxStyle: Definition: DocxStyle """ - bold: Optional[bool] = field(default=None, metadata={"wire_name": "Bold"}) + bold: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bold"}, + ) """Style applies bold formatting""" - font_family: Optional[str] = field( + font_family: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FontFamily"}, ) """Font family""" - font_size: Optional[str] = field( + font_size: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FontSize"}, ) """Font size""" - italic: Optional[bool] = field( + italic: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Italic"}, ) """Style applies italic formatting""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new tables""" - style_id: Optional[str] = field( + style_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StyleID"}, ) """ID of the style""" - underline: Optional[bool] = field( + underline: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Underline"}, ) """Style applies underline formatting""" @@ -2024,23 +2507,27 @@ class DocxTable: Definition: DocxTable """ - bottom_border_color: Optional[str] = field( + bottom_border_color: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BottomBorderColor"}, ) """HTML-style color hex value (do not include a #)""" - bottom_border_size: Optional[int] = field( + bottom_border_size: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BottomBorderSize"}, ) """Width of the border in points (1/72nd of an inch)""" - bottom_border_space: Optional[int] = field( + bottom_border_space: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BottomBorderSpace"}, ) """Spacing around the border in points (1/72nd of an inch)""" - bottom_border_type: Optional[str] = field( + bottom_border_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BottomBorderType"}, ) """ @@ -2051,23 +2538,27 @@ class DocxTable: ThinThickSmallGap, ThinThickThinLargeGap, ThinThickThinMediumGap, ThinThickThinSmallGap, ThreeDEmboss, ThreeDEngrave, Triple, Wave """ - cell_horizontal_border_color: Optional[str] = field( + cell_horizontal_border_color: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellHorizontalBorderColor"}, ) """HTML-style color hex value (do not include a #)""" - cell_horizontal_border_size: Optional[int] = field( + cell_horizontal_border_size: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellHorizontalBorderSize"}, ) """Width of the border in points (1/72nd of an inch)""" - cell_horizontal_border_space: Optional[int] = field( + cell_horizontal_border_space: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellHorizontalBorderSpace"}, ) """Spacing around the border in points (1/72nd of an inch)""" - cell_horizontal_border_type: Optional[str] = field( + cell_horizontal_border_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellHorizontalBorderType"}, ) """ @@ -2078,23 +2569,27 @@ class DocxTable: ThinThickSmallGap, ThinThickThinLargeGap, ThinThickThinMediumGap, ThinThickThinSmallGap, ThreeDEmboss, ThreeDEngrave, Triple, Wave """ - cell_vertical_border_color: Optional[str] = field( + cell_vertical_border_color: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellVerticalBorderColor"}, ) """HTML-style color hex value (do not include a #)""" - cell_vertical_border_size: Optional[int] = field( + cell_vertical_border_size: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellVerticalBorderSize"}, ) """Width of the border in points (1/72nd of an inch)""" - cell_vertical_border_space: Optional[int] = field( + cell_vertical_border_space: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellVerticalBorderSpace"}, ) """Spacing around the border in points (1/72nd of an inch)""" - cell_vertical_border_type: Optional[str] = field( + cell_vertical_border_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellVerticalBorderType"}, ) """ @@ -2105,23 +2600,27 @@ class DocxTable: ThinThickSmallGap, ThinThickThinLargeGap, ThinThickThinMediumGap, ThinThickThinSmallGap, ThreeDEmboss, ThreeDEngrave, Triple, Wave """ - end_border_color: Optional[str] = field( + end_border_color: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EndBorderColor"}, ) """HTML-style color hex value (do not include a #)""" - end_border_size: Optional[int] = field( + end_border_size: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EndBorderSize"}, ) """Width of the border in points (1/72nd of an inch)""" - end_border_space: Optional[int] = field( + end_border_space: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EndBorderSpace"}, ) """Spacing around the border in points (1/72nd of an inch)""" - end_border_type: Optional[str] = field( + end_border_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EndBorderType"}, ) """ @@ -2132,23 +2631,27 @@ class DocxTable: ThinThickSmallGap, ThinThickThinLargeGap, ThinThickThinMediumGap, ThinThickThinSmallGap, ThreeDEmboss, ThreeDEngrave, Triple, Wave """ - left_border_color: Optional[str] = field( + left_border_color: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LeftBorderColor"}, ) """HTML-style color hex value (do not include a #)""" - left_border_size: Optional[int] = field( + left_border_size: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LeftBorderSize"}, ) """Width of the border in points (1/72nd of an inch)""" - left_border_space: Optional[int] = field( + left_border_space: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LeftBorderSpace"}, ) """Spacing around the border in points (1/72nd of an inch)""" - left_border_type: Optional[str] = field( + left_border_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LeftBorderType"}, ) """ @@ -2159,27 +2662,35 @@ class DocxTable: ThinThickSmallGap, ThinThickThinLargeGap, ThinThickThinMediumGap, ThinThickThinSmallGap, ThreeDEmboss, ThreeDEngrave, Triple, Wave """ - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """ The Path of the location of this table object; leave blank for new tables """ - right_border_color: Optional[str] = field( + right_border_color: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RightBorderColor"}, ) """HTML-style color hex value (do not include a #)""" - right_border_size: Optional[int] = field( + right_border_size: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RightBorderSize"}, ) """Width of the border in points (1/72nd of an inch)""" - right_border_space: Optional[int] = field( + right_border_space: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RightBorderSpace"}, ) """Spacing around the border in points (1/72nd of an inch)""" - right_border_type: Optional[str] = field( + right_border_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RightBorderType"}, ) """ @@ -2190,23 +2701,27 @@ class DocxTable: ThinThickSmallGap, ThinThickThinLargeGap, ThinThickThinMediumGap, ThinThickThinSmallGap, ThreeDEmboss, ThreeDEngrave, Triple, Wave """ - start_border_color: Optional[str] = field( + start_border_color: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartBorderColor"}, ) """HTML-style color hex value (do not include a #)""" - start_border_size: Optional[int] = field( + start_border_size: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartBorderSize"}, ) """Width of the border in points (1/72nd of an inch)""" - start_border_space: Optional[int] = field( + start_border_space: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartBorderSpace"}, ) """Spacing around the border in points (1/72nd of an inch)""" - start_border_type: Optional[str] = field( + start_border_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartBorderType"}, ) """ @@ -2217,43 +2732,51 @@ class DocxTable: ThinThickSmallGap, ThinThickThinLargeGap, ThinThickThinMediumGap, ThinThickThinSmallGap, ThreeDEmboss, ThreeDEngrave, Triple, Wave """ - table_id: Optional[str] = field( + table_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableID"}, ) """The ID of the table; leave blank for new tables""" - table_indentation_mode: Optional[str] = field( + table_indentation_mode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableIndentationMode"}, ) """Table indentation type""" - table_indentation_width: Optional[int] = field( + table_indentation_width: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableIndentationWidth"}, ) """Table indentation width""" - table_rows: Optional[List[DocxTableRow]] = field( + table_rows: Optional[List[DocxTableRow | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableRows"}, ) """Rows in the table; this is where the contents is located""" - top_border_color: Optional[str] = field( + top_border_color: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TopBorderColor"}, ) """HTML-style color hex value (do not include a #)""" - top_border_size: Optional[int] = field( + top_border_size: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TopBorderSize"}, ) """Width of the border in points (1/72nd of an inch)""" - top_border_space: Optional[int] = field( + top_border_space: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TopBorderSpace"}, ) """Spacing around the border in points (1/72nd of an inch)""" - top_border_type: Optional[str] = field( + top_border_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TopBorderType"}, ) """ @@ -2264,10 +2787,15 @@ class DocxTable: ThinThickSmallGap, ThinThickThinLargeGap, ThinThickThinMediumGap, ThinThickThinSmallGap, ThreeDEmboss, ThreeDEngrave, Triple, Wave """ - width: Optional[str] = field(default=None, metadata={"wire_name": "Width"}) + width: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Width"}, + ) """The Width of the table, or 0 if not specified""" - width_type: Optional[str] = field( + width_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WidthType"}, ) """The Width configuration type of the table""" @@ -2279,45 +2807,56 @@ class DocxTableCell: Definition: DocxTableCell """ - cell_index: Optional[int] = field( + cell_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellIndex"}, ) """The index of the cell, 0-based""" - cell_shading_color: Optional[str] = field( + cell_shading_color: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellShadingColor"}, ) """Color of the cell shading""" - cell_shading_fill: Optional[str] = field( + cell_shading_fill: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellShadingFill"}, ) """Fill of the cell shading""" - cell_shading_pattern: Optional[str] = field( + cell_shading_pattern: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellShadingPattern"}, ) """Pattern of the cell shading""" - cell_width: Optional[str] = field( + cell_width: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellWidth"}, ) """Width of the cell""" - cell_width_mode: Optional[str] = field( + cell_width_mode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellWidthMode"}, ) """Width mode of the cell; can be auto (for automatic) or manual""" - paragraphs: Optional[List[DocxParagraph]] = field( + paragraphs: Optional[List[DocxParagraph | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Paragraphs"}, ) """ Paragraphs inside the cell; this is where the contents of the cell are stored """ - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new tables""" @@ -2327,18 +2866,24 @@ class DocxTableRow: Definition: DocxTableRow """ - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """ The Path of the location of this table row object; leave blank for new tables """ - row_cells: Optional[List[DocxTableCell]] = field( + row_cells: Optional[List[DocxTableCell | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RowCells"}, ) """Cells in the row; this is where the contents of the row is stored""" - row_index: Optional[int] = field( + row_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RowIndex"}, ) """Index of the row, 0-based""" @@ -2350,8 +2895,9 @@ class DocxTemplateApplicationRequest: Definition: DocxTemplateApplicationRequest """ - operations: Optional[List[DocxTemplateOperation]] = field( + operations: Optional[List[DocxTemplateOperation | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Operations"}, ) """Operations to apply to this template""" @@ -2363,21 +2909,24 @@ class DocxTemplateOperation: Definition: DocxTemplateOperation """ - action: Optional[int] = field( + action: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Action"}, ) """Operation action to take; possible values are \"Replace\"""" - match_against: Optional[str] = field( + match_against: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MatchAgainst"}, ) """ For Replace operations, the string to match against (to be replaced with ReplaceWith string) """ - replace_with: Optional[str] = field( + replace_with: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplaceWith"}, ) """ @@ -2391,15 +2940,21 @@ class DocxText: Definition: DocxText """ - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new tables""" - text_content: Optional[str] = field( + text_content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContent"}, ) """Text string containing the text content of this text content item""" - text_index: Optional[int] = field( + text_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextIndex"}, ) """Index of the text content in the run; 0-based""" @@ -2411,32 +2966,45 @@ class DocxTopLevelComment: Definition: DocxTopLevelComment """ - author: Optional[str] = field( + author: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Author"}, ) """Author name of the comment""" - author_initials: Optional[str] = field( + author_initials: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AuthorInitials"}, ) """Initials of the author of the comment""" - comment_date: Optional[str] = field( + comment_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CommentDate"}, ) """Date timestamp of the comment""" - comment_text: Optional[str] = field( + comment_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CommentText"}, ) """Text content of the comment""" - done: Optional[bool] = field(default=None, metadata={"wire_name": "Done"}) + done: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Done"}, + ) """True if this comment is marked as Done in Word, otherwise it is false""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """Path to the comment in the document""" - reply_child_comments: Optional[List[DocxComment]] = field( + reply_child_comments: Optional[List[DocxComment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyChildComments"}, ) """Child comments, that are replies to this one""" @@ -2448,17 +3016,23 @@ class ExifValue: Definition: ExifValue """ - data_type: Optional[str] = field( + data_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DataType"}, ) """Date type of the EXIF value""" - data_value: Optional[str] = field( + data_value: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DataValue"}, ) """Value, formatted as a string of the EXIF value""" - tag: Optional[str] = field(default=None, metadata={"wire_name": "Tag"}) + tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Tag"}, + ) """Tag name for the EXIF value""" @@ -2468,30 +3042,35 @@ class FindRegexMatch: Definition: FindRegexMatch """ - character_offset_end: Optional[int] = field( + character_offset_end: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CharacterOffsetEnd"}, ) """0-based index of the end of the match""" - character_offset_start: Optional[int] = field( + character_offset_start: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CharacterOffsetStart"}, ) """0-based index of the start of the match""" - containing_line: Optional[str] = field( + containing_line: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContainingLine"}, ) """Text content of the line containing the match""" - match_groups: Optional[List[str]] = field( + match_groups: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MatchGroups"}, ) """ Regular expression regex match groups; these correspond to the match values """ - match_value: Optional[str] = field( + match_value: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MatchValue"}, ) """The match value""" @@ -2503,18 +3082,21 @@ class FindStringMatch: Definition: FindStringMatch """ - character_offset_end: Optional[int] = field( + character_offset_end: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CharacterOffsetEnd"}, ) """0-based index of the end of the match""" - character_offset_start: Optional[int] = field( + character_offset_start: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CharacterOffsetStart"}, ) """0-based index of the start of the match""" - containing_line: Optional[str] = field( + containing_line: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContainingLine"}, ) """Text content of the line containing the match""" @@ -2526,18 +3108,21 @@ class FindStringRegexRequest: Definition: FindStringRegexRequest """ - match_case: Optional[bool] = field( + match_case: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MatchCase"}, ) """Set to True to match case, False to ignore case""" - target_regex: Optional[str] = field( + target_regex: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TargetRegex"}, ) """Target input regular expression (regex) to find""" - text_content: Optional[str] = field( + text_content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContent"}, ) """Input text content""" @@ -2549,18 +3134,21 @@ class FindStringRegexResponse: Definition: FindStringRegexResponse """ - match_count: Optional[int] = field( + match_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MatchCount"}, ) """The number of matches""" - matches: Optional[List[FindRegexMatch]] = field( + matches: Optional[List[FindRegexMatch | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Matches"}, ) """Regular expression matches""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -2572,13 +3160,15 @@ class FindStringSimpleRequest: Definition: FindStringSimpleRequest """ - target_string: Optional[str] = field( + target_string: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TargetString"}, ) """Target input string to find""" - text_content: Optional[str] = field( + text_content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContent"}, ) """Input text content""" @@ -2590,18 +3180,21 @@ class FindStringSimpleResponse: Definition: FindStringSimpleResponse """ - match_count: Optional[int] = field( + match_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MatchCount"}, ) """The number of matches""" - matches: Optional[List[FindStringMatch]] = field( + matches: Optional[List[FindStringMatch | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Matches"}, ) """Found matches""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -2613,8 +3206,9 @@ class FinishEditingRequest: Definition: FinishEditingRequest """ - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """URL of a document being edited to get the contents of.""" @@ -2626,13 +3220,15 @@ class GetDocxBodyRequest: Definition: GetDocxBodyRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -2649,18 +3245,21 @@ class GetDocxCommentsResponse: Definition: GetDocxCommentsResponse """ - comment_count: Optional[int] = field( + comment_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CommentCount"}, ) """The number of comments in the document""" - comments: Optional[List[DocxComment]] = field( + comments: Optional[List[DocxComment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Comments in the document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -2672,13 +3271,15 @@ class GetDocxGetCommentsHierarchicalRequest: Definition: GetDocxGetCommentsHierarchicalRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -2695,13 +3296,15 @@ class GetDocxGetCommentsRequest: Definition: GetDocxGetCommentsRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -2718,13 +3321,15 @@ class GetDocxHeadersAndFootersRequest: Definition: GetDocxHeadersAndFootersRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -2741,13 +3346,15 @@ class GetDocxImagesRequest: Definition: GetDocxImagesRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -2764,13 +3371,15 @@ class GetDocxPagesRequest: Definition: GetDocxPagesRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -2787,13 +3396,15 @@ class GetDocxSectionsRequest: Definition: GetDocxSectionsRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -2810,13 +3421,15 @@ class GetDocxStylesRequest: Definition: GetDocxStylesRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -2833,13 +3446,15 @@ class GetDocxTableByIndexRequest: Definition: GetDocxTableByIndexRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -2848,8 +3463,9 @@ class GetDocxTableByIndexRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - table_index: Optional[int] = field( + table_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableIndex"}, ) """0-based index of the table to retrieve from the Word Document""" @@ -2861,13 +3477,15 @@ class GetDocxTableRowRequest: Definition: GetDocxTableRowRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -2876,13 +3494,15 @@ class GetDocxTableRowRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - table_path: Optional[str] = field( + table_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TablePath"}, ) """Path to the table to retrievew the row from""" - table_row_row_index: Optional[int] = field( + table_row_row_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableRowRowIndex"}, ) """0-based index of the row to retrieve (e.g. 0, 1, 2, ...) in the table""" @@ -2894,13 +3514,15 @@ class GetDocxTablesRequest: Definition: GetDocxTablesRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -2917,85 +3539,108 @@ class GetImageInfoResult: Definition: GetImageInfoResult """ - bit_depth: Optional[int] = field( + bit_depth: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BitDepth"}, ) """Bit depth of the image""" - color_count: Optional[int] = field( + color_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ColorCount"}, ) """Unique colors in the image""" - color_space: Optional[str] = field( + color_space: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ColorSpace"}, ) """Color space of the image""" - color_type: Optional[str] = field( + color_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ColorType"}, ) """Color type of the image""" - comment: Optional[str] = field( + comment: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comment"}, ) """Comment string in the image""" - compression_level: Optional[int] = field( + compression_level: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CompressionLevel"}, ) """ Compression level value from 0 (lowest quality) to 100 (highest quality) """ - d_p_i: Optional[float] = field(default=None, metadata={"wire_name": "DPI"}) + d_p_i: Optional[float] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "DPI"}, + ) """DPI (pixels per unit, e.g. pixels per inch) of the image""" - d_p_i_unit: Optional[str] = field( + d_p_i_unit: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DPIUnit"}, ) """Units of the DPI measurement; can be either in Inches or Centimeters""" - exif_profile_name: Optional[str] = field( + exif_profile_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExifProfileName"}, ) """Name of the EXIF profile used""" - exif_values: Optional[List[ExifValue]] = field( + exif_values: Optional[List[ExifValue | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExifValues"}, ) """EXIF tags and values embedded in the image""" - has_transparency: Optional[bool] = field( + has_transparency: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HasTransparency"}, ) """True if the image contains transparency, otherwise false""" - height: Optional[int] = field( + height: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Height"}, ) """Height in pixels of the image""" - image_format: Optional[str] = field( + image_format: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageFormat"}, ) """Image format""" - image_hash_signature: Optional[str] = field( + image_hash_signature: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageHashSignature"}, ) """SHA256 hash signature of the image""" - mime_type: Optional[str] = field( + mime_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MimeType"}, ) """MIME type of the image format""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) - width: Optional[int] = field(default=None, metadata={"wire_name": "Width"}) + width: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Width"}, + ) """Width in pixels of the image""" @@ -3005,16 +3650,18 @@ class GetPdfAnnotationsResult: Definition: GetPdfAnnotationsResult """ - annotations: Optional[List[PdfAnnotation]] = field( + annotations: Optional[List[PdfAnnotation | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Annotations"}, ) """ Annotations in the PDF file, ordered by placement from start to finish in the document """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -3026,18 +3673,21 @@ class GetXlsxCellByIdentifierRequest: Definition: GetXlsxCellByIdentifierRequest """ - cell_identifier: Optional[str] = field( + cell_identifier: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellIdentifier"}, ) """Required; Excel cell identifier, e.g. A1, B22, C33, etc.""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -3046,8 +3696,9 @@ class GetXlsxCellByIdentifierRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - worksheet_to_query: Optional[XlsxWorksheet] = field( + worksheet_to_query: Optional[XlsxWorksheet | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetToQuery"}, ) """ @@ -3062,18 +3713,21 @@ class GetXlsxCellRequest: Definition: GetXlsxCellRequest """ - cell_index: Optional[int] = field( + cell_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellIndex"}, ) """0-based index of the cell, 0, 1, 2, ... in the row to retrieve""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -3082,13 +3736,15 @@ class GetXlsxCellRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - row_index: Optional[int] = field( + row_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RowIndex"}, ) """0-based index of the row, 0, 1, 2, ... to retrieve""" - worksheet_to_query: Optional[XlsxWorksheet] = field( + worksheet_to_query: Optional[XlsxWorksheet | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetToQuery"}, ) """ @@ -3103,13 +3759,15 @@ class GetXlsxColumnsRequest: Definition: GetXlsxColumnsRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -3118,8 +3776,9 @@ class GetXlsxColumnsRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - worksheet_to_query: Optional[XlsxWorksheet] = field( + worksheet_to_query: Optional[XlsxWorksheet | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetToQuery"}, ) """ @@ -3134,13 +3793,15 @@ class GetXlsxImagesRequest: Definition: GetXlsxImagesRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -3149,8 +3810,9 @@ class GetXlsxImagesRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - worksheet_to_query: Optional[XlsxWorksheet] = field( + worksheet_to_query: Optional[XlsxWorksheet | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetToQuery"}, ) """ @@ -3165,13 +3827,15 @@ class GetXlsxRowsAndCellsRequest: Definition: GetXlsxRowsAndCellsRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -3180,8 +3844,9 @@ class GetXlsxRowsAndCellsRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - worksheet_to_query: Optional[XlsxWorksheet] = field( + worksheet_to_query: Optional[XlsxWorksheet | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetToQuery"}, ) """ @@ -3196,13 +3861,15 @@ class GetXlsxStylesRequest: Definition: GetXlsxStylesRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -3219,13 +3886,15 @@ class GetXlsxWorksheetsRequest: Definition: GetXlsxWorksheetsRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -3242,10 +3911,15 @@ class HtmlMdResult: Definition: HtmlMdResult """ - html: Optional[str] = field(default=None, metadata={"wire_name": "Html"}) + html: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Html"}, + ) """Resulting HTML from the conversion""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if operation was successful, false otherwise""" @@ -3257,18 +3931,21 @@ class HtmlTemplateApplicationRequest: Definition: HtmlTemplateApplicationRequest """ - html_template: Optional[str] = field( + html_template: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HtmlTemplate"}, ) """HTML template input as a string""" - html_template_url: Optional[str] = field( + html_template_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HtmlTemplateUrl"}, ) """URL to HTML template input""" - operations: Optional[List[HtmlTemplateOperation]] = field( + operations: Optional[List[HtmlTemplateOperation | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Operations"}, ) """Operations to apply to this template""" @@ -3280,21 +3957,24 @@ class HtmlTemplateOperation: Definition: HtmlTemplateOperation """ - action: Optional[int] = field( + action: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Action"}, ) """Operation action to take; possible values are \"Replace\"""" - match_agsint: Optional[str] = field( + match_agsint: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MatchAgsint"}, ) """ For Replace operations, the string to match against (to be replaced with ReplaceWith string) """ - replace_with: Optional[str] = field( + replace_with: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplaceWith"}, ) """ @@ -3308,7 +3988,11 @@ class HtmlToOfficeRequest: Definition: HtmlToOfficeRequest """ - html: Optional[str] = field(default=None, metadata={"wire_name": "Html"}) + html: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Html"}, + ) """HTML to render to Office format""" @@ -3318,8 +4002,9 @@ class HtmlToPdfRequest: Definition: HtmlToPdfRequest """ - extra_loading_wait: Optional[int] = field( + extra_loading_wait: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExtraLoadingWait"}, ) """ @@ -3327,7 +4012,11 @@ class HtmlToPdfRequest: finished loading before taking the screenshot. Can be helpful for highly asynchronous websites. """ - html: Optional[str] = field(default=None, metadata={"wire_name": "Html"}) + html: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Html"}, + ) """HTML to render to PDF""" @@ -3337,8 +4026,9 @@ class HtmlToPngRequest: Definition: HtmlToPngRequest """ - extra_loading_wait: Optional[int] = field( + extra_loading_wait: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExtraLoadingWait"}, ) """ @@ -3346,10 +4036,15 @@ class HtmlToPngRequest: finished loading before taking the screenshot. Can be helpful for highly asynchronous websites. """ - html: Optional[str] = field(default=None, metadata={"wire_name": "Html"}) + html: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Html"}, + ) """HTML to render to PNG (screenshot)""" - screenshot_height: Optional[int] = field( + screenshot_height: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ScreenshotHeight"}, ) """ @@ -3357,8 +4052,9 @@ class HtmlToPngRequest: 1024, supply -1 to measure the full screen height of the page and attempt to take a screen-height screenshot """ - screenshot_width: Optional[int] = field( + screenshot_width: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ScreenshotWidth"}, ) """ @@ -3374,7 +4070,11 @@ class HtmlToTextRequest: Definition: HtmlToTextRequest """ - html: Optional[str] = field(default=None, metadata={"wire_name": "Html"}) + html: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Html"}, + ) """HTML to extract the text from""" @@ -3384,13 +4084,15 @@ class InsertDocxInsertParagraphRequest: Definition: InsertDocxInsertParagraphRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -3399,8 +4101,9 @@ class InsertDocxInsertParagraphRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - insert_path: Optional[str] = field( + insert_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InsertPath"}, ) """ @@ -3408,8 +4111,9 @@ class InsertDocxInsertParagraphRequest: InsertPath field using the Path value from an existing object. Used with InsertPlacement of BeforeExistingObject or AfterExistingObject """ - insert_placement: Optional[str] = field( + insert_placement: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InsertPlacement"}, ) """ @@ -3420,8 +4124,9 @@ class InsertDocxInsertParagraphRequest: object), AfterExistingObject (right after an existing object - fill in the InsertPath field using the Path value from an existing object) """ - paragraph_to_insert: Optional[DocxParagraph] = field( + paragraph_to_insert: Optional[DocxParagraph | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ParagraphToInsert"}, ) """Table you would like to insert""" @@ -3433,18 +4138,21 @@ class InsertDocxTableRowRequest: Definition: InsertDocxTableRowRequest """ - existing_table_path: Optional[str] = field( + existing_table_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExistingTablePath"}, ) """Required; the path to the existing table to modify""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -3453,8 +4161,9 @@ class InsertDocxTableRowRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - insert_placement: Optional[str] = field( + insert_placement: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InsertPlacement"}, ) """ @@ -3464,8 +4173,9 @@ class InsertDocxTableRowRequest: first row in the table, 1 being the second row in the table, 2 being the third row in the table, etc. to insert this row after """ - row_to_insert: Optional[DocxTableRow] = field( + row_to_insert: Optional[DocxTableRow | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RowToInsert"}, ) """Table you would like to insert""" @@ -3477,13 +4187,15 @@ class InsertDocxTablesRequest: Definition: InsertDocxTablesRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -3492,8 +4204,9 @@ class InsertDocxTablesRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - insert_path: Optional[str] = field( + insert_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InsertPath"}, ) """ @@ -3501,8 +4214,9 @@ class InsertDocxTablesRequest: InsertPath field using the Path value from an existing object. Used with InsertPlacement of BeforeExistingObject or AfterExistingObject """ - insert_placement: Optional[str] = field( + insert_placement: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InsertPlacement"}, ) """ @@ -3513,8 +4227,9 @@ class InsertDocxTablesRequest: object), AfterExistingObject (right after an existing object - fill in the InsertPath field using the Path value from an existing object) """ - table_to_insert: Optional[DocxTable] = field( + table_to_insert: Optional[DocxTable | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableToInsert"}, ) """Table you would like to insert""" @@ -3526,13 +4241,15 @@ class InsertXlsxWorksheetRequest: Definition: InsertXlsxWorksheetRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -3541,8 +4258,9 @@ class InsertXlsxWorksheetRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - worksheet_to_insert: Optional[XlsxWorksheet] = field( + worksheet_to_insert: Optional[XlsxWorksheet | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetToInsert"}, ) """Workersheet to insert""" @@ -3554,18 +4272,21 @@ class MultipageImageFormatConversionResult: Definition: MultipageImageFormatConversionResult """ - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PageCount"}, ) """The number of pages in the converted output""" - pages: Optional[List[PageConversionResult]] = field( + pages: Optional[List[PageConversionResult | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Pages"}, ) """Converted page results""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" @@ -3577,13 +4298,15 @@ class PageConversionResult: Definition: PageConversionResult """ - file_bytes: Optional[str] = field( + file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileBytes"}, ) """File bytes (contents) of the image in converted file format""" - filename: Optional[str] = field( + filename: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Filename"}, ) """File name of the image in the converted file format""" @@ -3595,63 +4318,78 @@ class PdfAnnotation: Definition: PdfAnnotation """ - annotation_index: Optional[int] = field( + annotation_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AnnotationIndex"}, ) """The 0-based index of the annotation in the document""" - annotation_type: Optional[str] = field( + annotation_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AnnotationType"}, ) """Type of the annotation; possible values are Text""" - creation_date: Optional[str] = field( + creation_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CreationDate"}, ) """Date that the annotation was created""" - height: Optional[float] = field( + height: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Height"}, ) """Height of the annotation""" - left_x: Optional[float] = field( + left_x: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LeftX"}, ) """Left X coordinate for the location of the annotation""" - modified_date: Optional[str] = field( + modified_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ModifiedDate"}, ) """Date that the annotation was last modified""" - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PageNumber"}, ) """The 1-based index of the page containing the annotation""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Subject of the annotation""" - text_contents: Optional[str] = field( + text_contents: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContents"}, ) """Text contents of the annotation""" - title: Optional[str] = field(default=None, metadata={"wire_name": "Title"}) + title: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Title"}, + ) """ Title of the annotation; this is often the author of the annotation in Acrobat-created PDF files """ - top_y: Optional[float] = field( + top_y: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TopY"}, ) """Top Y coordination of the location of the annotation""" - width: Optional[float] = field( + width: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Width"}, ) """Width of the annotation""" @@ -3663,8 +4401,9 @@ class PdfDocument: Definition: PdfDocument """ - document_contents: Optional[str] = field( + document_contents: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DocumentContents"}, ) """ @@ -3672,12 +4411,17 @@ class PdfDocument: document; otherwise will be set to null and the document contents will be available via the URL parameter """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PageNumber"}, ) """Page number of the converted page, starting with 1 for the first page""" - u_r_l: Optional[str] = field(default=None, metadata={"wire_name": "URL"}) + u_r_l: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "URL"}, + ) """ URL to the PDF file of this worksheet; file is stored in an in-memory cache and will be deleted @@ -3690,21 +4434,24 @@ class PdfFormField: Definition: PdfFormField """ - field_combo_box_selected_index: Optional[int] = field( + field_combo_box_selected_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FieldComboBoxSelectedIndex"}, ) """ Applies to ComboBox field types only; specifies the selected index of the combo box selection if available """ - field_name: Optional[str] = field( + field_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FieldName"}, ) """Name of the form field""" - field_type: Optional[str] = field( + field_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FieldType"}, ) """ @@ -3712,8 +4459,9 @@ class PdfFormField: string), Checkbox (FieldValue can be \"true\" or \"false\"), ComboBox (FieldComboBoxSelectedIndex will also be populated), Other """ - field_value: Optional[str] = field( + field_value: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FieldValue"}, ) """Value of the form field""" @@ -3725,13 +4473,15 @@ class PdfFormFields: Definition: PdfFormFields """ - form_fields: Optional[List[PdfFormField]] = field( + form_fields: Optional[List[PdfFormField | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FormFields"}, ) """Fields and field values found in the form""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -3743,56 +4493,68 @@ class PdfMetadata: Definition: PdfMetadata """ - author: Optional[str] = field( + author: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Author"}, ) """ User name of the creator/author of the document, if available, null if not available """ - creator: Optional[str] = field( + creator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Creator"}, ) """Creator of the document""" - date_created: Optional[str] = field( + date_created: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateCreated"}, ) """ The timestamp that the document was created, if available, null if not available """ - date_modified: Optional[str] = field( + date_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) """ The timestamp that the document was last modified, if available, null if not available """ - keywords: Optional[str] = field( + keywords: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Keywords"}, ) """Keywords of the document""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PageCount"}, ) """The number of pages in the document""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Subject of the document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" - title: Optional[str] = field(default=None, metadata={"wire_name": "Title"}) + title: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Title"}, + ) """Title of the document""" @@ -3802,13 +4564,15 @@ class PdfPageText: Definition: PdfPageText """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PageNumber"}, ) """Page number of the page (1-based)""" - page_text: Optional[str] = field( + page_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PageText"}, ) """Text of the page""" @@ -3820,13 +4584,15 @@ class PdfTextByPageResult: Definition: PdfTextByPageResult """ - pages: Optional[List[PdfPageText]] = field( + pages: Optional[List[PdfPageText | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Pages"}, ) """Pages in the PDF""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -3838,13 +4604,15 @@ class PdfToPngResult: Definition: PdfToPngResult """ - png_result_pages: Optional[List[ConvertedPngPage]] = field( + png_result_pages: Optional[List[ConvertedPngPage | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PngResultPages"}, ) """Array of converted pages""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -3856,20 +4624,26 @@ class PresentationResult: Definition: PresentationResult """ - presentation_contents: Optional[str] = field( + presentation_contents: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PresentationContents"}, ) """Contents of the presentation in bytes""" - slide_number: Optional[int] = field( + slide_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SlideNumber"}, ) """ Worksheet number of the converted page, starting with 1 for the left-most worksheet """ - u_r_l: Optional[str] = field(default=None, metadata={"wire_name": "URL"}) + u_r_l: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "URL"}, + ) """ URL to the PPTX file of this slide; file is stored in an in-memory cache and will be deleted @@ -3882,13 +4656,15 @@ class RemoveDocxHeadersAndFootersRequest: Definition: RemoveDocxHeadersAndFootersRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -3897,16 +4673,18 @@ class RemoveDocxHeadersAndFootersRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - remove_footers: Optional[bool] = field( + remove_footers: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RemoveFooters"}, ) """ True if you would like to remove all footers from the input document, false otherwise """ - remove_headers: Optional[bool] = field( + remove_headers: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RemoveHeaders"}, ) """ @@ -3921,18 +4699,21 @@ class RemoveDocxPagesRequest: Definition: RemoveDocxPagesRequest """ - end_delete_page_number: Optional[int] = field( + end_delete_page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EndDeletePageNumber"}, ) """Page number (1-based) to stop deleting pages; inclusive""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -3941,8 +4722,9 @@ class RemoveDocxPagesRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - start_delete_page_number: Optional[int] = field( + start_delete_page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartDeletePageNumber"}, ) """Page number (1-based) to start deleting pages; inclusive""" @@ -3954,8 +4736,9 @@ class RemoveHtmlFromTextRequest: Definition: RemoveHtmlFromTextRequest """ - text_containing_html: Optional[str] = field( + text_containing_html: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContainingHtml"}, ) """Input text string to remove the HTML from""" @@ -3967,13 +4750,15 @@ class RemoveHtmlFromTextResponse: Definition: RemoveHtmlFromTextResponse """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" - text_content_result: Optional[str] = field( + text_content_result: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContentResult"}, ) """Result of performing a remove HTML from string operation""" @@ -3985,18 +4770,21 @@ class RemovePptxSlidesRequest: Definition: RemovePptxSlidesRequest """ - end_delete_slide_number: Optional[int] = field( + end_delete_slide_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EndDeleteSlideNumber"}, ) """Slide number (1-based) to stop deleting slides; inclusive""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -4005,8 +4793,9 @@ class RemovePptxSlidesRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - start_delete_slide_number: Optional[int] = field( + start_delete_slide_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartDeleteSlideNumber"}, ) """Slide number (1-based) to start deleting slides; inclusive""" @@ -4018,8 +4807,9 @@ class RemoveWhitespaceFromTextRequest: Definition: RemoveWhitespaceFromTextRequest """ - text_containing_whitespace: Optional[str] = field( + text_containing_whitespace: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContainingWhitespace"}, ) """Input text string to remove the whitespace from""" @@ -4031,13 +4821,15 @@ class RemoveWhitespaceFromTextResponse: Definition: RemoveWhitespaceFromTextResponse """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" - text_content_result: Optional[str] = field( + text_content_result: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContentResult"}, ) """Result of performing a remove whitespace from string operation""" @@ -4049,13 +4841,15 @@ class RemoveXlsxWorksheetRequest: Definition: RemoveXlsxWorksheetRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -4064,8 +4858,9 @@ class RemoveXlsxWorksheetRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - worksheet_to_remove: Optional[XlsxWorksheet] = field( + worksheet_to_remove: Optional[XlsxWorksheet | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetToRemove"}, ) """ @@ -4081,24 +4876,27 @@ class ReplaceStringRegexRequest: Definition: ReplaceStringRegexRequest """ - regular_expression_string: Optional[str] = field( + regular_expression_string: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RegularExpressionString"}, ) """ Target input regular expression (regex) string to match and be replaced; supports all regular expression values """ - replace_with_string: Optional[str] = field( + replace_with_string: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplaceWithString"}, ) """ Replacement for target string; supports referencing indexed regex matched values from RegularExpressionString, such as $1, $2, and so on """ - text_content: Optional[str] = field( + text_content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContent"}, ) """Input text content""" @@ -4110,13 +4908,15 @@ class ReplaceStringRegexResponse: Definition: ReplaceStringRegexResponse """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" - text_content_result: Optional[str] = field( + text_content_result: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContentResult"}, ) """Result of performing a base 64 decode operation, binary file content""" @@ -4128,13 +4928,15 @@ class ReplaceStringRequest: Definition: ReplaceStringRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -4143,18 +4945,21 @@ class ReplaceStringRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - match_case: Optional[bool] = field( + match_case: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MatchCase"}, ) """True if the case should be matched, false for case insensitive match""" - match_string: Optional[str] = field( + match_string: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MatchString"}, ) """String to search for and match against, to be replaced""" - replace_string: Optional[str] = field( + replace_string: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplaceString"}, ) """String to replace the matched values with""" @@ -4166,18 +4971,21 @@ class ReplaceStringSimpleRequest: Definition: ReplaceStringSimpleRequest """ - replace_with_string: Optional[str] = field( + replace_with_string: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplaceWithString"}, ) """Replacement for target string""" - target_string: Optional[str] = field( + target_string: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TargetString"}, ) """Target input string to match and be replaced""" - text_content: Optional[str] = field( + text_content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContent"}, ) """Input text content""" @@ -4189,13 +4997,15 @@ class ReplaceStringSimpleResponse: Definition: ReplaceStringSimpleResponse """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" - text_content_result: Optional[str] = field( + text_content_result: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextContentResult"}, ) """Result of performing a replace string operation""" @@ -4207,8 +5017,9 @@ class ScreenshotRequest: Definition: ScreenshotRequest """ - extra_loading_wait: Optional[int] = field( + extra_loading_wait: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExtraLoadingWait"}, ) """ @@ -4217,8 +5028,9 @@ class ScreenshotRequest: asynchronous websites. Provide a value of 0 for the default of 5000 milliseconds (5 seconds) """ - screenshot_height: Optional[int] = field( + screenshot_height: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ScreenshotHeight"}, ) """ @@ -4226,15 +5038,20 @@ class ScreenshotRequest: 1024, supply -1 to measure the full screen height of the page and attempt to take a screen-height screenshot """ - screenshot_width: Optional[int] = field( + screenshot_width: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ScreenshotWidth"}, ) """ Optional: Width of the screenshot in pixels; supply 0 to default to 1280 x 1024 """ - url: Optional[str] = field(default=None, metadata={"wire_name": "Url"}) + url: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Url"}, + ) """ URL address of the website to screenshot. HTTP and HTTPS are both supported, as are custom ports. @@ -4247,29 +5064,33 @@ class SetFormFieldValue: Definition: SetFormFieldValue """ - checkbox_value: Optional[bool] = field( + checkbox_value: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckboxValue"}, ) """For fields of type Checkbox, the value to put into the field""" - combo_box_selected_index: Optional[int] = field( + combo_box_selected_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ComboBoxSelectedIndex"}, ) """ For fields of type ComboBox; specifies the selected index of the combo box selection """ - field_name: Optional[str] = field( + field_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FieldName"}, ) """ Name of the field to set; you can call /convert/edit/pdf/form/get-fields to enumerate field names in a form """ - text_value: Optional[str] = field( + text_value: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextValue"}, ) """For fields of type Text, the text value to put into the field""" @@ -4281,13 +5102,15 @@ class SetPdfFormFieldsRequest: Definition: SetPdfFormFieldsRequest """ - field_values: Optional[List[SetFormFieldValue]] = field( + field_values: Optional[List[SetFormFieldValue | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FieldValues"}, ) """Field values to set""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Contents of the input file to set the fields on""" @@ -4299,13 +5122,15 @@ class SetPdfMetadataRequest: Definition: SetPdfMetadataRequest """ - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Input file contents bytes for the file to modify""" - metadata_to_set: Optional[PdfMetadata] = field( + metadata_to_set: Optional[PdfMetadata | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MetadataToSet"}, ) """PDF metadata to set on the file""" @@ -4317,25 +5142,29 @@ class SetXlsxCellByIdentifierRequest: Definition: SetXlsxCellByIdentifierRequest """ - cell_identifier: Optional[str] = field( + cell_identifier: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellIdentifier"}, ) """ The Excel cell identifier (e.g. A1, B2, C33, etc.) of the cell to update """ - cell_value: Optional[XlsxSpreadsheetCell] = field( + cell_value: Optional[XlsxSpreadsheetCell | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellValue"}, ) """New Cell value to update/overwrite into the Excel XLSX spreadsheet""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -4344,8 +5173,9 @@ class SetXlsxCellByIdentifierRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - worksheet_to_update: Optional[XlsxWorksheet] = field( + worksheet_to_update: Optional[XlsxWorksheet | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetToUpdate"}, ) """ @@ -4360,23 +5190,27 @@ class SetXlsxCellRequest: Definition: SetXlsxCellRequest """ - cell_index: Optional[int] = field( + cell_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellIndex"}, ) """0-based index of the cell, 0, 1, 2, ... in the row to set""" - cell_value: Optional[XlsxSpreadsheetCell] = field( + cell_value: Optional[XlsxSpreadsheetCell | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellValue"}, ) """New Cell value to update/overwrite into the Excel XLSX spreadsheet""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -4385,13 +5219,15 @@ class SetXlsxCellRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - row_index: Optional[int] = field( + row_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RowIndex"}, ) """0-based index of the row, 0, 1, 2, ... to set""" - worksheet_to_update: Optional[XlsxWorksheet] = field( + worksheet_to_update: Optional[XlsxWorksheet | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetToUpdate"}, ) """ @@ -4406,17 +5242,23 @@ class SplitDocumentResult: Definition: SplitDocumentResult """ - document_contents: Optional[str] = field( + document_contents: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DocumentContents"}, ) """Contents of the document in bytes""" - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PageNumber"}, ) """Page number of the converted page, starting with 1 for the first page""" - u_r_l: Optional[str] = field(default=None, metadata={"wire_name": "URL"}) + u_r_l: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "URL"}, + ) """ URL to the DOCX file of this slide; file is stored in an in-memory cache and will be deleted @@ -4429,12 +5271,16 @@ class SplitDocxDocumentResult: Definition: SplitDocxDocumentResult """ - result_documents: Optional[List[SplitDocumentResult]] = field( + result_documents: Optional[ + List[SplitDocumentResult | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultDocuments"}, ) - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -4446,13 +5292,15 @@ class SplitPdfResult: Definition: SplitPdfResult """ - documents: Optional[List[PdfDocument]] = field( + documents: Optional[List[PdfDocument | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Documents"}, ) """PDF documents as output""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -4464,12 +5312,16 @@ class SplitPptxPresentationResult: Definition: SplitPptxPresentationResult """ - result_presentations: Optional[List[PresentationResult]] = field( + result_presentations: Optional[ + List[PresentationResult | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultPresentations"}, ) - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -4481,17 +5333,20 @@ class SplitTextDocumentByLinesResult: Definition: SplitTextDocumentByLinesResult """ - line_count: Optional[int] = field( + line_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LineCount"}, ) """The count of lines in the text file""" - result_lines: Optional[List[TextDocumentLine]] = field( + result_lines: Optional[List[TextDocumentLine | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultLines"}, ) - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -4503,17 +5358,22 @@ class SplitTextDocumentByStringResult: Definition: SplitTextDocumentByStringResult """ - element_count: Optional[int] = field( + element_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ElementCount"}, ) """The count of elements in the text file""" - result_elements: Optional[List[TextDocumentElement]] = field( + result_elements: Optional[ + List[TextDocumentElement | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultElements"}, ) - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -4525,12 +5385,14 @@ class SplitXlsxWorksheetResult: Definition: SplitXlsxWorksheetResult """ - result_worksheets: Optional[List[WorksheetResult]] = field( + result_worksheets: Optional[List[WorksheetResult | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultWorksheets"}, ) - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -4542,13 +5404,15 @@ class TextConversionResult: Definition: TextConversionResult """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" - text_result: Optional[str] = field( + text_result: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextResult"}, ) """ @@ -4563,13 +5427,15 @@ class TextDocumentElement: Definition: TextDocumentElement """ - element_contents: Optional[str] = field( + element_contents: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ElementContents"}, ) """The text contents of a single element of a text file""" - element_number: Optional[int] = field( + element_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ElementNumber"}, ) """The 1-based line index of the element""" @@ -4581,13 +5447,15 @@ class TextDocumentLine: Definition: TextDocumentLine """ - line_contents: Optional[str] = field( + line_contents: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LineContents"}, ) """The text contents of a single line of a text file""" - line_number: Optional[int] = field( + line_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LineNumber"}, ) """The 1-based line index of the line""" @@ -4599,13 +5467,15 @@ class TextEncodingDetectResponse: Definition: TextEncodingDetectResponse """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if successful, false otherwise""" - text_encoding: Optional[str] = field( + text_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextEncoding"}, ) """ @@ -4620,23 +5490,27 @@ class UpdateDocxTableCellRequest: Definition: UpdateDocxTableCellRequest """ - cell_to_update: Optional[DocxTableCell] = field( + cell_to_update: Optional[DocxTableCell | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellToUpdate"}, ) """Table cell contents you would like to update the cell with""" - existing_table_path: Optional[str] = field( + existing_table_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExistingTablePath"}, ) """Required; the path to the existing table to modify""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -4645,13 +5519,15 @@ class UpdateDocxTableCellRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - table_cell_index: Optional[int] = field( + table_cell_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableCellIndex"}, ) """0-based index of the Table Cell (within the row) to update""" - table_row_index: Optional[int] = field( + table_row_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableRowIndex"}, ) """0-based index of the Table Row to update""" @@ -4663,18 +5539,21 @@ class UpdateDocxTableRowRequest: Definition: UpdateDocxTableRowRequest """ - existing_table_path: Optional[str] = field( + existing_table_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExistingTablePath"}, ) """Required; the path to the existing table to modify""" - input_file_bytes: Optional[str] = field( + input_file_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileBytes"}, ) """Optional: Bytes of the input file to operate on""" - input_file_url: Optional[str] = field( + input_file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InputFileUrl"}, ) """ @@ -4683,13 +5562,15 @@ class UpdateDocxTableRowRequest: the secure URL result from that operation as the URL here (this URL is not public). """ - row_to_update: Optional[DocxTableRow] = field( + row_to_update: Optional[DocxTableRow | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RowToUpdate"}, ) """Table row contents you would like to update the row with""" - table_row_index: Optional[int] = field( + table_row_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableRowIndex"}, ) """0-based index of the Table Row to update""" @@ -4701,7 +5582,11 @@ class UrlToTextRequest: Definition: UrlToTextRequest """ - url: Optional[str] = field(default=None, metadata={"wire_name": "Url"}) + url: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Url"}, + ) """URL of the website to extract the text from""" @@ -4711,12 +5596,14 @@ class ViewerResponse: Definition: ViewerResponse """ - html_embed: Optional[str] = field( + html_embed: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HtmlEmbed"}, ) - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) @@ -4727,23 +5614,30 @@ class WorksheetResult: Definition: WorksheetResult """ - u_r_l: Optional[str] = field(default=None, metadata={"wire_name": "URL"}) + u_r_l: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "URL"}, + ) """ URL to the XLSX file of this worksheet; file is stored in an in-memory cache and will be deleted """ - worksheet_contents: Optional[str] = field( + worksheet_contents: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetContents"}, ) """Contents of the worksheet in bytes""" - worksheet_name: Optional[str] = field( + worksheet_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetName"}, ) """The name of the worksheet""" - worksheet_number: Optional[int] = field( + worksheet_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetNumber"}, ) """ @@ -4758,30 +5652,38 @@ class XlsxImage: Definition: XlsxImage """ - image_contents_u_r_l: Optional[str] = field( + image_contents_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageContentsURL"}, ) """ URL to the image contents; file is stored in an in-memory cache and will be deleted. Call Finish-Editing to get the contents. """ - image_data_content_type: Optional[str] = field( + image_data_content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageDataContentType"}, ) """Read-only; image data MIME content-type""" - image_data_embed_id: Optional[str] = field( + image_data_embed_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageDataEmbedId"}, ) """Read-only; internal ID for the image contents""" - image_internal_file_name: Optional[str] = field( + image_internal_file_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageInternalFileName"}, ) """Read-only; internal file name/path for the image""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new rows""" @@ -4791,24 +5693,32 @@ class XlsxSpreadsheetCell: Definition: XlsxSpreadsheetCell """ - cell_identifier: Optional[str] = field( + cell_identifier: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CellIdentifier"}, ) """Cell reference of the cell, e.g. A1, Z22, etc.""" - formula: Optional[str] = field( + formula: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Formula"}, ) - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new rows""" - style_index: Optional[int] = field( + style_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StyleIndex"}, ) """Identifier for the style to apply to this style""" - text_value: Optional[str] = field( + text_value: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TextValue"}, ) """Text value of the cell""" @@ -4820,12 +5730,17 @@ class XlsxSpreadsheetColumn: Definition: XlsxSpreadsheetColumn """ - heading_cell: Optional[XlsxSpreadsheetCell] = field( + heading_cell: Optional[XlsxSpreadsheetCell | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HeadingCell"}, ) """Heading cell for this column""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new rows""" @@ -4835,12 +5750,17 @@ class XlsxSpreadsheetRow: Definition: XlsxSpreadsheetRow """ - cells: Optional[List[XlsxSpreadsheetCell]] = field( + cells: Optional[List[XlsxSpreadsheetCell | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Cells"}, ) """Spreadsheet Cells in the spreadsheet row""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The Path of the location of this object; leave blank for new rows""" @@ -4850,12 +5770,17 @@ class XlsxWorksheet: Definition: XlsxWorksheet """ - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """ The Path of the location of this object; leave blank for new worksheets """ - worksheet_name: Optional[str] = field( + worksheet_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorksheetName"}, ) """User-facing name of the worksheet tab""" @@ -4867,18 +5792,21 @@ class XmlAddAttributeWithXPathResult: Definition: XmlAddAttributeWithXPathResult """ - nodes_edited_count: Optional[int] = field( + nodes_edited_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NodesEditedCount"}, ) """Count of the matching results""" - resulting_xml_document: Optional[str] = field( + resulting_xml_document: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultingXmlDocument"}, ) """Resulting, modified XML document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -4890,18 +5818,21 @@ class XmlAddChildWithXPathResult: Definition: XmlAddChildWithXPathResult """ - nodes_edited_count: Optional[int] = field( + nodes_edited_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NodesEditedCount"}, ) """Count of the matching results""" - resulting_xml_document: Optional[str] = field( + resulting_xml_document: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultingXmlDocument"}, ) """Resulting, modified XML document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -4913,18 +5844,21 @@ class XmlFilterWithXPathResult: Definition: XmlFilterWithXPathResult """ - result_count: Optional[int] = field( + result_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultCount"}, ) """Count of the matching results""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" - xml_nodes: Optional[List[str]] = field( + xml_nodes: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "XmlNodes"}, ) """Matching selected XML nodes as strings""" @@ -4936,18 +5870,21 @@ class XmlQueryWithXQueryMultiResult: Definition: XmlQueryWithXQueryMultiResult """ - error_message: Optional[str] = field( + error_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ErrorMessage"}, ) """If an error occurs, additional details on the error""" - resulting_xml: Optional[str] = field( + resulting_xml: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultingXml"}, ) """Resulting XML result output""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -4959,18 +5896,21 @@ class XmlQueryWithXQueryResult: Definition: XmlQueryWithXQueryResult """ - error_message: Optional[str] = field( + error_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ErrorMessage"}, ) """If an error occurs, additional details on the error""" - resulting_xml: Optional[str] = field( + resulting_xml: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultingXml"}, ) """Resulting XML result output""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -4982,18 +5922,21 @@ class XmlRemoveAllChildrenWithXPathResult: Definition: XmlRemoveAllChildrenWithXPathResult """ - nodes_edited_count: Optional[int] = field( + nodes_edited_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NodesEditedCount"}, ) """Count of the matching results""" - resulting_xml_document: Optional[str] = field( + resulting_xml_document: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultingXmlDocument"}, ) """Resulting, modified XML document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -5005,25 +5948,29 @@ class XmlRemoveWithXPathResult: Definition: XmlRemoveWithXPathResult """ - nodes_removed_count: Optional[int] = field( + nodes_removed_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NodesRemovedCount"}, ) """Count of the matching results""" - resulting_xml_document: Optional[str] = field( + resulting_xml_document: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultingXmlDocument"}, ) """ Resulting, modified XML document with matching nodes removed as a string """ - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" - xml_nodes_removed: Optional[List[str]] = field( + xml_nodes_removed: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "XmlNodesRemoved"}, ) """Matching selected XML nodes as strings""" @@ -5035,18 +5982,21 @@ class XmlReplaceWithXPathResult: Definition: XmlReplaceWithXPathResult """ - nodes_edited_count: Optional[int] = field( + nodes_edited_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NodesEditedCount"}, ) """Count of the matching results""" - resulting_xml_document: Optional[str] = field( + resulting_xml_document: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultingXmlDocument"}, ) """Resulting, modified XML document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -5058,18 +6008,21 @@ class XmlSetValueWithXPathResult: Definition: XmlSetValueWithXPathResult """ - nodes_edited_count: Optional[int] = field( + nodes_edited_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NodesEditedCount"}, ) """Count of the matching results""" - resulting_xml_document: Optional[str] = field( + resulting_xml_document: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultingXmlDocument"}, ) """Resulting, modified XML document""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -5081,18 +6034,23 @@ class ZipDirectory: Definition: ZipDirectory """ - directories_in_directory: Optional[List[ZipDirectory]] = field( + directories_in_directory: Optional[ + List[ZipDirectory | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DirectoriesInDirectory"}, ) """Child directories contained directly in this directory""" - directory_name: Optional[str] = field( + directory_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DirectoryName"}, ) """Name of this directory""" - files_in_directory: Optional[List[ZipFile]] = field( + files_in_directory: Optional[List[ZipFile | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FilesInDirectory"}, ) """Child files contained directly in this directory""" @@ -5104,21 +6062,24 @@ class ZipExtractResponse: Definition: ZipExtractResponse """ - directories_in_zip: Optional[List[ZipDirectory]] = field( + directories_in_zip: Optional[List[ZipDirectory | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DirectoriesInZip"}, ) """ Top-level directories in the root directory of the zip; directories can contain sub-directories and files """ - files_in_zip: Optional[List[ZipFile]] = field( + files_in_zip: Optional[List[ZipFile | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FilesInZip"}, ) """Top-level files in the root directory fo the zip file""" - successful: Optional[bool] = field( + successful: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Successful"}, ) """True if the operation was successful, false otherwise""" @@ -5130,13 +6091,15 @@ class ZipFile: Definition: ZipFile """ - file_contents: Optional[str] = field( + file_contents: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileContents"}, ) """Contents of this file""" - file_name: Optional[str] = field( + file_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileName"}, ) """Name of this file""" @@ -5150,16 +6113,16 @@ class CloudmersiveconvertClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -5170,8 +6133,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -5179,8 +6142,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -5192,7 +6155,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -5207,9 +6170,9 @@ def __init__( def connector_name(self) -> str: return "cloudmersiveconvert" - async def edit_document_docx_create_blank_document_async( + def edit_document_docx_create_blank_document( self, - input: CreateBlankDocxRequest, + input: CreateBlankDocxRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5222,12 +6185,28 @@ async def edit_document_docx_create_blank_document_async( Returns a blank Word DOCX Document format file. The file is blank, with no contents. Use additional editing commands such as Insert Paragraph or Insert Table or Insert Image to populate the document. + + Swagger operation ID: `EditDocument_DocxCreateBlankDocument`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/create/blank" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5241,6 +6220,7 @@ async def edit_document_docx_create_blank_document_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5248,9 +6228,9 @@ async def edit_document_docx_create_blank_document_async( return json.loads(response.text) - async def edit_document_docx_delete_pages_async( + def edit_document_docx_delete_pages( self, - input: RemoveDocxPagesRequest, + input: RemoveDocxPagesRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5262,12 +6242,28 @@ async def edit_document_docx_delete_pages_async( Returns the edited Word Document in the Word Document (DOCX) format file with the specified pages removed + + Swagger operation ID: `EditDocument_DocxDeletePages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/delete-pages" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5281,13 +6277,14 @@ async def edit_document_docx_delete_pages_async( request_url, response.status, response.text, + response=response, ) return response.content - async def edit_document_docx_delete_table_row_async( + def edit_document_docx_delete_table_row( self, - input: DeleteDocxTableRowRequest, + input: DeleteDocxTableRowRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5299,13 +6296,29 @@ async def edit_document_docx_delete_table_row_async( Deletes an existing table row in a Word DOCX Document and returns the result. + + Swagger operation ID: `EditDocument_DocxDeleteTableRow`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/docx/delete-table-row" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5319,6 +6332,7 @@ async def edit_document_docx_delete_table_row_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5326,9 +6340,9 @@ async def edit_document_docx_delete_table_row_async( return json.loads(response.text) - async def edit_document_docx_delete_table_row_range_async( + def edit_document_docx_delete_table_row_range( self, - input: DeleteDocxTableRowRangeRequest, + input: DeleteDocxTableRowRangeRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5340,13 +6354,29 @@ async def edit_document_docx_delete_table_row_range_async( Deletes a range of 1 or more existing table rows in a Word DOCX Document and returns the result. + + Swagger operation ID: `EditDocument_DocxDeleteTableRowRange`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/docx/delete-table-row/range" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5360,6 +6390,7 @@ async def edit_document_docx_delete_table_row_range_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5367,9 +6398,9 @@ async def edit_document_docx_delete_table_row_range_async( return json.loads(response.text) - async def edit_document_docx_body_async( + def edit_document_docx_body( self, - input: GetDocxBodyRequest, + input: GetDocxBodyRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5381,12 +6412,28 @@ async def edit_document_docx_body_async( Returns the body defined in the Word Document (DOCX) format file; this is the main content part of a DOCX document + + Swagger operation ID: `EditDocument_DocxBody`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/get-body" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5400,6 +6447,7 @@ async def edit_document_docx_body_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5407,9 +6455,9 @@ async def edit_document_docx_body_async( return json.loads(response.text) - async def edit_document_docx_get_comments_hierarchical_async( + def edit_document_docx_get_comments_hierarchical( self, - input: GetDocxGetCommentsHierarchicalRequest, + input: GetDocxGetCommentsHierarchicalRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5422,13 +6470,29 @@ async def edit_document_docx_get_comments_hierarchical_async( Returns the comments and review annotations stored in the Word Document (DOCX) format file hierarchically, where reply comments are nested as children under top-level comments in the results returned. + + Swagger operation ID: `EditDocument_DocxGetCommentsHierarchical`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/docx/get-comments/hierarchical" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5442,6 +6506,7 @@ async def edit_document_docx_get_comments_hierarchical_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5449,9 +6514,9 @@ async def edit_document_docx_get_comments_hierarchical_async( return json.loads(response.text) - async def edit_document_docx_get_headers_and_footers_async( + def edit_document_docx_get_headers_and_footers( self, - input: GetDocxHeadersAndFootersRequest, + input: GetDocxHeadersAndFootersRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5462,13 +6527,29 @@ async def edit_document_docx_get_headers_and_footers_async( Get content of a footer from a Word DOCX document Returns the footer content from a Word Document (DOCX) format file + + Swagger operation ID: `EditDocument_DocxGetHeadersAndFooters`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/docx/get-headers-and-footers" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5482,6 +6563,7 @@ async def edit_document_docx_get_headers_and_footers_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5489,9 +6571,9 @@ async def edit_document_docx_get_headers_and_footers_async( return json.loads(response.text) - async def edit_document_docx_get_images_async( + def edit_document_docx_get_images( self, - input: GetDocxImagesRequest, + input: GetDocxImagesRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5502,12 +6584,28 @@ async def edit_document_docx_get_images_async( Get images from a Word DOCX document Returns the images defined in the Word Document (DOCX) format file + + Swagger operation ID: `EditDocument_DocxGetImages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/get-images" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5521,6 +6619,7 @@ async def edit_document_docx_get_images_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5528,9 +6627,9 @@ async def edit_document_docx_get_images_async( return json.loads(response.text) - async def edit_document_docx_pages_async( + def edit_document_docx_pages( self, - input: GetDocxPagesRequest, + input: GetDocxPagesRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5542,12 +6641,28 @@ async def edit_document_docx_pages_async( Returns the pages and contents of each page defined in the Word Document (DOCX) format file + + Swagger operation ID: `EditDocument_DocxPages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/get-pages" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5561,6 +6676,7 @@ async def edit_document_docx_pages_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5568,9 +6684,9 @@ async def edit_document_docx_pages_async( return json.loads(response.text) - async def edit_document_docx_get_sections_async( + def edit_document_docx_get_sections( self, - input: GetDocxSectionsRequest, + input: GetDocxSectionsRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5581,12 +6697,28 @@ async def edit_document_docx_get_sections_async( Get sections from a Word DOCX document Returns the sections defined in the Word Document (DOCX) format file + + Swagger operation ID: `EditDocument_DocxGetSections`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/get-sections" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5600,6 +6732,7 @@ async def edit_document_docx_get_sections_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5607,9 +6740,9 @@ async def edit_document_docx_get_sections_async( return json.loads(response.text) - async def edit_document_docx_get_styles_async( + def edit_document_docx_get_styles( self, - input: GetDocxStylesRequest, + input: GetDocxStylesRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5620,12 +6753,28 @@ async def edit_document_docx_get_styles_async( Get styles from a Word DOCX document Returns the styles defined in the Word Document (DOCX) format file + + Swagger operation ID: `EditDocument_DocxGetStyles`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/get-styles" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5639,6 +6788,7 @@ async def edit_document_docx_get_styles_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5646,9 +6796,9 @@ async def edit_document_docx_get_styles_async( return json.loads(response.text) - async def edit_document_docx_get_table_row_async( + def edit_document_docx_get_table_row( self, - input: GetDocxTableRowRequest, + input: GetDocxTableRowRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5660,12 +6810,28 @@ async def edit_document_docx_get_table_row_async( Gets the contents of an existing table row in a Word DOCX Document and returns the result. + + Swagger operation ID: `EditDocument_DocxGetTableRow`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/get-table-row" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5679,6 +6845,7 @@ async def edit_document_docx_get_table_row_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5686,9 +6853,9 @@ async def edit_document_docx_get_table_row_async( return json.loads(response.text) - async def edit_document_docx_get_table_by_index_async( + def edit_document_docx_get_table_by_index( self, - input: GetDocxTableByIndexRequest, + input: GetDocxTableByIndexRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5700,13 +6867,29 @@ async def edit_document_docx_get_table_by_index_async( Returns the specific table object by its 0-based index in an Office Word Document (DOCX) + + Swagger operation ID: `EditDocument_DocxGetTableByIndex`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/docx/get-table/by-index" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5720,6 +6903,7 @@ async def edit_document_docx_get_table_by_index_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5727,9 +6911,9 @@ async def edit_document_docx_get_table_by_index_async( return json.loads(response.text) - async def edit_document_docx_get_tables_async( + def edit_document_docx_get_tables( self, - input: GetDocxTablesRequest, + input: GetDocxTablesRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5740,12 +6924,28 @@ async def edit_document_docx_get_tables_async( Get all tables in Word DOCX document Returns all the table objects in an Office Word Document (docx) + + Swagger operation ID: `EditDocument_DocxGetTables`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/get-tables" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5759,6 +6959,7 @@ async def edit_document_docx_get_tables_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5766,9 +6967,9 @@ async def edit_document_docx_get_tables_async( return json.loads(response.text) - async def edit_document_docx_insert_comment_on_paragraph_async( + def edit_document_docx_insert_comment_on_paragraph( self, - input: DocxInsertCommentOnParagraphRequest, + input: DocxInsertCommentOnParagraphRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5781,13 +6982,29 @@ async def edit_document_docx_insert_comment_on_paragraph_async( Adds a new comment into a Word DOCX document attached to a paragraph and returns the result. Call Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxInsertCommentOnParagraph`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/docx/insert-comment/on/paragraph" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5801,6 +7018,7 @@ async def edit_document_docx_insert_comment_on_paragraph_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5808,9 +7026,9 @@ async def edit_document_docx_insert_comment_on_paragraph_async( return json.loads(response.text) - async def edit_document_docx_insert_image_async( + def edit_document_docx_insert_image( self, - input: DocxInsertImageRequest, + input: DocxInsertImageRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5822,12 +7040,28 @@ async def edit_document_docx_insert_image_async( Set the footer in a Word Document (DOCX). Call Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxInsertImage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/insert-image" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5841,6 +7075,7 @@ async def edit_document_docx_insert_image_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5848,9 +7083,9 @@ async def edit_document_docx_insert_image_async( return json.loads(response.text) - async def edit_document_docx_insert_paragraph_async( + def edit_document_docx_insert_paragraph( self, - input: InsertDocxInsertParagraphRequest, + input: InsertDocxInsertParagraphRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5864,13 +7099,29 @@ async def edit_document_docx_insert_paragraph_async( at the beginning/end of a document, or before/after an existing object using its Path (location within the document). Call Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxInsertParagraph`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/docx/insert-paragraph" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5884,6 +7135,7 @@ async def edit_document_docx_insert_paragraph_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5891,9 +7143,9 @@ async def edit_document_docx_insert_paragraph_async( return json.loads(response.text) - async def edit_document_docx_insert_table_async( + def edit_document_docx_insert_table( self, - input: InsertDocxTablesRequest, + input: InsertDocxTablesRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5905,12 +7157,28 @@ async def edit_document_docx_insert_table_async( Adds a new table into a DOCX and returns the result. Call Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxInsertTable`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/insert-table" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5924,6 +7192,7 @@ async def edit_document_docx_insert_table_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5931,9 +7200,9 @@ async def edit_document_docx_insert_table_async( return json.loads(response.text) - async def edit_document_docx_insert_table_row_async( + def edit_document_docx_insert_table_row( self, - input: InsertDocxTableRowRequest, + input: InsertDocxTableRowRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5945,13 +7214,29 @@ async def edit_document_docx_insert_table_row_async( Adds a new table row into a DOCX Document and returns the result. Call Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxInsertTableRow`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/docx/insert-table-row" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5965,6 +7250,7 @@ async def edit_document_docx_insert_table_row_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5972,9 +7258,9 @@ async def edit_document_docx_insert_table_row_async( return json.loads(response.text) - async def edit_document_docx_remove_headers_and_footers_async( + def edit_document_docx_remove_headers_and_footers( self, - input: RemoveDocxHeadersAndFootersRequest, + input: RemoveDocxHeadersAndFootersRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5986,13 +7272,29 @@ async def edit_document_docx_remove_headers_and_footers_async( Remove all headers, or footers, or both from a Word Document (DOCX). Call Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxRemoveHeadersAndFooters`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/docx/remove-headers-and-footers" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6006,6 +7308,7 @@ async def edit_document_docx_remove_headers_and_footers_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6013,9 +7316,9 @@ async def edit_document_docx_remove_headers_and_footers_async( return json.loads(response.text) - async def edit_document_docx_remove_object_async( + def edit_document_docx_remove_object( self, - input: DocxRemoveObjectRequest, + input: DocxRemoveObjectRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6030,12 +7333,28 @@ async def edit_document_docx_remove_object_async( delete. You can call other functions such as Get-Tables, Get-Images, Get-Body, etc. to get the paths of the objects in the document. Call Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxRemoveObject`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/remove-object" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6049,6 +7368,7 @@ async def edit_document_docx_remove_object_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6056,9 +7376,9 @@ async def edit_document_docx_remove_object_async( return json.loads(response.text) - async def edit_document_docx_replace_async( + def edit_document_docx_replace( self, - input: ReplaceStringRequest, + input: ReplaceStringRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6069,12 +7389,28 @@ async def edit_document_docx_replace_async( Replace string in Word DOCX document Replace all instances of a string in an Office Word Document (docx) + + Swagger operation ID: `EditDocument_DocxReplace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/replace-all" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6088,13 +7424,14 @@ async def edit_document_docx_replace_async( request_url, response.status, response.text, + response=response, ) return response.content - async def edit_document_docx_set_footer_async( + def edit_document_docx_set_footer( self, - input: DocxSetFooterRequest, + input: DocxSetFooterRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6106,12 +7443,28 @@ async def edit_document_docx_set_footer_async( Set the footer in a Word Document (DOCX). Call Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxSetFooter`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/set-footer" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6125,6 +7478,7 @@ async def edit_document_docx_set_footer_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6132,9 +7486,9 @@ async def edit_document_docx_set_footer_async( return json.loads(response.text) - async def edit_document_docx_set_footer_add_page_number_async( + def edit_document_docx_set_footer_add_page_number( self, - input: DocxSetFooterAddPageNumberRequest, + input: DocxSetFooterAddPageNumberRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6146,13 +7500,29 @@ async def edit_document_docx_set_footer_add_page_number_async( Set the footer in a Word Document (DOCX) to contain a page number. Call Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxSetFooterAddPageNumber`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/docx/set-footer/add-page-number" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6166,6 +7536,7 @@ async def edit_document_docx_set_footer_add_page_number_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6173,9 +7544,9 @@ async def edit_document_docx_set_footer_add_page_number_async( return json.loads(response.text) - async def edit_document_docx_set_header_async( + def edit_document_docx_set_header( self, - input: DocxSetHeaderRequest, + input: DocxSetHeaderRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6187,12 +7558,28 @@ async def edit_document_docx_set_header_async( Set the header in a Word Document (DOCX). Call Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxSetHeader`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/docx/set-header" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6206,6 +7593,7 @@ async def edit_document_docx_set_header_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6213,9 +7601,9 @@ async def edit_document_docx_set_header_async( return json.loads(response.text) - async def edit_document_docx_update_table_cell_async( + def edit_document_docx_update_table_cell( self, - input: UpdateDocxTableCellRequest, + input: UpdateDocxTableCellRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6228,13 +7616,29 @@ async def edit_document_docx_update_table_cell_async( Sets the contents of a table cell into a DOCX Document and returns the result. Call Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxUpdateTableCell`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/docx/update-table-cell" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6248,6 +7652,7 @@ async def edit_document_docx_update_table_cell_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6255,9 +7660,9 @@ async def edit_document_docx_update_table_cell_async( return json.loads(response.text) - async def edit_document_docx_update_table_row_async( + def edit_document_docx_update_table_row( self, - input: UpdateDocxTableRowRequest, + input: UpdateDocxTableRowRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6271,13 +7676,29 @@ async def edit_document_docx_update_table_row_async( Sets the contents of a table row into a DOCX Document and returns the result. Call Finish Editing on the output URL to complete the operation. + + Swagger operation ID: `EditDocument_DocxUpdateTableRow`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/docx/update-table-row" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6291,6 +7712,7 @@ async def edit_document_docx_update_table_row_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6298,9 +7720,9 @@ async def edit_document_docx_update_table_row_async( return json.loads(response.text) - async def edit_document_finish_editing_async( + def edit_document_finish_editing( self, - input: FinishEditingRequest, + input: FinishEditingRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6313,12 +7735,28 @@ async def edit_document_finish_editing_async( Once done editing a document, download the result. Begin editing a document by calling begin-editing, then perform operations, then call finish-editing to get the result. + + Swagger operation ID: `EditDocument_FinishEditing`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/finish-editing" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6332,13 +7770,14 @@ async def edit_document_finish_editing_async( request_url, response.status, response.text, + response=response, ) return response.content - async def edit_document_pptx_delete_slides_async( + def edit_document_pptx_delete_slides( self, - input: RemovePptxSlidesRequest, + input: RemovePptxSlidesRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6350,12 +7789,28 @@ async def edit_document_pptx_delete_slides_async( Edits the input PowerPoint PPTX presentation document to remove the specified slides + + Swagger operation ID: `EditDocument_PptxDeleteSlides`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/pptx/delete-slides" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6369,13 +7824,14 @@ async def edit_document_pptx_delete_slides_async( request_url, response.status, response.text, + response=response, ) return response.content - async def edit_document_pptx_replace_async( + def edit_document_pptx_replace( self, - input: ReplaceStringRequest, + input: ReplaceStringRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6387,12 +7843,28 @@ async def edit_document_pptx_replace_async( Replace all instances of a string in an Office PowerPoint Document (pptx) + + Swagger operation ID: `EditDocument_PptxReplace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/pptx/replace-all" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6406,13 +7878,14 @@ async def edit_document_pptx_replace_async( request_url, response.status, response.text, + response=response, ) return response.content - async def edit_document_xlsx_clear_cell_by_index_async( + def edit_document_xlsx_clear_cell_by_index( self, - input: ClearXlsxCellRequest, + input: ClearXlsxCellRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6424,13 +7897,29 @@ async def edit_document_xlsx_clear_cell_by_index_async( Clears, sets to blank, the contents of a specific cell in an Excel XLSX spreadsheet, worksheet + + Swagger operation ID: `EditDocument_XlsxClearCellByIndex`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/xlsx/clear-cell/by-index" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6444,6 +7933,7 @@ async def edit_document_xlsx_clear_cell_by_index_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6451,9 +7941,9 @@ async def edit_document_xlsx_clear_cell_by_index_async( return json.loads(response.text) - async def edit_document_xlsx_create_blank_spreadsheet_async( + def edit_document_xlsx_create_blank_spreadsheet( self, - input: CreateBlankSpreadsheetRequest, + input: CreateBlankSpreadsheetRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6464,12 +7954,28 @@ async def edit_document_xlsx_create_blank_spreadsheet_async( Create a blank Excel XLSX spreadsheet Returns a blank Excel XLSX Spreadsheet (XLSX) format file + + Swagger operation ID: `EditDocument_XlsxCreateBlankSpreadsheet`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/xlsx/create/blank" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6483,6 +7989,7 @@ async def edit_document_xlsx_create_blank_spreadsheet_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6490,9 +7997,9 @@ async def edit_document_xlsx_create_blank_spreadsheet_async( return json.loads(response.text) - async def edit_document_xlsx_create_spreadsheet_from_data_async( + def edit_document_xlsx_create_spreadsheet_from_data( self, - input: CreateSpreadsheetFromDataRequest, + input: CreateSpreadsheetFromDataRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6504,13 +8011,29 @@ async def edit_document_xlsx_create_spreadsheet_from_data_async( Returns a new Excel XLSX Spreadsheet (XLSX) format file populated with column and row data specified as input + + Swagger operation ID: `EditDocument_XlsxCreateSpreadsheetFromData`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/xlsx/create/from/data" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6524,6 +8047,7 @@ async def edit_document_xlsx_create_spreadsheet_from_data_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6531,9 +8055,9 @@ async def edit_document_xlsx_create_spreadsheet_from_data_async( return json.loads(response.text) - async def edit_document_xlsx_delete_worksheet_async( + def edit_document_xlsx_delete_worksheet( self, - input: RemoveXlsxWorksheetRequest, + input: RemoveXlsxWorksheetRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6546,13 +8070,29 @@ async def edit_document_xlsx_delete_worksheet_async( Edits the input Excel XLSX spreadsheet document to remove the specified worksheet (tab). Use the Get Worksheets API to enumerate available worksheets in a spreadsheet. + + Swagger operation ID: `EditDocument_XlsxDeleteWorksheet`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/xlsx/delete-worksheet" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6566,6 +8106,7 @@ async def edit_document_xlsx_delete_worksheet_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6573,9 +8114,9 @@ async def edit_document_xlsx_delete_worksheet_async( return json.loads(response.text) - async def edit_document_xlsx_get_cell_by_identifier_async( + def edit_document_xlsx_get_cell_by_identifier( self, - input: GetXlsxCellByIdentifierRequest, + input: GetXlsxCellByIdentifierRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6587,13 +8128,29 @@ async def edit_document_xlsx_get_cell_by_identifier_async( Returns the value of a specific cell based on its identifier (e.g. A1, B22, C33, etc.) in the Excel Spreadsheet worksheet + + Swagger operation ID: `EditDocument_XlsxGetCellByIdentifier`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/xlsx/get-cell/by-identifier" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6607,6 +8164,7 @@ async def edit_document_xlsx_get_cell_by_identifier_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6614,9 +8172,9 @@ async def edit_document_xlsx_get_cell_by_identifier_async( return json.loads(response.text) - async def edit_document_xlsx_get_cell_by_index_async( + def edit_document_xlsx_get_cell_by_index( self, - input: GetXlsxCellRequest, + input: GetXlsxCellRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6628,13 +8186,29 @@ async def edit_document_xlsx_get_cell_by_index_async( Returns the value and definition of a specific cell in a specific row in the Excel Spreadsheet worksheet + + Swagger operation ID: `EditDocument_XlsxGetCellByIndex`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/xlsx/get-cell/by-index" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6648,6 +8222,7 @@ async def edit_document_xlsx_get_cell_by_index_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6655,9 +8230,9 @@ async def edit_document_xlsx_get_cell_by_index_async( return json.loads(response.text) - async def edit_document_xlsx_get_columns_async( + def edit_document_xlsx_get_columns( self, - input: GetXlsxColumnsRequest, + input: GetXlsxColumnsRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6668,12 +8243,28 @@ async def edit_document_xlsx_get_columns_async( Get rows and cells from a Excel XLSX spreadsheet, worksheet Returns the rows and cells defined in the Excel Spreadsheet worksheet + + Swagger operation ID: `EditDocument_XlsxGetColumns`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/xlsx/get-columns" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6687,6 +8278,7 @@ async def edit_document_xlsx_get_columns_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6694,9 +8286,9 @@ async def edit_document_xlsx_get_columns_async( return json.loads(response.text) - async def edit_document_xlsx_get_images_async( + def edit_document_xlsx_get_images( self, - input: GetXlsxImagesRequest, + input: GetXlsxImagesRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6707,12 +8299,28 @@ async def edit_document_xlsx_get_images_async( Get images from a Excel XLSX spreadsheet, worksheet Returns the images defined in the Excel Spreadsheet worksheet + + Swagger operation ID: `EditDocument_XlsxGetImages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/xlsx/get-images" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6726,6 +8334,7 @@ async def edit_document_xlsx_get_images_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6733,9 +8342,9 @@ async def edit_document_xlsx_get_images_async( return json.loads(response.text) - async def edit_document_xlsx_get_rows_and_cells_async( + def edit_document_xlsx_get_rows_and_cells( self, - input: GetXlsxRowsAndCellsRequest, + input: GetXlsxRowsAndCellsRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6746,13 +8355,29 @@ async def edit_document_xlsx_get_rows_and_cells_async( Get rows and cells from a Excel XLSX spreadsheet, worksheet Returns the rows and cells defined in the Excel Spreadsheet worksheet + + Swagger operation ID: `EditDocument_XlsxGetRowsAndCells`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/xlsx/get-rows-and-cells" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6766,6 +8391,7 @@ async def edit_document_xlsx_get_rows_and_cells_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6773,9 +8399,9 @@ async def edit_document_xlsx_get_rows_and_cells_async( return json.loads(response.text) - async def edit_document_xlsx_get_styles_async( + def edit_document_xlsx_get_styles( self, - input: GetXlsxStylesRequest, + input: GetXlsxStylesRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6786,12 +8412,28 @@ async def edit_document_xlsx_get_styles_async( Get styles from a Excel XLSX spreadsheet, worksheet Returns the style defined in the Excel Spreadsheet + + Swagger operation ID: `EditDocument_XlsxGetStyles`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/xlsx/get-styles" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6805,6 +8447,7 @@ async def edit_document_xlsx_get_styles_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6812,9 +8455,9 @@ async def edit_document_xlsx_get_styles_async( return json.loads(response.text) - async def edit_document_xlsx_get_worksheets_async( + def edit_document_xlsx_get_worksheets( self, - input: GetXlsxWorksheetsRequest, + input: GetXlsxWorksheetsRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6826,12 +8469,28 @@ async def edit_document_xlsx_get_worksheets_async( Returns the worksheets (tabs) defined in the Excel Spreadsheet (XLSX) format file + + Swagger operation ID: `EditDocument_XlsxGetWorksheets`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/edit/xlsx/get-worksheets" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6845,6 +8504,7 @@ async def edit_document_xlsx_get_worksheets_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6852,9 +8512,9 @@ async def edit_document_xlsx_get_worksheets_async( return json.loads(response.text) - async def edit_document_xlsx_insert_worksheet_async( + def edit_document_xlsx_insert_worksheet( self, - input: InsertXlsxWorksheetRequest, + input: InsertXlsxWorksheetRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6865,13 +8525,29 @@ async def edit_document_xlsx_insert_worksheet_async( Insert a new worksheet into an Excel XLSX spreadsheet Inserts a new worksheet into an Excel Spreadsheet + + Swagger operation ID: `EditDocument_XlsxInsertWorksheet`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/xlsx/insert-worksheet" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6885,6 +8561,7 @@ async def edit_document_xlsx_insert_worksheet_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6892,9 +8569,9 @@ async def edit_document_xlsx_insert_worksheet_async( return json.loads(response.text) - async def edit_document_xlsx_set_cell_by_identifier_async( + def edit_document_xlsx_set_cell_by_identifier( self, - input: SetXlsxCellByIdentifierRequest, + input: SetXlsxCellByIdentifierRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6907,13 +8584,29 @@ async def edit_document_xlsx_set_cell_by_identifier_async( Sets, updates the contents of a specific cell in an Excel XLSX spreadsheet, worksheet using its cell identifier (e.g. A1, B22, C33) in the worksheet + + Swagger operation ID: `EditDocument_XlsxSetCellByIdentifier`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/xlsx/set-cell/by-identifier" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6927,6 +8620,7 @@ async def edit_document_xlsx_set_cell_by_identifier_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6934,9 +8628,9 @@ async def edit_document_xlsx_set_cell_by_identifier_async( return json.loads(response.text) - async def edit_document_xlsx_set_cell_by_index_async( + def edit_document_xlsx_set_cell_by_index( self, - input: SetXlsxCellRequest, + input: SetXlsxCellRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6949,13 +8643,29 @@ async def edit_document_xlsx_set_cell_by_index_async( Sets, updates the contents of a specific cell in an Excel XLSX spreadsheet, worksheet + + Swagger operation ID: `EditDocument_XlsxSetCellByIndex`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/convert/edit/xlsx/set-cell/by-index" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6969,6 +8679,7 @@ async def edit_document_xlsx_set_cell_by_index_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6976,9 +8687,9 @@ async def edit_document_xlsx_set_cell_by_index_async( return json.loads(response.text) - async def convert_web_html_to_docx_async( + def convert_web_html_to_docx( self, - input: HtmlToOfficeRequest, + input: HtmlToOfficeRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6989,10 +8700,26 @@ async def convert_web_html_to_docx_async( Convert HTML to Word DOCX Document Convert HTML to Office Word Document (DOCX) format + + Swagger operation ID: `ConvertWeb_HtmlToDocx`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/convert/html/to/docx" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7006,13 +8733,14 @@ async def convert_web_html_to_docx_async( request_url, response.status, response.text, + response=response, ) return response.content - async def convert_data_json_to_xml_async( + def convert_data_json_to_xml( self, - input: ConvertDataJsonToXmlInput, + input: ConvertDataJsonToXmlInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -7023,10 +8751,26 @@ async def convert_data_json_to_xml_async( Convert JSON to XML conversion Convert a JSON object into XML + + Swagger operation ID: `ConvertData_JsonToXml`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/convert/json/to/xml" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7040,6 +8784,7 @@ async def convert_data_json_to_xml_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7047,9 +8792,9 @@ async def convert_data_json_to_xml_async( return json.loads(response.text) - async def convert_template_apply_html_template_async( + def convert_template_apply_html_template( self, - input: HtmlTemplateApplicationRequest, + input: HtmlTemplateApplicationRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -7061,12 +8806,28 @@ async def convert_template_apply_html_template_async( Apply operations to fill in an HTML template, generating a final HTML result + + Swagger operation ID: `ConvertTemplate_ApplyHtmlTemplate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/template/html/apply" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7080,6 +8841,7 @@ async def convert_template_apply_html_template_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7087,9 +8849,9 @@ async def convert_template_apply_html_template_async( return json.loads(response.text) - async def convert_web_html_to_pdf_async( + def convert_web_html_to_pdf( self, - input: HtmlToPdfRequest, + input: HtmlToPdfRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -7101,10 +8863,26 @@ async def convert_web_html_to_pdf_async( Fully renders a website and returns a PDF of the HTML. Javascript, HTML5, CSS and other advanced features are all supported. + + Swagger operation ID: `ConvertWeb_HtmlToPdf`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/convert/web/html/to/pdf" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7118,13 +8896,14 @@ async def convert_web_html_to_pdf_async( request_url, response.status, response.text, + response=response, ) return response.content - async def convert_web_html_to_png_async( + def convert_web_html_to_png( self, - input: HtmlToPngRequest, + input: HtmlToPngRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -7136,10 +8915,26 @@ async def convert_web_html_to_png_async( Fully renders a website and returns a PNG (screenshot) of the HTML. Javascript, HTML5, CSS and other advanced features are all supported. + + Swagger operation ID: `ConvertWeb_HtmlToPng`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/convert/web/html/to/png" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7153,6 +8948,7 @@ async def convert_web_html_to_png_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7160,9 +8956,9 @@ async def convert_web_html_to_png_async( return json.loads(response.text) - async def convert_web_html_to_txt_async( + def convert_web_html_to_txt( self, - input: HtmlToTextRequest, + input: HtmlToTextRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -7173,10 +8969,26 @@ async def convert_web_html_to_txt_async( Convert HTML string to text (txt) Converts an HTML string input into text (txt); extracts text from HTML + + Swagger operation ID: `ConvertWeb_HtmlToTxt`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/convert/web/html/to/txt" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7190,6 +9002,7 @@ async def convert_web_html_to_txt_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7197,9 +9010,9 @@ async def convert_web_html_to_txt_async( return json.loads(response.text) - async def convert_web_url_to_pdf_async( + def convert_web_url_to_pdf( self, - input: ScreenshotRequest, + input: ScreenshotRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -7211,10 +9024,26 @@ async def convert_web_url_to_pdf_async( Fully renders a website and returns a PDF of the full page. Javascript, HTML5, CSS and other advanced features are all supported. + + Swagger operation ID: `ConvertWeb_UrlToPdf`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/convert/web/url/to/pdf" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7228,13 +9057,14 @@ async def convert_web_url_to_pdf_async( request_url, response.status, response.text, + response=response, ) return response.content - async def convert_web_url_to_screenshot_async( + def convert_web_url_to_screenshot( self, - input: ScreenshotRequest, + input: ScreenshotRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -7247,12 +9077,28 @@ async def convert_web_url_to_screenshot_async( Fully renders a website and returns a PNG screenshot of the full page image. Javascript, HTML5, CSS and other advanced features are all supported. + + Swagger operation ID: `ConvertWeb_UrlToScreenshot`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/convert/web/url/to/screenshot" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7266,13 +9112,14 @@ async def convert_web_url_to_screenshot_async( request_url, response.status, response.text, + response=response, ) return response.content - async def convert_web_url_to_txt_async( + def convert_web_url_to_txt( self, - input: UrlToTextRequest, + input: UrlToTextRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -7283,10 +9130,26 @@ async def convert_web_url_to_txt_async( Convert website URL page to text (txt) Converts a website URL page into text (txt); extracts text from HTML + + Swagger operation ID: `ConvertWeb_UrlToTxt`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/convert/web/url/to/txt" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7300,6 +9163,7 @@ async def convert_web_url_to_txt_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/commondataservice.py b/src/azure/connectors/commondataservice.py index 39483a2..30ce021 100644 --- a/src/azure/connectors/commondataservice.py +++ b/src/azure/connectors/commondataservice.py @@ -5,21 +5,71 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping from urllib.parse import quote, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "CommondataserviceClient", + "ActionsDynamicValuesList", + "AssociateEntityRequest", + "AssociateRecordsPatchItemInput", + "BlobDataSetsMetadata", + "CallbackRegistration", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "DisplayCollectionName", + "EntitiesDynamicValuesList", + "EntitiesDynamicValuesListItem", + "EntityItem", + "EntityItemList", + "EntityMetadata", + "EntityRelationshipsDynamicValuesList", + "GetItemResponse", + "Item", + "ItemsList", + "ObjectEntity", + "OrganizationsDynamicValuesList", + "OrganizationsDynamicValuesListItem", + "PassThroughNativeQuery", + "PatchItemInput", + "PatchItemResponse", + "PostItemInput", + "PostItemResponse", + "Procedure", + "SearchOutput", + "SearchRequestBody", + "SubscriptionRequest", + "SubscriptionResponse", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TablesList", + "TabularDataSetsMetadata", + "UpdateTriggerSubscriptionRequest", + "UserLocalizedLabel", + "WebhookNotificationContent", + "WebhookNotificationContentForWhenAnActionIsPerformed", + "WhenAnActionIsPerformedSubscriptionRequest", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,8 +79,18 @@ class DataSetsMetadata: Response for GetDataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -39,7 +99,7 @@ class AssociateRecordsPatchItemInput: Associates one row to another on the provided relationship """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -52,8 +112,9 @@ class Item: Response for Associates one row to another on the provided relationship """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) @@ -64,10 +125,16 @@ class ItemsList: Response for Retrieves all collection valued relationship items as an expand would """ - value: Optional[List[Item]] = None + value: Optional[ + List[Item | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Items""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -79,7 +146,12 @@ class DataSetsList: Response for GetDataSets """ - value: Optional[List[DataSet]] = None + value: Optional[ + List[DataSet | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of datasets""" @@ -89,7 +161,7 @@ class GetItemResponse: Response for Get row (legacy) """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -102,26 +174,30 @@ class TableMetadata: Response for Get table metadata - Patch """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Table name""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Table title""" - x_ms_permission: Optional[str] = field( + x_ms_permission: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-permission"}, ) """Table permission""" - x_ms_capabilities: Optional[TableCapabilitiesMetadata] = field( + x_ms_capabilities: Optional[TableCapabilitiesMetadata | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-capabilities"}, ) - schema: Optional[ObjectEntity] = None - referenced_entities: Optional[ObjectEntity] = field( + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + referenced_entities: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "referencedEntities"}, ) - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webUrl"}, ) """Url link""" @@ -133,7 +209,7 @@ class ObjectEntity: Response for Retrieves the metadata for multi select column metadata """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -146,7 +222,12 @@ class TablesList: Response for GetTables """ - value: Optional[List[Table]] = None + value: Optional[ + List[Table | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Tables""" @@ -156,7 +237,7 @@ class PatchItemInput: Update a row (legacy) """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -169,7 +250,7 @@ class PatchItemResponse: Response for Update a row (legacy) """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -182,7 +263,7 @@ class PostItemInput: Add a new row (legacy) """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -195,7 +276,7 @@ class PostItemResponse: Response for Add a new row (legacy) """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -208,25 +289,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -238,15 +323,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -258,30 +345,42 @@ class TableCapabilitiesMetadata: Definition: TableCapabilitiesMetadata """ - sort_restrictions: Optional[TableSortRestrictionsMetadata] = field( + sort_restrictions: Optional[ + TableSortRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sortRestrictions"}, ) - filter_restrictions: Optional[TableFilterRestrictionsMetadata] = field( + filter_restrictions: Optional[ + TableFilterRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterRestrictions"}, ) - select_restrictions: Optional[TableSelectRestrictionsMetadata] = field( + select_restrictions: Optional[ + TableSelectRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selectRestrictions"}, ) - is_only_server_pagable: Optional[bool] = field( + is_only_server_pagable: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isOnlyServerPagable"}, ) """Server paging restrictions""" - filter_function_support: Optional[List[str]] = field( + filter_function_support: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterFunctionSupport"}, ) """List of supported filter capabilities""" - server_paging_options: Optional[List[str]] = field( + server_paging_options: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "serverPagingOptions"}, ) """List of supported server-driven paging capabilities""" @@ -293,15 +392,17 @@ class TableSortRestrictionsMetadata: Definition: TableSortRestrictionsMetadata """ - sortable: Optional[bool] = None + sortable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has sortable columns""" - unsortable_properties: Optional[List[str]] = field( + unsortable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "unsortableProperties"}, ) """List of unsortable properties""" - ascending_only_properties: Optional[List[str]] = field( + ascending_only_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ascendingOnlyProperties"}, ) """List of properties which support ascending order only""" @@ -313,15 +414,17 @@ class TableFilterRestrictionsMetadata: Definition: TableFilterRestrictionsMetadata """ - filterable: Optional[bool] = None + filterable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has filterable columns""" - non_filterable_properties: Optional[List[str]] = field( + non_filterable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nonFilterableProperties"}, ) """List of non filterable properties""" - required_properties: Optional[List[str]] = field( + required_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredProperties"}, ) """List of required properties""" @@ -333,7 +436,7 @@ class TableSelectRestrictionsMetadata: Definition: TableSelectRestrictionsMetadata """ - selectable: Optional[bool] = None + selectable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has selectable columns""" @@ -343,8 +446,7 @@ class SubscriptionRequest: Definition: SubscriptionRequest """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "NotificationUrl"}, ) """ @@ -359,17 +461,19 @@ class SubscriptionResponse: Definition: SubscriptionResponse """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id of the subscription""" - resource: Optional[str] = None + resource: Optional[str] = dataclass_field(default=None, kw_only=True) """Resource of the subscription request""" - notification_type: Optional[str] = field( + notification_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notificationType"}, ) """Notification Type""" - notification_url: Optional[str] = field( + notification_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notificationUrl"}, ) """Notification Url""" @@ -381,13 +485,13 @@ class UpdateTriggerSubscriptionRequest: Definition: UpdateTriggerSubscriptionRequest """ - attribute_filters: Optional[List[str]] = field( + attribute_filters: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AttributeFilters"}, ) """Column filters""" - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "NotificationUrl"}, ) """ @@ -402,14 +506,24 @@ class DataSet: Definition: DataSet """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Dataset name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Dataset display name""" - query: Optional[List[PassThroughNativeQuery]] = None + query: Optional[ + List[PassThroughNativeQuery | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Pass-through Native Queries""" @@ -419,15 +533,21 @@ class Table: Definition: Table """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the table. The name is used at runtime.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the table.""" - dynamic_properties: Optional[Dict[str, str]] = field( + dynamic_properties: Optional[Dict[str, str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DynamicProperties"}, ) """Additional table properties provided by the connector to the clients.""" @@ -439,10 +559,15 @@ class Procedure: Definition: Procedure """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Procedure name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Procedure display name""" @@ -454,8 +579,9 @@ class PassThroughNativeQuery: Definition: PassThroughNativeQuery """ - language: Optional[str] = field( + language: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Language"}, ) """Query language""" @@ -467,8 +593,9 @@ class DisplayCollectionName: Definition: DisplayCollectionName """ - user_localized_label: Optional[UserLocalizedLabel] = field( + user_localized_label: Optional[UserLocalizedLabel | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userLocalizedLabel"}, ) """The user localized display name label object.""" @@ -480,7 +607,12 @@ class EntitiesDynamicValuesList: Definition: EntitiesDynamicValuesList """ - value: Optional[List[EntitiesDynamicValuesListItem]] = None + value: Optional[ + List[EntitiesDynamicValuesListItem | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of tables as dynamic values.""" @@ -490,23 +622,27 @@ class EntitiesDynamicValuesListItem: Definition: EntitiesDynamicValuesListItem """ - metadata_id: Optional[str] = field( + metadata_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "metadataId"}, ) """The metadata id.""" - entity_set_name: Optional[str] = field( + entity_set_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "entitySetName"}, ) """The name of the table.""" - logical_name: Optional[str] = field( + logical_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "logicalName"}, ) """The logical name of the table.""" - display_collection_name: Optional[DisplayCollectionName] = field( + display_collection_name: Optional[DisplayCollectionName | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayCollectionName"}, ) """The display name of the table.""" @@ -518,7 +654,12 @@ class OrganizationsDynamicValuesList: Definition: OrganizationsDynamicValuesList """ - value: Optional[List[OrganizationsDynamicValuesListItem]] = None + value: Optional[ + List[OrganizationsDynamicValuesListItem | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of organizations as dynamic values.""" @@ -528,14 +669,23 @@ class OrganizationsDynamicValuesListItem: Definition: OrganizationsDynamicValuesListItem """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The organization id.""" - friendly_name: Optional[str] = field( + friendly_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FriendlyName"}, ) """The name of the organization.""" - url: Optional[str] = field(default=None, metadata={"wire_name": "Url"}) + url: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Url"}, + ) """The URL of the organization.""" @@ -545,7 +695,7 @@ class EntityMetadata: Definition: EntityMetadata """ - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) """Swagger schema""" @@ -555,10 +705,16 @@ class EntityItemList: Definition: EntityItemList """ - value: Optional[List[EntityItem]] = None + value: Optional[ + List[EntityItem | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Items""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The url to fetch next page data.""" @@ -570,8 +726,9 @@ class EntityItem: Definition: EntityItem """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) @@ -582,38 +739,38 @@ class CallbackRegistration: Definition: CallbackRegistration """ - version: Optional[int] = None + version: int """The callback registration table version""" - url: Optional[str] = None + url: str """ Callback url to the flow engine. Expected as part of the request and provided by Flow. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Callback registration name. Value will be replaced with workflow id""" - entityname: Optional[str] = None + entityname: str """Choose a table""" - message: Optional[int] = None + message: int """Choose when the flow triggers""" - sdkmessagename: Optional[str] = None + sdkmessagename: Optional[str] = dataclass_field(default=None, kw_only=True) """Choose an option or add your own""" - scope: Optional[int] = None + scope: int """Choose a scope to limit which rows can trigger the flow""" - filteringattributes: Optional[str] = None + filteringattributes: Optional[str] = dataclass_field(default=None, kw_only=True) """ Enter a comma-separated list of column unique names. The flow triggers if any of them are modified """ - filterexpression: Optional[str] = None + filterexpression: Optional[str] = dataclass_field(default=None, kw_only=True) """ Enter an OData style filter expression to determine which rows can trigger the flow """ - postponeuntil: Optional[str] = None + postponeuntil: Optional[str] = dataclass_field(default=None, kw_only=True) """ Enter a time to delay the trigger evaluation, eg. 2020-01-01T10:10:00Z """ - runas: Optional[int] = None + runas: Optional[int] = dataclass_field(default=None, kw_only=True) """Choose the running user for steps where invoker connections are used""" @@ -623,7 +780,7 @@ class UserLocalizedLabel: Definition: UserLocalizedLabel """ - label: Optional[str] = None + label: Optional[str] = dataclass_field(default=None, kw_only=True) """The display name label of the table.""" @@ -633,7 +790,7 @@ class WebhookNotificationContent: Definition: WebhookNotificationContent """ - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) """Swagger schema""" @@ -643,7 +800,7 @@ class EntityRelationshipsDynamicValuesList: Definition: EntityRelationshipsDynamicValuesList """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of table relationships as dynamic values.""" @@ -653,10 +810,7 @@ class AssociateEntityRequest: Definition: AssociateEntityRequest """ - id: Optional[str] = field( - default=None, - metadata={"wire_name": "@odata.id"}, - ) + id: str = dataclass_field(metadata={"wire_name": "@odata.id"}) """ Enter the row URL using OData ID from a previous step or typing the full URL (eg. @@ -670,7 +824,7 @@ class ActionsDynamicValuesList: Definition: ActionsDynamicValuesList """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of actions as dynamic values""" @@ -680,40 +834,40 @@ class SearchRequestBody: Definition: SearchRequestBody """ - search: Optional[str] = None + search: str """ Enter a search term, eg. Contoso. Searches modifiers like boolean operators, wildcards, fuzzy search, proximity search etc. require the search type full """ - searchtype: Optional[str] = None + searchtype: Optional[str] = dataclass_field(default=None, kw_only=True) """ Enter whether simple or full search syntax should be used (default is simple) """ - searchmode: Optional[str] = None + searchmode: Optional[str] = dataclass_field(default=None, kw_only=True) """ Enter whether any or all of the search terms must be matched (default is any) """ - top: Optional[int] = None + top: Optional[int] = dataclass_field(default=None, kw_only=True) """Enter the number of search results to be listed (default = 50)""" - filter: Optional[str] = None + filter: Optional[str] = dataclass_field(default=None, kw_only=True) """Enter an OData style filter expression to narrow the search""" - entities: Optional[List[str]] = None + entities: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ Enter a comma-separated list of tables to be searched (default is all tables) """ - orderby: Optional[List[str]] = None + orderby: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ Enter a comma-separated list of column unique names followed by asc or desc """ - facets: Optional[List[str]] = None + facets: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Enter a comma-separated list of facet queries to narrow the search""" - skip: Optional[int] = None + skip: Optional[int] = dataclass_field(default=None, kw_only=True) """Enter the number of search results to be skipped""" - returntotalrecordcount: Optional[bool] = None + returntotalrecordcount: Optional[bool] = dataclass_field(default=None, kw_only=True) """Choose an option""" @@ -723,11 +877,11 @@ class SearchOutput: Definition: SearchOutput """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of rows""" - totalrecordcount: Optional[int] = None + totalrecordcount: Optional[int] = dataclass_field(default=None, kw_only=True) """Total count of results (-1 if returntotalrecordcount is set to false)""" - facets: Optional[Dict[str, Any]] = None + facets: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Facet results""" @@ -737,20 +891,20 @@ class WhenAnActionIsPerformedSubscriptionRequest: Definition: WhenAnActionIsPerformedSubscriptionRequest """ - version: Optional[int] = None + version: int """The callback registration table version.""" - url: Optional[str] = None + url: str """ Callback url to the flow engine. Expected as part of the request and provided by Flow. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Callback registration name. Value will be replaced with workflow id.""" - scope: Optional[int] = None + scope: int """Choose a scope to limit which rows can trigger the flow.""" - entityname: Optional[str] = None + entityname: str """Choose a table to filter actions.""" - sdkmessagename: Optional[str] = None + sdkmessagename: str """Choose an action.""" @@ -760,7 +914,7 @@ class WebhookNotificationContentForWhenAnActionIsPerformed: Definition: WebhookNotificationContentForWhenAnActionIsPerformed """ - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) """Swagger schema""" @@ -772,16 +926,16 @@ class CommondataserviceClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -792,8 +946,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -801,8 +955,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -814,7 +968,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -869,7 +1023,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def get_data_sets_metadata_async( + def get_data_sets_metadata( self, *, timeout: Optional[float] = None, @@ -879,10 +1033,24 @@ async def get_data_sets_metadata_async( ) -> dict[str, Any] | None: """ GetDataSetsMetadata + + Swagger operation ID: `GetDataSetsMetadata`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/$metadata.json/datasets" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -896,6 +1064,7 @@ async def get_data_sets_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -903,7 +1072,7 @@ async def get_data_sets_metadata_async( return json.loads(response.text) - async def get_next_page_async( + def get_next_page( self, next_link: str, *, @@ -916,13 +1085,28 @@ async def get_next_page_async( Follows nextLink to retrieve next page of data This operation gets the next page of data. + + Swagger operation ID: `GetNextPage`. + + Args: + next_link: OData nextLink. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/nextLink/{quote(str(next_link), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -936,6 +1120,7 @@ async def get_next_page_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -943,9 +1128,9 @@ async def get_next_page_async( return json.loads(response.text) - async def associate_records_patch_item_async( + def associate_records_patch_item( self, - input: AssociateRecordsPatchItemInput, + input: AssociateRecordsPatchItemInput | Mapping[str, Any], dataset: str, table: str, id: str, @@ -960,6 +1145,26 @@ async def associate_records_patch_item_async( Associates one row to another on the provided relationship Associates one row to another on the provided relationship + + Swagger operation ID: `AssociateRecordsPatchItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Select an Environment. + table: Name of the table. + id: Id of the table row. + relationship: Relationship on which to associate. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -974,7 +1179,7 @@ async def associate_records_patch_item_async( f"/{quote(quote(str(relationship), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -988,6 +1193,7 @@ async def associate_records_patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -995,7 +1201,7 @@ async def associate_records_patch_item_async( return json.loads(response.text) - async def create_attachment_async( + def create_attachment( self, input: bytes, dataset: str, @@ -1012,6 +1218,25 @@ async def create_attachment_async( Creates Note (annotation) for specified table row Creates Note (annotation) for specified table row. + + Swagger operation ID: `CreateAttachment_V2`. + + Args: + input: The binary request body. + dataset: Select an Environment. + table: Table on which to create Note (annotation). + id: Id of the table row on which to create a Note (annotation). + display_name: Filename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1032,7 +1257,7 @@ async def create_attachment_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -1049,6 +1274,7 @@ async def create_attachment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1056,7 +1282,7 @@ async def create_attachment_async( return json.loads(response.text) - async def delete_attachment_async( + def delete_attachment( self, dataset: str, table: str, @@ -1072,6 +1298,24 @@ async def delete_attachment_async( Deletes specified attachment on the Note (annotation) Deletes specified attachment on the Note (annotation). + + Swagger operation ID: `DeleteAttachment_V2`. + + Args: + dataset: Select an Environment. + table: Table on which to delete Note (annotation). + id: Id of the table row on which to delete a Note (annotation). + attachment_id: Note (annotation) id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1086,7 +1330,7 @@ async def delete_attachment_async( f"/{quote(quote(str(attachment_id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1100,9 +1344,10 @@ async def delete_attachment_async( request_url, response.status, response.text, + response=response, ) - async def delete_item_async( + def delete_item( self, dataset: str, table: str, @@ -1117,6 +1362,23 @@ async def delete_item_async( Delete a row (legacy) This operation deletes a row from a table collection + + Swagger operation ID: `DeleteItem_V2`. + + Args: + dataset: Select an Environment. + table: Select a table. + id: Identifier for the row. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1129,7 +1391,7 @@ async def delete_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1143,9 +1405,10 @@ async def delete_item_async( request_url, response.status, response.text, + response=response, ) - async def disassociate_records_post_item_async( + def disassociate_records_post_item( self, dataset: str, table: str, @@ -1162,6 +1425,25 @@ async def disassociate_records_post_item_async( Disassociates a row from a multi-valued relationship Disassociates a row from a multi-valued relationship + + Swagger operation ID: `DisassociateRecordsPostItem_V2`. + + Args: + dataset: Select an Environment. + table: Name of the table. + id: Id of the table row. + relationship: Relationship on which to associate. + related_id: The item to disassociate. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1178,7 +1460,7 @@ async def disassociate_records_post_item_async( f"/{quote(quote(str(related_id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1192,6 +1474,7 @@ async def disassociate_records_post_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1199,7 +1482,7 @@ async def disassociate_records_post_item_async( return json.loads(response.text) - async def disassociate_single_value_record_delete_item_async( + def disassociate_single_value_record_delete_item( self, dataset: str, table: str, @@ -1215,6 +1498,24 @@ async def disassociate_single_value_record_delete_item_async( Disassociates a row from a single-valued relationship Disassociates a row from a single-valued relationship + + Swagger operation ID: `DisassociateSingleValueRecordDeleteItem_V2`. + + Args: + dataset: Select an Environment. + table: Name of the table. + id: Id of the table row. + relationship: Relationship on which to associate. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1229,7 +1530,7 @@ async def disassociate_single_value_record_delete_item_async( f"/{quote(quote(str(relationship), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1243,6 +1544,7 @@ async def disassociate_single_value_record_delete_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1250,7 +1552,7 @@ async def disassociate_single_value_record_delete_item_async( return json.loads(response.text) - async def get_attachment_content_async( + def get_attachment_content( self, dataset: str, table: str, @@ -1266,6 +1568,24 @@ async def get_attachment_content_async( Retrieves file content for specified Note (annotation) Retrieves file content for specified Note (annotation). + + Swagger operation ID: `GetAttachmentContent_V2`. + + Args: + dataset: Select an Environment. + table: Table for which to get Note (annotation) content. + id: Id of the table row for which to get Notes (annotations). + attachment_id: Note (annotation) id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1281,7 +1601,7 @@ async def get_attachment_content_async( f"/$value" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1295,11 +1615,12 @@ async def get_attachment_content_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_collection_relationships_async( + def list_collection_relationships( self, dataset: str, table: str, @@ -1312,11 +1633,35 @@ async def get_collection_relationships_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Retrieves all collection valued relationship items as an expand would Retrieves all collection valued relationship items as an expand would + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetCollectionRelationships_V2`. + + Args: + dataset: Select an Environment. + table: Name of the table. + id: Id of the table row. + collection_type: many to many or not. + relationship: Relationship on which to expand. + target: Target table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1333,63 +1678,123 @@ async def get_collection_relationships_async( f"/TargetTable" f"/{quote(quote(str(target), safe=''), safe='')}" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def get_data_sets_async( + return ItemPaged(get_next, extract_data) + + def list_data_sets( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ GetDataSets + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetDataSets_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/datasets" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def get_item_async( + return ItemPaged(get_next, extract_data) + + def get_item( self, dataset: str, table: str, @@ -1404,6 +1809,23 @@ async def get_item_async( Get row (legacy) This operation retrieves the specified row for a table + + Swagger operation ID: `GetItem_V2`. + + Args: + dataset: Select an Environment. + table: Select a table. + id: Identifier for the row. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1416,7 +1838,7 @@ async def get_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1430,6 +1852,7 @@ async def get_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1437,7 +1860,7 @@ async def get_item_async( return json.loads(response.text) - async def get_item_attachments_async( + def list_item_attachments( self, dataset: str, table: str, @@ -1447,11 +1870,32 @@ async def get_item_attachments_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Retrieves all Notes (annotations) for the provided table row Id Retrieves all Notes (annotations) for the provided table row Id. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItemAttachments_V2`. + + Args: + dataset: Select an Environment. + table: Table for which to get Notes (annotations). + id: Id of the table row for which to get Notes (annotations). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1464,50 +1908,96 @@ async def get_item_attachments_async( f"/{quote(quote(str(id), safe=''), safe='')}" f"/attachments" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_items_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_items( self, dataset: str, table: str, + *, apply: Optional[str] = None, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, expand: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List rows (legacy) This operation gets rows for a table - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItems_V2`. + + Args: + dataset: Select an Environment. + table: Select a table. + apply: A sequence of OData aggregation transformations. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + expand: Related entries to include with requested entries (default + = none). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1546,11 +2036,18 @@ async def get_items_async( query_params.append(f"$expand={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1563,23 +2060,32 @@ async def get_items_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def get_metadata_for_patch_item_async( + def get_metadata_for_patch_item( self, dataset: str, table: str, @@ -1593,6 +2099,22 @@ async def get_metadata_for_patch_item_async( Get table metadata - Patch Gets table metadata for patch operation + + Swagger operation ID: `GetMetadataForPatchItem_V2`. + + Args: + dataset: Select an Environment. + table: Select a table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1605,7 +2127,7 @@ async def get_metadata_for_patch_item_async( f"/patchitem" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1619,6 +2141,7 @@ async def get_metadata_for_patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1626,7 +2149,7 @@ async def get_metadata_for_patch_item_async( return json.loads(response.text) - async def get_metadata_for_post_item_async( + def get_metadata_for_post_item( self, dataset: str, table: str, @@ -1640,6 +2163,22 @@ async def get_metadata_for_post_item_async( Get table metadata - Post Gets table metadata for post operation + + Swagger operation ID: `GetMetadataForPostItem_V2`. + + Args: + dataset: Select an Environment. + table: Select a table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1652,7 +2191,7 @@ async def get_metadata_for_post_item_async( f"/postitem" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1666,6 +2205,7 @@ async def get_metadata_for_post_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1673,7 +2213,7 @@ async def get_metadata_for_post_item_async( return json.loads(response.text) - async def get_multi_select_metadata_async( + def get_multi_select_metadata( self, dataset: str, table: str, @@ -1688,6 +2228,23 @@ async def get_multi_select_metadata_async( Retrieves the metadata for multi select column metadata Retrieves the metadata for multi select column metadata. + + Swagger operation ID: `GetMultiSelectMetadata_V2`. + + Args: + dataset: org name. + table: table name. + item: id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1701,7 +2258,7 @@ async def get_multi_select_metadata_async( f"/MultiSelect" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1715,6 +2272,7 @@ async def get_multi_select_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1722,7 +2280,7 @@ async def get_multi_select_metadata_async( return json.loads(response.text) - async def get_option_set_metadata_async( + def get_option_set_metadata( self, dataset: str, table: str, @@ -1738,6 +2296,24 @@ async def get_option_set_metadata_async( Retrieves the metadata for choice column metadata Retrieves the metadata for choice column metadata. + + Swagger operation ID: `GetOptionSetMetadata_V2`. + + Args: + dataset: org name. + table: table name. + item: id. + type_: type of choice. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1752,7 +2328,7 @@ async def get_option_set_metadata_async( f"/{quote(str(type_), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1766,6 +2342,7 @@ async def get_option_set_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1773,7 +2350,7 @@ async def get_option_set_metadata_async( return json.loads(response.text) - async def get_table_async( + def get_table( self, dataset: str, table: str, @@ -1787,6 +2364,22 @@ async def get_table_async( Get table metadata Gets table metadata + + Swagger operation ID: `GetTable_V2`. + + Args: + dataset: Select an Environment. + table: Select atable. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1798,7 +2391,7 @@ async def get_table_async( f"/{quote(quote(str(table), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1812,6 +2405,7 @@ async def get_table_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1819,7 +2413,7 @@ async def get_table_async( return json.loads(response.text) - async def get_tables_async( + def list_tables( self, dataset: str, *, @@ -1827,9 +2421,28 @@ async def get_tables_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ GetTables + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTables_V2`. + + Args: + dataset: dataset. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1838,31 +2451,52 @@ async def get_tables_async( f"/{quote(quote(str(dataset), safe=''), safe='')}" f"/tables" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def patch_item_async( + return ItemPaged(get_next, extract_data) + + def patch_item( self, - input: PatchItemInput, + input: PatchItemInput | Mapping[str, Any], dataset: str, table: str, id: str, @@ -1876,6 +2510,25 @@ async def patch_item_async( Update a row (legacy) This operation updates an existing row for a table + + Swagger operation ID: `PatchItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Select an Environment. + table: Select a table. + id: Identifier for the row. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1888,7 +2541,7 @@ async def patch_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -1902,6 +2555,7 @@ async def patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1909,9 +2563,9 @@ async def patch_item_async( return json.loads(response.text) - async def post_item_async( + def post_item( self, - input: PostItemInput, + input: PostItemInput | Mapping[str, Any], dataset: str, table: str, *, @@ -1924,6 +2578,24 @@ async def post_item_async( Add a new row (legacy) This operation adds a new row of a table + + Swagger operation ID: `PostItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Select an Environment. + table: Select a table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1935,7 +2607,7 @@ async def post_item_async( f"/items" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1949,6 +2621,7 @@ async def post_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/documentdb.py b/src/azure/connectors/documentdb.py index b6af71f..9d3152b 100644 --- a/src/azure/connectors/documentdb.py +++ b/src/azure/connectors/documentdb.py @@ -5,21 +5,53 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "DocumentdbClient", + "CosmosDbAccount", + "CosmosDbAccountList", + "CreateStoredProcedureInput", + "CreateStoredProcedureResponse", + "DataWithSensitivityLabelInfo", + "DocumentsCollection", + "DocumentsQuery", + "ExecuteStoredProcedureInput", + "GetAccountResponse", + "GetCollectionResponse", + "GetCollectionsResponse", + "GetDatabaseResponse", + "GetDatabasesResponse", + "GetDocumentResponse", + "GetDocumentsResponse", + "GetStoredProceduresResponse", + "ObjectEntity", + "ObjectWithoutType", + "PostDocumentsRequest", + "PostDocumentsResponse", + "PutDocumentRequest", + "PutDocumentResponse", + "QueryDocumentsResponse", + "QueryRequest", + "QueryResponse", + "ReplaceStoredProcedureInput", + "SensitivityLabelMetadata", +] + # Type Definitions @@ -29,15 +61,32 @@ class PostDocumentsResponse: Response for Create or update document """ - rid: Optional[str] = field(default=None, metadata={"wire_name": "_rid"}) - ts: Optional[int] = field(default=None, metadata={"wire_name": "_ts"}) - self: Optional[str] = field(default=None, metadata={"wire_name": "_self"}) - etag: Optional[str] = field(default=None, metadata={"wire_name": "_etag"}) - attachments: Optional[str] = field( + rid: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_rid"}, + ) + ts: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_ts"}, + ) + self: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_self"}, + ) + etag: Optional[str] = dataclass_field( default=None, + kw_only=True, + metadata={"wire_name": "_etag"}, + ) + attachments: Optional[str] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "_attachments"}, ) - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -46,11 +95,11 @@ class CreateStoredProcedureInput: Create stored procedure """ - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """ Function that defines the stored procedure, e.g. 'function(params){ ... }' """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """New id of the stored procedure.""" @@ -60,17 +109,33 @@ class CreateStoredProcedureResponse: Response for Create stored procedure """ - etag: Optional[str] = field(default=None, metadata={"wire_name": "_etag"}) + etag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_etag"}, + ) """_etag""" - rid: Optional[str] = field(default=None, metadata={"wire_name": "_rid"}) + rid: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_rid"}, + ) """_rid""" - self: Optional[str] = field(default=None, metadata={"wire_name": "_self"}) + self: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_self"}, + ) """_self""" - ts: Optional[int] = field(default=None, metadata={"wire_name": "_ts"}) + ts: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_ts"}, + ) """_ts""" - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """body""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" @@ -83,7 +148,7 @@ class ObjectWithoutType: Response for Execute stored procedure """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -96,8 +161,11 @@ class GetDocumentResponse: Response for Get a document """ - metadata: Optional[List[DataWithSensitivityLabelInfo]] = field( + metadata: Optional[ + List[DataWithSensitivityLabelInfo | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@metadata"}, ) """List of columns along with their Sensitivity Labels""" @@ -109,13 +177,21 @@ class GetDocumentsResponse: Response for Get all documents """ - rid: Optional[str] = field(default=None, metadata={"wire_name": "_rid"}) - documents: Optional[List[Dict[str, Any]]] = field( + rid: Optional[str] = dataclass_field( default=None, + kw_only=True, + metadata={"wire_name": "_rid"}, + ) + documents: Optional[List[Dict[str, Any]]] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "Documents"}, ) - metadata: Optional[List[DataWithSensitivityLabelInfo]] = field( + metadata: Optional[ + List[DataWithSensitivityLabelInfo | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@metadata"}, ) """List of columns along with their Sensitivity Labels""" @@ -127,15 +203,21 @@ class GetStoredProceduresResponse: Response for Get stored procedures """ - count: Optional[int] = field( + count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_count"}, ) """_count""" - rid: Optional[str] = field(default=None, metadata={"wire_name": "_rid"}) + rid: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_rid"}, + ) """_rid""" - stored_procedures: Optional[List[Dict[str, Any]]] = field( + stored_procedures: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StoredProcedures"}, ) """StoredProcedures""" @@ -147,31 +229,48 @@ class QueryDocumentsResponse: Response for Query documents """ - value: Optional[List[ObjectWithoutType]] = None - continuation_token: Optional[str] = field( + value: Optional[ + List[ObjectWithoutType | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, + ) + continuation_token: Optional[str] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "ContinuationToken"}, ) - count: Optional[int] = field(default=None, metadata={"wire_name": "Count"}) - request_charge: Optional[float] = field( + count: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Count"}, + ) + request_charge: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequestCharge"}, ) - session_token: Optional[str] = field( + session_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SessionToken"}, ) - activity_id: Optional[str] = field( + activity_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ActivityId"}, ) - metadata: Optional[List[DataWithSensitivityLabelInfo]] = field( + metadata: Optional[ + List[DataWithSensitivityLabelInfo | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@metadata"}, ) """List of columns along with their Sensitivity Labels""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to retrieve the next page.""" @@ -183,8 +282,12 @@ class PutDocumentResponse: Response for Replace a document """ - rid: Optional[str] = field(default=None, metadata={"wire_name": "_rid"}) - id: Optional[str] = None + rid: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_rid"}, + ) + id: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -193,11 +296,11 @@ class ReplaceStoredProcedureInput: Replace stored procedure """ - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """ Function that defines the stored procedure, e.g. 'function(params){ ... }' """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id of the existing stored procedure.""" @@ -207,7 +310,12 @@ class CosmosDbAccountList: Response for Get Cosmos DB accounts """ - value: Optional[List[CosmosDbAccount]] = None + value: Optional[ + List[CosmosDbAccount | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Azure Cosmos DB account names""" @@ -217,13 +325,19 @@ class GetDatabasesResponse: Response for Get all databases """ - rid: Optional[str] = field(default=None, metadata={"wire_name": "_rid"}) - databases: Optional[List[Dict[str, Any]]] = field( + rid: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_rid"}, + ) + databases: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Databases"}, ) - count: Optional[int] = field( + count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_count"}, ) @@ -234,13 +348,19 @@ class GetCollectionsResponse: Response for Get all collections """ - rid: Optional[str] = field(default=None, metadata={"wire_name": "_rid"}) - document_collections: Optional[List[Dict[str, Any]]] = field( + rid: Optional[str] = dataclass_field( default=None, + kw_only=True, + metadata={"wire_name": "_rid"}, + ) + document_collections: Optional[List[Dict[str, Any]]] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "DocumentCollections"}, ) - count: Optional[int] = field( + count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_count"}, ) @@ -251,8 +371,9 @@ class DocumentsQuery: Definition: DocumentsQuery """ - query_text: Optional[str] = field( + query_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "QueryText"}, ) """SQL Syntax Query over documents""" @@ -264,7 +385,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -277,22 +398,35 @@ class DocumentsCollection: Definition: DocumentsCollection """ - value: Optional[List[ObjectWithoutType]] = None - continuation_token: Optional[str] = field( + value: Optional[ + List[ObjectWithoutType | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, + ) + continuation_token: Optional[str] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "ContinuationToken"}, ) - count: Optional[int] = field(default=None, metadata={"wire_name": "Count"}) - request_charge: Optional[float] = field( + count: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Count"}, + ) + request_charge: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequestCharge"}, ) - session_token: Optional[str] = field( + session_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SessionToken"}, ) - activity_id: Optional[str] = field( + activity_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ActivityId"}, ) @@ -303,9 +437,17 @@ class GetAccountResponse: Definition: getAccountResponse """ - self: Optional[str] = field(default=None, metadata={"wire_name": "_self"}) - rid: Optional[str] = field(default=None, metadata={"wire_name": "_rid"}) - id: Optional[str] = None + self: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_self"}, + ) + rid: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_rid"}, + ) + id: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -314,19 +456,37 @@ class GetDatabaseResponse: Definition: getDatabaseResponse """ - id: Optional[str] = None - rid: Optional[str] = field(default=None, metadata={"wire_name": "_rid"}) - self: Optional[str] = field(default=None, metadata={"wire_name": "_self"}) - etag: Optional[str] = field(default=None, metadata={"wire_name": "_etag"}) - colls: Optional[str] = field( + id: Optional[str] = dataclass_field(default=None, kw_only=True) + rid: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_rid"}, + ) + self: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_self"}, + ) + etag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_etag"}, + ) + colls: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_colls"}, ) - users: Optional[str] = field( + users: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_users"}, ) - ts: Optional[int] = field(default=None, metadata={"wire_name": "_ts"}) + ts: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_ts"}, + ) GetCollectionResponse = List[Dict[str, Any]] @@ -338,7 +498,7 @@ class PostDocumentsRequest: Definition: postDocumentsRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -351,7 +511,7 @@ class PutDocumentRequest: Definition: putDocumentRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -364,7 +524,7 @@ class QueryRequest: Definition: queryRequest """ - query: Optional[str] = None + query: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -373,13 +533,19 @@ class QueryResponse: Definition: queryResponse """ - rid: Optional[str] = field(default=None, metadata={"wire_name": "_rid"}) - count: Optional[float] = field( + rid: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "_rid"}, + ) + count: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_count"}, ) - documents: Optional[List[Any]] = field( + documents: Optional[List[Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Documents"}, ) @@ -390,10 +556,13 @@ class DataWithSensitivityLabelInfo: Definition: DataWithSensitivityLabelInfo """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name""" - sensitivity_label_info: Optional[List[SensitivityLabelMetadata]] = field( + sensitivity_label_info: Optional[ + List[SensitivityLabelMetadata | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelInfo"}, ) """List of Sensitivity Label Information""" @@ -405,41 +574,47 @@ class SensitivityLabelMetadata: Definition: SensitivityLabelMetadata """ - sensitivity_label_id: Optional[str] = field( + sensitivity_label_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelId"}, ) """SensitivityLabel Id.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel name.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """SensitivityLabel displayName info""" - tooltip: Optional[str] = None + tooltip: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel details on tooltip.""" - priority: Optional[int] = None + priority: Optional[int] = dataclass_field(default=None, kw_only=True) """SensitivityLabel priority.""" - color: Optional[str] = None + color: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel color.""" - is_encrypted: Optional[bool] = field( + is_encrypted: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEncrypted"}, ) """ is SensitivityLabel Encrypted.""" - is_enabled: Optional[bool] = field( + is_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEnabled"}, ) """Whether SensitivityLabel is Enabled.""" - is_parent: Optional[bool] = field( + is_parent: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isParent"}, ) """Whether SensitivityLabel is Parent.""" - parent_sensitivity_label_id: Optional[str] = field( + parent_sensitivity_label_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentSensitivityLabelId"}, ) """Parent SensitivityLabel Id.""" @@ -451,10 +626,15 @@ class CosmosDbAccount: Definition: CosmosDbAccount """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the Azure Cosmos DB account.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the Azure Cosmos DB account.""" @@ -468,16 +648,16 @@ class DocumentdbClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -488,8 +668,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -497,8 +677,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -510,7 +690,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -532,7 +712,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -564,9 +744,9 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def create_document_async( + def create_document( self, - input: PostDocumentsRequest, + input: PostDocumentsRequest | Mapping[str, Any], cosmos_db_account_name: str, database_id: str, collection_id: str, @@ -581,6 +761,26 @@ async def create_document_async( Create or update document. When creating a document in DocumentDB, the body must include an id property. + + Swagger operation ID: `CreateDocument_V3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -594,7 +794,7 @@ async def create_document_async( f"/docs" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -608,6 +808,7 @@ async def create_document_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -615,9 +816,9 @@ async def create_document_async( return json.loads(response.text) - async def create_stored_procedure_async( + def create_stored_procedure( self, - input: CreateStoredProcedureInput, + input: CreateStoredProcedureInput | Mapping[str, Any], cosmos_db_account_name: str, database_id: str, collection_id: str, @@ -631,6 +832,26 @@ async def create_stored_procedure_async( Create stored procedure Create stored procedure. + + Swagger operation ID: `CreateStoredProcedure_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -644,7 +865,7 @@ async def create_stored_procedure_async( f"/sprocs" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -658,6 +879,7 @@ async def create_stored_procedure_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -665,7 +887,7 @@ async def create_stored_procedure_async( return json.loads(response.text) - async def delete_document_async( + def delete_document( self, cosmos_db_account_name: str, database_id: str, @@ -681,6 +903,25 @@ async def delete_document_async( Delete a document Delete a document. + + Swagger operation ID: `DeleteDocument_V2`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + document_id: The identifier of the document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -695,7 +936,7 @@ async def delete_document_async( f"/{quote(str(document_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -709,9 +950,10 @@ async def delete_document_async( request_url, response.status, response.text, + response=response, ) - async def delete_stored_procedure_async( + def delete_stored_procedure( self, cosmos_db_account_name: str, database_id: str, @@ -727,6 +969,25 @@ async def delete_stored_procedure_async( Delete stored procedure Delete stored procedure. + + Swagger operation ID: `DeleteStoredProcedure_V2`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + sproc_id: The name of the stored procedure. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -741,7 +1002,7 @@ async def delete_stored_procedure_async( f"/{quote(str(sproc_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -755,6 +1016,7 @@ async def delete_stored_procedure_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -762,7 +1024,7 @@ async def delete_stored_procedure_async( return json.loads(response.text) - async def execute_stored_procedure_async( + def execute_stored_procedure( self, input: ExecuteStoredProcedureInput, cosmos_db_account_name: str, @@ -779,6 +1041,26 @@ async def execute_stored_procedure_async( Execute stored procedure Execute stored procedure in specified collection. + + Swagger operation ID: `ExecuteStoredProcedure_V2`. + + Args: + input: The request body. + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + sproc_id: The name of the stored procedure. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -793,7 +1075,7 @@ async def execute_stored_procedure_async( f"/{quote(str(sproc_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -807,6 +1089,7 @@ async def execute_stored_procedure_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -814,24 +1097,50 @@ async def execute_stored_procedure_async( return json.loads(response.text) - async def get_document_async( + def list_document( self, cosmos_db_account_name: str, database_id: str, collection_id: str, document_id: str, + *, extract_sensitivity_label: Optional[bool] = None, purview_account_name: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get a document Get a document. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetDocument_V2`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + document_id: The identifier for the document. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -858,45 +1167,91 @@ async def get_document_async( query_params.append(f"purviewAccountName={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("@metadata", []): + yield item - async def get_documents_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_documents( self, cosmos_db_account_name: str, database_id: str, collection_id: str, + *, extract_sensitivity_label: Optional[bool] = None, purview_account_name: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get all documents Get all documents. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetDocuments_V3`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -922,29 +1277,50 @@ async def get_documents_async( query_params.append(f"purviewAccountName={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("Documents", []): + yield item + + return None, items() - async def get_stored_procedures_async( + return ItemPaged(get_next, extract_data) + + def get_stored_procedures( self, cosmos_db_account_name: str, database_id: str, @@ -959,6 +1335,24 @@ async def get_stored_procedures_async( Get stored procedures Get stored procedures in the specified collection. + + Swagger operation ID: `GetStoredProcedures_V2`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -972,7 +1366,7 @@ async def get_stored_procedures_async( f"/sprocs" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -986,6 +1380,7 @@ async def get_stored_procedures_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -993,32 +1388,62 @@ async def get_stored_procedures_async( return json.loads(response.text) - async def query_documents_async( + def list_query_documents( self, cosmos_db_account_name: str, database_id: str, container_id: str, + *, query_text: Optional[str] = None, partition_key: Optional[str] = None, max_item_count: Optional[int] = None, - continuation_token: Optional[str] = None, consistency_level: Optional[str] = None, session_token: Optional[str] = None, extract_sensitivity_label: Optional[bool] = None, purview_account_name: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Query documents Query documents. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `QueryDocuments_V5`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + container_id: The name of the container. + query_text: SQL query. If empty, will return all documents. + partition_key: Value must be provided according to its type + (\"string\", 42, 0.5). If empty, all partitions will be used to + search for documents. + max_item_count: An integer indicating the maximum number of items + to be returned per page. + consistency_level: Consistency level required for the feed + (query/read feed) operation. + session_token: The session token for use with session consistency. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1047,11 +1472,6 @@ async def query_documents_async( if isinstance(max_item_count, bool): value = value.lower() query_params.append(f"maxItemCount={quote(value, safe='')}") - if continuation_token is not None: - value = str(continuation_token) - if isinstance(continuation_token, bool): - value = value.lower() - query_params.append(f"continuationToken={quote(value, safe='')}") if consistency_level is not None: value = str(consistency_level) if isinstance(consistency_level, bool): @@ -1074,11 +1494,18 @@ async def query_documents_async( query_params.append(f"purviewAccountName={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1091,25 +1518,34 @@ async def query_documents_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def replace_document_async( + return ItemPaged(get_next, extract_data) + + def replace_document( self, - input: PutDocumentRequest, + input: PutDocumentRequest | Mapping[str, Any], cosmos_db_account_name: str, database_id: str, collection_id: str, @@ -1124,6 +1560,27 @@ async def replace_document_async( Replace a document Replace a document. + + Swagger operation ID: `ReplaceDocument_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + document_id: The identifier of the document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1138,7 +1595,7 @@ async def replace_document_async( f"/{quote(str(document_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1152,6 +1609,7 @@ async def replace_document_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1159,9 +1617,9 @@ async def replace_document_async( return json.loads(response.text) - async def replace_stored_procedure_async( + def replace_stored_procedure( self, - input: ReplaceStoredProcedureInput, + input: ReplaceStoredProcedureInput | Mapping[str, Any], cosmos_db_account_name: str, database_id: str, collection_id: str, @@ -1176,6 +1634,27 @@ async def replace_stored_procedure_async( Replace stored procedure Replace stored procedure. + + Swagger operation ID: `ReplaceStoredProcedure_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + collection_id: The name of the collection. + sproc_id: The name of the stored procedure. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1190,7 +1669,7 @@ async def replace_stored_procedure_async( f"/{quote(str(sproc_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1204,6 +1683,7 @@ async def replace_stored_procedure_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1211,43 +1691,82 @@ async def replace_stored_procedure_async( return json.loads(response.text) - async def get_cosmos_db_accounts_async( + def list_cosmos_db_accounts( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Cosmos DB accounts This operation list the user's Azure Cosmos DB accounts. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetCosmosDbAccounts`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/cosmosdbaccounts" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_databases_async( + def get_databases( self, cosmos_db_account_name: str, *, @@ -1260,13 +1779,29 @@ async def get_databases_async( Get all databases Get all databases. + + Swagger operation ID: `GetDatabases_V2`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v2/cosmosdb/{quote(str(cosmos_db_account_name), safe='')}/dbs" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1280,6 +1815,7 @@ async def get_databases_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1287,7 +1823,7 @@ async def get_databases_async( return json.loads(response.text) - async def get_collections_async( + def get_collections( self, cosmos_db_account_name: str, database_id: str, @@ -1301,6 +1837,23 @@ async def get_collections_async( Get all collections Get all collections. + + Swagger operation ID: `GetCollections_V2`. + + Args: + cosmos_db_account_name: The Azure Cosmos DB account name (without + documents.azure.com). + database_id: The name of the database. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1312,7 +1865,7 @@ async def get_collections_async( f"/colls" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1326,6 +1879,7 @@ async def get_collections_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/docusign.py b/src/azure/connectors/docusign.py index fad0f06..d3cbd10 100644 --- a/src/azure/connectors/docusign.py +++ b/src/azure/connectors/docusign.py @@ -5,21 +5,142 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "DocusignClient", + "AccountCustomFields", + "Activity", + "ActivityListResponseEnvelope", + "AddDocumentsResponse", + "AddDocumentsToEnvelopeInput", + "AddRecipientTabsResponse", + "AddRecipientToEnvelopeRequest", + "AddRemindersResponse", + "AddVerificationToRecipientResponse", + "AdditionalRecipientData", + "AdditionalRecipientParamsSchema", + "AdditionalURL", + "AdditionalURLForSenderView", + "AnchorTabSchema", + "ApiError", + "ApplyTemplatesToDocumentsInput", + "AuditResponse", + "BuildNumberResponse", + "BuildNumberSchema", + "BulkSendListGuid", + "CombinedEmailBodyAndCustomFields", + "CompositeTemplateSchema", + "CompositeTemplatesResponse", + "CreateBulkSendListInput", + "CreateEnvelopeResponse", + "CreateHookEnvelopeInput", + "CreateHookEnvelopeResponse", + "CreateOrgHookEnvelopeInput", + "CreateOrgHookEnvelopeResponse", + "DeclineReasonWithoutType", + "DocGenFormField", + "DocGenFormFieldsResponse", + "DocumentRecord", + "DocumentRecordListResponseEnvelope", + "DocumentType", + "DocumentTypesResponse", + "DynamicRecipients", + "DynamicSigners", + "DynamicSigningUrlFields", + "EmailSummary", + "EmailSummaryResponse", + "EmbeddedSenderResponse", + "EmbeddedSigningResponse", + "Envelope", + "EnvelopeCustomFieldResponse", + "EnvelopeDocument", + "EnvelopeDocumentField", + "EnvelopeIDsResponse", + "EnvelopeIds", + "EnvelopeResendResponse", + "EnvelopeTemplate", + "EnvelopeVoidResponse", + "FilteredEnvelopeListResponse", + "FilteredEnvelopes", + "FilteredSalesCopilotEnvelopeListResponse", + "Folder", + "FolderItem", + "FontName", + "FontNamesResponse", + "GetDocGenTemplateTabsResponse", + "GetDocumentsResponse", + "GetDynamicRecipientsResponse", + "GetDynamicSignersResponse", + "GetLoginAccountsResponse", + "GetOrganizationsResponse", + "GetWorkFlowIdsResponse", + "KeySales", + "KeySalesResponse", + "ListDocumentsResponse", + "ListEnvelopeDocumentFieldsResponse", + "ListEnvelopesResponse", + "ListFoldersResponse", + "ListRecipientsResponse", + "ListSigningGroupResponse", + "ListTabsResponse", + "ListTemplateDocumentsResponse", + "ListTemplatesResponse", + "LoginAccount", + "MaestroInputVariables", + "OnEnvelopeStatusChangesResponse", + "Organization", + "RecipientTab", + "RecipientTabsResponse", + "RecipientType", + "RecipientTypesResponse", + "SalesCopilotFilteredEnvelopes", + "SendDraftEnvelopeResponse", + "SignatureType", + "SignatureTypesResponse", + "Signer", + "SignerRequest", + "SigningGroup", + "StaticResponseForAnchorTabSchemaResponse", + "StaticResponseForBuildNumberSchemaResponse", + "StaticResponseForCompositeTemplatesResponse", + "StaticResponseForEmbeddedSenderSchemaResponse", + "StaticResponseForEmbeddedSigningSchemaResponse", + "StaticResponseForRecipientTypeSchemaResponse", + "StaticResponseForVerificationTypeSchemaResponse", + "Tab", + "TabType", + "TabTypesResponse", + "TriggerMaestroFlowResponse", + "UpdateDocgenFormFieldsInput", + "UpdateEnvelopeCustomFieldResponse", + "UpdateEnvelopePrefillTabsInput", + "UpdateRecipientTabsValuesInput", + "WebhookEnvelopeResponse", + "WebhookOrganizationResponse", + "WebhookRequest", + "WorkflowDefPayloadSchema", + "WorkflowDefinition", + "WorkflowDefinitionResponse", + "WorkflowDefinitionsResponse", + "WorkflowId", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,29 +150,22 @@ class CreateOrgHookEnvelopeInput: When a Docusign Connect event occurs (Organization-level) """ - all_users: Optional[str] = field( - default=None, - metadata={"wire_name": "allUsers"}, - ) - allow_envelope_publish: Optional[str] = field( - default=None, + all_users: str = dataclass_field(metadata={"wire_name": "allUsers"}) + allow_envelope_publish: str = dataclass_field( metadata={"wire_name": "allowEnvelopePublish"}, ) - include_document_fields: Optional[str] = field( - default=None, + include_document_fields: str = dataclass_field( metadata={"wire_name": "includeDocumentFields"}, ) - requires_acknowledgement: Optional[str] = field( - default=None, + requires_acknowledgement: str = dataclass_field( metadata={"wire_name": "requiresAcknowledgement"}, ) - url_to_publish_to: Optional[str] = field( - default=None, + url_to_publish_to: str = dataclass_field( metadata={"wire_name": "urlToPublishTo"}, ) - name: Optional[str] = None + name: str """Name your Connect configuration (for example, \"Envelope Events\").""" - events: Optional[List[str]] = None + events: List[str] """Select an event. To include another event, select \"Add new item.\"""" @@ -61,7 +175,7 @@ class CreateOrgHookEnvelopeResponse: Response for When a Docusign Connect event occurs (Organization-level) """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -74,8 +188,9 @@ class DocGenFormFieldsResponse: Response for Get document generation form fields from envelope """ - docgen_fields: Optional[List[DocGenFormField]] = field( + docgen_fields: Optional[List[DocGenFormField | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "docgenFields"}, ) """Docgen Fields""" @@ -90,7 +205,7 @@ class GetDocGenTemplateTabsResponse: Response for Get document generation form fields from template (bulk send templates only) """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -103,7 +218,7 @@ class EnvelopeVoidResponse: Response for Void the envelope """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -116,7 +231,7 @@ class EnvelopeResendResponse: Response for Resend the envelope """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -129,8 +244,9 @@ class AddRemindersResponse: Response for Add reminders for an envelope """ - reminder_enabled: Optional[str] = field( + reminder_enabled: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reminderEnabled"}, ) """Reminder enabled""" @@ -142,7 +258,12 @@ class ListTabsResponse: Response for Get document tabs from envelope """ - tabs: Optional[List[Tab]] = None + tabs: Optional[ + List[Tab | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Tabs""" @@ -155,8 +276,11 @@ class ListEnvelopeDocumentFieldsResponse: Response for Get document custom fields from envelope """ - envelope_document_fields: Optional[List[EnvelopeDocumentField]] = field( + envelope_document_fields: Optional[ + List[EnvelopeDocumentField | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "envelopeDocumentFields"}, ) """Document Custom Fields""" @@ -168,19 +292,21 @@ class CompositeTemplatesResponse: Response for Create envelope using composite templates """ - envelope_id: Optional[str] = field( + envelope_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "envelopeId"}, ) """The id of the envelope.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status of the envelope.""" - status_date_time: Optional[str] = field( + status_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "statusDateTime"}, ) """The datetime the status was set.""" - uri: Optional[str] = None + uri: Optional[str] = dataclass_field(default=None, kw_only=True) """The URI for the envelope in DocuSign.""" @@ -190,10 +316,16 @@ class FilteredEnvelopeListResponse: Response for List envelopes """ - value: Optional[List[FilteredEnvelopes]] = None + value: Optional[ + List[FilteredEnvelopes | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Filtered envelopes""" - has_more_results: Optional[bool] = field( + has_more_results: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasMoreResults"}, ) """ @@ -208,24 +340,27 @@ class CreateEnvelopeResponse: Response for Create envelope using template """ - envelope_id: Optional[str] = field( + envelope_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "envelopeId"}, ) """The id of the envelope.""" - template_id: Optional[str] = field( + template_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "templateId"}, ) """The id of the template.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status of the envelope.""" - status_date_time: Optional[str] = field( + status_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "statusDateTime"}, ) """The datetime the status was set.""" - uri: Optional[str] = None + uri: Optional[str] = dataclass_field(default=None, kw_only=True) """The URI for the envelope in DocuSign.""" @@ -235,7 +370,7 @@ class SendDraftEnvelopeResponse: Response for Send envelope """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -248,19 +383,21 @@ class EnvelopeCustomFieldResponse: Response for Get envelope custom field info """ - field_id: Optional[str] = field( + field_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fieldId"}, ) """The id of the envelope custom field.""" - field_type: Optional[str] = field( + field_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fieldType"}, ) """The type of the envelope custom field.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the envelope custom field.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """The value of the envelope custom field.""" @@ -270,19 +407,21 @@ class UpdateEnvelopeCustomFieldResponse: Response for Update envelope custom field """ - field_id: Optional[str] = field( + field_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fieldId"}, ) """The id of the envelope custom field.""" - field_type: Optional[str] = field( + field_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fieldType"}, ) """The type of the envelope custom field.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the envelope custom field.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """The value of the envelope custom field.""" @@ -292,7 +431,7 @@ class EmbeddedSenderResponse: Response for Generate Embedded Sender URL """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The url of embedded sender view.""" @@ -302,11 +441,17 @@ class ListRecipientsResponse: Response for List recipients from an envelope """ - envelope_id: Optional[str] = field( + envelope_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "envelopeId"}, ) - signers: Optional[List[Signer]] = None + signers: Optional[ + List[Signer | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Signers""" @@ -316,37 +461,43 @@ class Signer: Response for Get recipient info from envelope """ - routing_order: Optional[str] = field( + routing_order: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "routingOrder"}, ) """The signing order of the recipient in the document.""" - role_name: Optional[str] = field( + role_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "roleName"}, ) """The role of the signer.""" - recipient_id: Optional[str] = field( + recipient_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientId"}, ) """The id the recipient.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the recipient.""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """The email of the recipient.""" - recipient_type: Optional[str] = field( + recipient_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientType"}, ) """The type the recipient.""" - verification_type: Optional[str] = field( + verification_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "verificationType"}, ) """The type of verification.""" - recipient_id_guid: Optional[str] = field( + recipient_id_guid: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientIdGuid"}, ) """The recipient GUID.""" @@ -358,7 +509,7 @@ class AuditResponse: Response for Get audit event list """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -371,7 +522,7 @@ class AddVerificationToRecipientResponse: Response for Add verification type to a recipient """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -384,8 +535,9 @@ class ApplyTemplatesToDocumentsInput: Apply a template to documents """ - document_templates: Optional[List[Dict[str, Any]]] = field( + document_templates: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "documentTemplates"}, ) """Document Templates""" @@ -397,10 +549,11 @@ class CreateBulkSendListInput: Create bulk send list """ - csv: Optional[str] = None + csv: Optional[str] = dataclass_field(default=None, kw_only=True) """Upload CSV File""" - raw_output: Optional[Dict[str, Any]] = field( + raw_output: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "rawOutput"}, ) """Document generation fields""" @@ -412,8 +565,9 @@ class BulkSendListGuid: Response for Create bulk send list """ - list_id: Optional[str] = field( + list_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "listId"}, ) """Bulk send list guid""" @@ -425,8 +579,9 @@ class GetLoginAccountsResponse: Response for Login """ - login_accounts: Optional[List[LoginAccount]] = field( + login_accounts: Optional[List[LoginAccount | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "loginAccounts"}, ) """Login accounts""" @@ -438,8 +593,11 @@ class ListTemplatesResponse: Response for List templates """ - envelope_templates: Optional[List[EnvelopeTemplate]] = field( + envelope_templates: Optional[ + List[EnvelopeTemplate | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "envelopeTemplates"}, ) """The available envelope templates.""" @@ -451,7 +609,7 @@ class AddDocumentsToEnvelopeInput: Add documents to an envelope """ - documents: Optional[List[Dict[str, Any]]] = None + documents: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -460,13 +618,17 @@ class AddDocumentsResponse: Response for Add documents to an envelope """ - envelope_id: Optional[str] = field( + envelope_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "envelopeId"}, ) """The id of the envelope.""" - envelope_documents: Optional[List[EnvelopeDocument]] = field( + envelope_documents: Optional[ + List[EnvelopeDocument | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "envelopeDocuments"}, ) """The documents attached to the envelope.""" @@ -478,8 +640,11 @@ class ListTemplateDocumentsResponse: Response for List documents from a template """ - template_documents: Optional[List[EnvelopeDocument]] = field( + template_documents: Optional[ + List[EnvelopeDocument | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "templateDocuments"}, ) """Documents attached to a template.""" @@ -491,8 +656,11 @@ class ListDocumentsResponse: Response for List documents from an envelope """ - envelope_documents: Optional[List[EnvelopeDocument]] = field( + envelope_documents: Optional[ + List[EnvelopeDocument | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "envelopeDocuments"}, ) """The documents attached to the envelope.""" @@ -504,20 +672,23 @@ class EnvelopeDocument: Response for Get document info from envelope """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the document.""" - document_id: Optional[str] = field( + document_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "documentId"}, ) """The id of the document.""" - document_id_guid: Optional[str] = field( + document_id_guid: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "documentIdGuid"}, ) """The guid of the document.""" - error_details: Optional[Dict[str, Any]] = field( + error_details: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "errorDetails"}, ) """The error details of the document.""" @@ -529,38 +700,43 @@ class Tab: Response for Get info for recipient tab """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the tab.""" - tab_type: Optional[str] = field( + tab_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tabType"}, ) """The type of the tab.""" - tab_label: Optional[str] = field( + tab_label: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tabLabel"}, ) """The label of the tab.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """The value of the tab.""" - tab_id: Optional[str] = field( + tab_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tabId"}, ) """The id of the tab.""" - document_id: Optional[str] = field( + document_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "documentId"}, ) """The id of the document.""" - recipient_id: Optional[str] = field( + recipient_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientId"}, ) """The id of the recipient.""" - prefill: Optional[bool] = None + prefill: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether the tab is of prefill type.""" - selected: Optional[str] = None + selected: Optional[str] = dataclass_field(default=None, kw_only=True) """If tabs is checkbox, indicates whether the tab is selected.""" @@ -570,8 +746,9 @@ class AddRecipientTabsResponse: Response for Add tabs for a recipient on an envelope """ - recipient_tabs: Optional[List[RecipientTab]] = field( + recipient_tabs: Optional[List[RecipientTab | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientTabs"}, ) """The tabs added to a recipient.""" @@ -586,8 +763,9 @@ class RecipientTabsResponse: Response for Get recipient tabs from envelope """ - recipient_tabs: Optional[List[Tab]] = field( + recipient_tabs: Optional[List[Tab | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientTabs"}, ) """Recipient tab""" @@ -599,7 +777,7 @@ class TriggerMaestroFlowResponse: Response for Start Docusign workflow """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -612,7 +790,7 @@ class BuildNumberResponse: Response for Show build Number (For reference only. Do not include in a flow for execution) """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -625,29 +803,22 @@ class CreateHookEnvelopeInput: When a Docusign Connect event occurs (Account-level) """ - all_users: Optional[str] = field( - default=None, - metadata={"wire_name": "allUsers"}, - ) - allow_envelope_publish: Optional[str] = field( - default=None, + all_users: str = dataclass_field(metadata={"wire_name": "allUsers"}) + allow_envelope_publish: str = dataclass_field( metadata={"wire_name": "allowEnvelopePublish"}, ) - include_document_fields: Optional[str] = field( - default=None, + include_document_fields: str = dataclass_field( metadata={"wire_name": "includeDocumentFields"}, ) - requires_acknowledgement: Optional[str] = field( - default=None, + requires_acknowledgement: str = dataclass_field( metadata={"wire_name": "requiresAcknowledgement"}, ) - url_to_publish_to: Optional[str] = field( - default=None, + url_to_publish_to: str = dataclass_field( metadata={"wire_name": "urlToPublishTo"}, ) - name: Optional[str] = None + name: str """Name your Connect configuration (for example, \"Envelope Events\").""" - events: Optional[List[str]] = None + events: List[str] """Select an event. To include another event, select \"Add new item.\"""" @@ -657,7 +828,7 @@ class CreateHookEnvelopeResponse: Response for When a Docusign Connect event occurs (Account-level) """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -670,7 +841,7 @@ class EmbeddedSigningResponse: Response for Generate Embedded Signing URL """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The url of embedded signing view.""" @@ -683,7 +854,12 @@ class GetOrganizationsResponse: Response for Get organizations """ - organizations: Optional[List[Organization]] = None + organizations: Optional[ + List[Organization | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """list of organizations""" @@ -693,7 +869,12 @@ class ListFoldersResponse: Response for List folders """ - folders: Optional[List[Folder]] = None + folders: Optional[ + List[Folder | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Folders""" @@ -703,8 +884,9 @@ class ListEnvelopesResponse: Response for List envelopes """ - folder_items: Optional[List[FolderItem]] = field( + folder_items: Optional[List[FolderItem | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "folderItems"}, ) """The envelopes within a folder.""" @@ -716,8 +898,9 @@ class RecipientTypesResponse: Response for StaticResponseForRecipientTypes """ - tab_types: Optional[List[RecipientType]] = field( + tab_types: Optional[List[RecipientType | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tabTypes"}, ) """Recipient types""" @@ -729,8 +912,9 @@ class SignatureTypesResponse: Response for StaticResponseForSignatureTypes """ - tab_types: Optional[List[SignatureType]] = field( + tab_types: Optional[List[SignatureType | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tabTypes"}, ) """Signature types""" @@ -742,8 +926,9 @@ class ListSigningGroupResponse: Response for GetSigningGroups """ - signing_groups: Optional[List[SigningGroup]] = field( + signing_groups: Optional[List[SigningGroup | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "signingGroups"}, ) """List of all signing groups""" @@ -755,8 +940,9 @@ class TabTypesResponse: Response for StaticResponseForTabTypes """ - tab_types: Optional[List[TabType]] = field( + tab_types: Optional[List[TabType | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tabTypes"}, ) """Tab types""" @@ -768,8 +954,11 @@ class WorkflowDefinitionsResponse: Response for Get Maestro Workflow Definitions """ - workflow_definitions: Optional[List[WorkflowDefinition]] = field( + workflow_definitions: Optional[ + List[WorkflowDefinition | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WorkflowDefinitions"}, ) """WorkflowDefinitions""" @@ -781,8 +970,9 @@ class GetWorkFlowIdsResponse: Response for Get All Workflow Ids """ - workflow_ids: Optional[List[WorkflowId]] = field( + workflow_ids: Optional[List[WorkflowId | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "workflowIds"}, ) """Workflow ID""" @@ -794,12 +984,23 @@ class WorkflowDefinitionResponse: Response for Get Maestro Workflow Definition """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Id""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Name""" - payload_schema: Optional[List[WorkflowDefPayloadSchema]] = field( + payload_schema: Optional[ + List[WorkflowDefPayloadSchema | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PayloadSchema"}, ) @@ -810,7 +1011,7 @@ class GetDynamicSignersResponse: Response for Get the signers of a template in dynamic schema format """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -823,7 +1024,7 @@ class GetDynamicRecipientsResponse: Response for Get the signers of a template in dynamic schema format """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -836,7 +1037,7 @@ class StaticResponseForRecipientTypeSchemaResponse: Response for StaticResponseForRecipientTypeSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -849,7 +1050,7 @@ class StaticResponseForVerificationTypeSchemaResponse: Response for StaticResponseForVerificationTypeSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -862,7 +1063,7 @@ class StaticResponseForEmbeddedSenderSchemaResponse: Response for StaticResponseForEmbeddedSenderSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -875,7 +1076,7 @@ class StaticResponseForEmbeddedSigningSchemaResponse: Response for StaticResponseForEmbeddedSigningSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -888,7 +1089,7 @@ class StaticResponseForBuildNumberSchemaResponse: Response for StaticResponseForBuildNumberSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -901,7 +1102,7 @@ class StaticResponseForAnchorTabSchemaResponse: Response for StaticResponseForAnchorTabSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -914,7 +1115,7 @@ class StaticResponseForCompositeTemplatesResponse: Response for StaticResponseForCompositeTemplates """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -927,29 +1128,21 @@ class WebhookRequest: Definition: WebhookRequest """ - all_users: Optional[str] = field( - default=None, - metadata={"wire_name": "allUsers"}, - ) - allow_envelope_publish: Optional[str] = field( - default=None, + all_users: str = dataclass_field(metadata={"wire_name": "allUsers"}) + allow_envelope_publish: str = dataclass_field( metadata={"wire_name": "allowEnvelopePublish"}, ) - include_document_fields: Optional[str] = field( - default=None, + include_document_fields: str = dataclass_field( metadata={"wire_name": "includeDocumentFields"}, ) - requires_acknowledgement: Optional[str] = field( - default=None, + requires_acknowledgement: str = dataclass_field( metadata={"wire_name": "requiresAcknowledgement"}, ) - url_to_publish_to: Optional[str] = field( - default=None, + url_to_publish_to: str = dataclass_field( metadata={"wire_name": "urlToPublishTo"}, ) - name: Optional[str] = None - envelope_events: Optional[str] = field( - default=None, + name: str + envelope_events: str = dataclass_field( metadata={"wire_name": "envelopeEvents"}, ) @@ -960,7 +1153,7 @@ class WebhookEnvelopeResponse: Definition: WebhookEnvelopeResponse """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -969,7 +1162,7 @@ class WebhookOrganizationResponse: Definition: WebhookOrganizationResponse """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -978,9 +1171,17 @@ class WorkflowDefinition: Definition: WorkflowDefinition """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Id""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Name""" @@ -990,12 +1191,17 @@ class WorkflowDefPayloadSchema: Definition: WorkflowDefPayloadSchema """ - property_name: Optional[str] = field( + property_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PropertyName"}, ) """Name""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Type"}, + ) """Type""" @@ -1005,7 +1211,7 @@ class MaestroInputVariables: Definition: MaestroInputVariables """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1018,7 +1224,7 @@ class DynamicSigners: Definition: DynamicSigners """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1031,7 +1237,7 @@ class DynamicRecipients: Definition: DynamicRecipients """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1044,7 +1250,7 @@ class AdditionalRecipientParamsSchema: Definition: AdditionalRecipientParamsSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1057,7 +1263,7 @@ class AdditionalRecipientData: Definition: AdditionalRecipientData """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1070,7 +1276,7 @@ class AdditionalURLForSenderView: Definition: AdditionalURLForSenderView """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1083,7 +1289,7 @@ class AdditionalURL: Definition: AdditionalURL """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1096,7 +1302,7 @@ class DynamicSigningUrlFields: Definition: DynamicSigningUrlFields """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1109,7 +1315,7 @@ class BuildNumberSchema: Definition: BuildNumberSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1122,7 +1328,7 @@ class AccountCustomFields: Definition: AccountCustomFields """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1135,7 +1341,7 @@ class AnchorTabSchema: Definition: AnchorTabSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1148,7 +1354,7 @@ class CompositeTemplateSchema: Definition: CompositeTemplateSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1161,7 +1367,12 @@ class AddRecipientToEnvelopeRequest: Definition: AddRecipientToEnvelopeRequest """ - signers: Optional[List[SignerRequest]] = None + signers: Optional[ + List[SignerRequest | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1170,13 +1381,15 @@ class SignerRequest: Definition: SignerRequest """ - routing_order: Optional[str] = field( + routing_order: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "routingOrder"}, ) """The signing order of the recipient in the document.""" - role_name: Optional[str] = field( + role_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "roleName"}, ) """The role of the signer.""" @@ -1188,7 +1401,12 @@ class OnEnvelopeStatusChangesResponse: Definition: OnEnvelopeStatusChangesResponse """ - envelopes: Optional[List[Envelope]] = None + envelopes: Optional[ + List[Envelope | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Envelopes""" @@ -1198,13 +1416,15 @@ class EnvelopeIds: Definition: EnvelopeIds """ - email_subject: Optional[str] = field( + email_subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "emailSubject"}, ) """Title of the envelope""" - envelope_id: Optional[str] = field( + envelope_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "envelopeId"}, ) """Envelope ID""" @@ -1216,34 +1436,37 @@ class FilteredEnvelopes: Definition: FilteredEnvelopes """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of the envelope""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the envelope activity""" - envelope_id: Optional[str] = field( + envelope_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "envelopeId"}, ) """Envelope ID""" - documents: Optional[str] = None + documents: Optional[str] = dataclass_field(default=None, kw_only=True) """List of document names""" - recipients: Optional[str] = None + recipients: Optional[str] = dataclass_field(default=None, kw_only=True) """List of recipient names""" - sender: Optional[str] = None + sender: Optional[str] = dataclass_field(default=None, kw_only=True) """Sender name""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status of the envelope""" - status_date: Optional[str] = field( + status_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "statusDate"}, ) """Last status update of the activity""" - date_sent: Optional[str] = field( + date_sent: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dateSent"}, ) """Envelope sent date""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """URL of the envelope""" @@ -1253,17 +1476,19 @@ class SalesCopilotFilteredEnvelopes: Definition: SalesCopilotFilteredEnvelopes """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of the envelope""" - sub_title: Optional[str] = field( + sub_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "subTitle"}, ) """SubTitle of the envelope""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """URL of the envelope""" - additional_properties_for_sales_envelope: Optional[Dict[str, Any]] = field( + additional_properties_for_sales_envelope: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "additionalPropertiesForSalesEnvelope"}, ) """Additional Properties""" @@ -1275,19 +1500,17 @@ class Activity: Definition: Activity """ - title: Optional[str] = None + title: str """This output indicates the title of the activity in the citation card.""" - description: Optional[str] = None + description: str """This output indicates the description of the insight.""" - date_time: Optional[str] = field( - default=None, - metadata={"wire_name": "dateTime"}, - ) + date_time: str = dataclass_field(metadata={"wire_name": "dateTime"}) """This output indicates the time associated with the insight.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """This output indicates the URL to open insight.""" - additional_properties: Optional[Dict[str, Any]] = field( + additional_properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "additionalProperties"}, ) """ @@ -1302,15 +1525,12 @@ class EmailSummary: Definition: EmailSummary """ - title: Optional[str] = field(default=None, metadata={"wire_name": "Title"}) + title: str = dataclass_field(metadata={"wire_name": "Title"}) """ This output indicates the title of the partner section and should include only the partner's name. """ - description: Optional[str] = field( - default=None, - metadata={"wire_name": "Description"}, - ) + description: str = dataclass_field(metadata={"wire_name": "Description"}) """ This output indicates the text you would like to be included in the email summary. @@ -1323,22 +1543,24 @@ class KeySales: Definition: KeySales """ - title: Optional[str] = field(default=None, metadata={"wire_name": "Title"}) + title: str = dataclass_field(metadata={"wire_name": "Title"}) """This output indicates the title of citation card for the insight.""" - description: Optional[str] = None + description: str """ This output indicates the text of the insight to be included in key sales info. """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """This output indicates the URL to learn more about the insight.""" - date_time: Optional[str] = field( + date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dateTime"}, ) """This output indicates the time associated with the insight.""" - additional_properties: Optional[Dict[str, Any]] = field( + additional_properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "additionalProperties"}, ) """ @@ -1353,52 +1575,42 @@ class DocumentRecord: Definition: DocumentRecord """ - record_id: Optional[str] = field( - default=None, - metadata={"wire_name": "recordId"}, - ) + record_id: str = dataclass_field(metadata={"wire_name": "recordId"}) """ This output uniquely identifies each related record returned by the action. """ - record_type_display_name: Optional[str] = field( - default=None, + record_type_display_name: str = dataclass_field( metadata={"wire_name": "recordTypeDisplayName"}, ) """ This output indicates the display name of record type of each related record returned by the action. """ - record_type_plural_display_name: Optional[str] = field( - default=None, + record_type_plural_display_name: str = dataclass_field( metadata={"wire_name": "recordTypePluralDisplayName"}, ) """ This output indicates the plural display name of the record type of each related record returned by the action. """ - record_type: Optional[str] = field( - default=None, - metadata={"wire_name": "recordType"}, - ) + record_type: str = dataclass_field(metadata={"wire_name": "recordType"}) """ This output indicates the type of each related record returned by the action. """ - record_title: Optional[str] = field( - default=None, - metadata={"wire_name": "recordTitle"}, - ) + record_title: str = dataclass_field(metadata={"wire_name": "recordTitle"}) """ This output indicates the title of each related record returned by the action. """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """ This output indicates the URL of each related record returned by the action. """ - additional_properties: Optional[Dict[str, Any]] = field( + additional_properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "additionalProperties"}, ) """Additional Properties""" @@ -1410,35 +1622,41 @@ class Envelope: Definition: Envelope """ - documents_uri: Optional[str] = field( + documents_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "documentsUri"}, ) """The URI for the document in DocuSign.""" - envelope_id: Optional[str] = field( + envelope_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "envelopeId"}, ) """The id of the envelope.""" - envelope_uri: Optional[str] = field( + envelope_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "envelopeUri"}, ) """The URI for the envelope in DocuSign.""" - notification_uri: Optional[str] = field( + notification_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notificationUri"}, ) """The URI for the notifications.""" - recipients_uri: Optional[str] = field( + recipients_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientsUri"}, ) """The URI for the recipients of the envelope in DocuSign.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status of the envelope.""" - status_changed_date_time: Optional[str] = field( + status_changed_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "statusChangedDateTime"}, ) """The datetime the status changed.""" @@ -1450,13 +1668,15 @@ class CombinedEmailBodyAndCustomFields: Definition: CombinedEmailBodyAndCustomFields """ - email_blurb: Optional[str] = field( + email_blurb: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "emailBlurb"}, ) """Body of the email.""" - account_custom_fields: Optional[AccountCustomFields] = field( + account_custom_fields: Optional[AccountCustomFields | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountCustomFields"}, ) @@ -1467,7 +1687,12 @@ class EnvelopeIDsResponse: Definition: EnvelopeIDsResponse """ - envelopes: Optional[List[EnvelopeIds]] = None + envelopes: Optional[ + List[EnvelopeIds | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """list of envelope ids""" @@ -1477,10 +1702,16 @@ class FilteredSalesCopilotEnvelopeListResponse: Definition: FilteredSalesCopilotEnvelopeListResponse """ - value: Optional[List[SalesCopilotFilteredEnvelopes]] = None + value: Optional[ + List[SalesCopilotFilteredEnvelopes | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Filtered envelopes""" - has_more_results: Optional[bool] = field( + has_more_results: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasMoreResults"}, ) @@ -1491,10 +1722,16 @@ class ActivityListResponseEnvelope: Definition: ActivityListResponseEnvelope """ - value: Optional[List[Activity]] = None + value: Optional[ + List[Activity | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Related activies""" - has_more_results: Optional[bool] = field( + has_more_results: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasMoreResults"}, ) @@ -1505,10 +1742,16 @@ class EmailSummaryResponse: Definition: EmailSummaryResponse """ - value: Optional[List[EmailSummary]] = None + value: Optional[ + List[EmailSummary | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Key Sales""" - has_more_results: Optional[bool] = field( + has_more_results: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasMoreResults"}, ) @@ -1519,10 +1762,16 @@ class KeySalesResponse: Definition: KeySalesResponse """ - value: Optional[List[KeySales]] = None + value: Optional[ + List[KeySales | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Key Sales""" - has_more_results: Optional[bool] = field( + has_more_results: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasMoreResults"}, ) @@ -1533,10 +1782,16 @@ class DocumentRecordListResponseEnvelope: Definition: DocumentRecordListResponseEnvelope """ - value: Optional[List[DocumentRecord]] = None + value: Optional[ + List[DocumentRecord | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Related records""" - has_more_results: Optional[bool] = field( + has_more_results: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasMoreResults"}, ) @@ -1547,19 +1802,18 @@ class ApiError: Definition: ApiError """ - error_code: Optional[str] = field( - default=None, - metadata={"wire_name": "errorCode"}, - ) - error_message: Optional[str] = field( + error_code: str = dataclass_field(metadata={"wire_name": "errorCode"}) + error_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "errorMessage"}, ) - activity_id: Optional[str] = field( + activity_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "activityId"}, ) - details: Optional[Dict[str, Any]] = None + details: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1568,9 +1822,9 @@ class Organization: Definition: organization """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The id of the organization.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the organization.""" @@ -1580,10 +1834,9 @@ class LoginAccount: Definition: LoginAccount """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the account. """ - account_id_guid: Optional[str] = field( - default=None, + account_id_guid: str = dataclass_field( metadata={"wire_name": "accountIdGuid"}, ) """The GUID of the account.""" @@ -1595,8 +1848,9 @@ class DocumentTypesResponse: Definition: DocumentTypesResponse """ - document_types: Optional[List[DocumentType]] = field( + document_types: Optional[List[DocumentType | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "documentTypes"}, ) """Document types""" @@ -1608,18 +1862,23 @@ class DocGenFormField: Definition: DocGenFormField """ - document_id: Optional[str] = field( + document_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "documentId"}, ) """Document Id.""" - label: Optional[str] = None + label: Optional[str] = dataclass_field(default=None, kw_only=True) """Label.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Value.""" @@ -1629,8 +1888,9 @@ class FontNamesResponse: Definition: FontNamesResponse """ - font_names: Optional[List[FontName]] = field( + font_names: Optional[List[FontName | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fontNames"}, ) """Font names""" @@ -1642,7 +1902,7 @@ class DocumentType: Definition: DocumentType """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The type of a document.""" @@ -1652,9 +1912,13 @@ class TabType: Definition: TabType """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Display name of the tab.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type of the tab.""" @@ -1664,9 +1928,13 @@ class WorkflowId: Definition: WorkflowID """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of workflowID""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type of workflowID""" @@ -1676,9 +1944,13 @@ class RecipientType: Definition: RecipientType """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Display name of the recipient type.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type of the recipient.""" @@ -1688,9 +1960,13 @@ class SignatureType: Definition: SignatureType """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Display name of the signature type.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type of the signature.""" @@ -1700,7 +1976,7 @@ class FontName: Definition: FontName """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of a font metadata.""" @@ -1710,13 +1986,13 @@ class SigningGroup: Definition: SigningGroup """ - signing_group_id: Optional[str] = field( - default=None, + signing_group_id: str = dataclass_field( metadata={"wire_name": "signingGroupId"}, ) """The ID of the signing group.""" - group_name: Optional[str] = field( + group_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "groupName"}, ) """The name of the signing group.""" @@ -1728,12 +2004,9 @@ class EnvelopeTemplate: Definition: EnvelopeTemplate """ - template_id: Optional[str] = field( - default=None, - metadata={"wire_name": "templateId"}, - ) + template_id: str = dataclass_field(metadata={"wire_name": "templateId"}) """The id of the template.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the template.""" @@ -1743,10 +2016,11 @@ class Folder: Definition: Folder """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the folder.""" - folder_id: Optional[str] = field( + folder_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "folderId"}, ) """The id of the folder.""" @@ -1758,12 +2032,13 @@ class FolderItem: Definition: FolderItem """ - envelope_id: Optional[str] = field( + envelope_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "envelopeId"}, ) """The id of the envelope.""" - subject: Optional[str] = None + subject: Optional[str] = dataclass_field(default=None, kw_only=True) """The subject of the envelope.""" @@ -1773,13 +2048,15 @@ class RecipientTab: Definition: RecipientTab """ - tab_id: Optional[str] = field( + tab_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tabId"}, ) """The id of the tab.""" - tab_type: Optional[str] = field( + tab_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tabType"}, ) """The type of the tab.""" @@ -1791,9 +2068,9 @@ class EnvelopeDocumentField: Definition: EnvelopeDocumentField """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the custom field.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """The value of the custom field.""" @@ -1803,7 +2080,7 @@ class DeclineReasonWithoutType: Definition: DeclineReasonWithoutType """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1818,16 +2095,16 @@ class DocusignClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -1838,8 +2115,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -1847,8 +2124,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -1860,7 +2137,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -1875,7 +2152,46 @@ def __init__( def connector_name(self) -> str: return "docusign" - async def get_docgen_form_fields_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_docgen_form_fields( self, account_id: str, envelope_id: str, @@ -1884,11 +2200,31 @@ async def get_docgen_form_fields_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get document generation form fields from envelope Get document generation form fields from envelope + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetDocgenFormFields`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1898,29 +2234,50 @@ async def get_docgen_form_fields_async( f"/{quote(str(envelope_id), safe='')}" f"/docGenFormFields" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("docgenFields", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def update_docgen_form_fields_async( + def update_docgen_form_fields( self, input: UpdateDocgenFormFieldsInput, account_id: str, @@ -1936,6 +2293,24 @@ async def update_docgen_form_fields_async( Update document generation form fields from envelope Update document generation form fields from envelope + + Swagger operation ID: `UpdateDocgenFormFields`. + + Args: + input: The request body. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + document_guid: Document GUID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1953,7 +2328,7 @@ async def update_docgen_form_fields_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1967,9 +2342,10 @@ async def update_docgen_form_fields_async( request_url, response.status, response.text, + response=response, ) - async def get_doc_gen_template_tabs_async( + def get_doc_gen_template_tabs( self, account_id: str, template_id: str, @@ -1985,6 +2361,22 @@ async def get_doc_gen_template_tabs_async( Get document generation form fields from template (bulk send templates only) + + Swagger operation ID: `GetDocGenTemplateTabs`. + + Args: + account_id: Enter or select an account ID. + template_id: Enter or select a template ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1994,7 +2386,7 @@ async def get_doc_gen_template_tabs_async( f"/{quote(str(template_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2008,6 +2400,7 @@ async def get_doc_gen_template_tabs_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2015,7 +2408,7 @@ async def get_doc_gen_template_tabs_async( return json.loads(response.text) - async def void_envelope_async( + def void_envelope( self, account_id: str, envelope_id: str, @@ -2030,6 +2423,23 @@ async def void_envelope_async( Void the envelope Void the envelope. + + Swagger operation ID: `VoidEnvelope`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + voided_reason: Voided reason. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2047,7 +2457,7 @@ async def void_envelope_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -2061,6 +2471,7 @@ async def void_envelope_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2068,7 +2479,7 @@ async def void_envelope_async( return json.loads(response.text) - async def resend_envelope_async( + def resend_envelope( self, envelope_id: str, *, @@ -2083,6 +2494,21 @@ async def resend_envelope_async( This action resends a Docusign envelope or sends a reminder to recipients who need to sign a Docusign agreement based on a provided EnvelopeId. + + Swagger operation ID: `ResendEnvelope`. + + Args: + envelope_id: Enter an envelope ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2093,7 +2519,7 @@ async def resend_envelope_async( f"/resendEnvelope" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -2107,6 +2533,7 @@ async def resend_envelope_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2114,15 +2541,15 @@ async def resend_envelope_async( return json.loads(response.text) - async def add_reminders_async( + def add_reminders( self, account_id: str, envelope_id: str, reminder_enabled: bool, reminder_delay: str, reminder_frequency: str, - expire_after: Optional[str] = None, *, + expire_after: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2132,6 +2559,28 @@ async def add_reminders_async( Add reminders for an envelope Add reminders for an envelope + + Swagger operation ID: `AddReminders`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + reminder_enabled: When set to false the reminders are disabled. + Default is false. + reminder_delay: Add number of days after which recipient receives + reminder email. + reminder_frequency: Add number of days between reminder emails. + expire_after: Add number of days before expiry. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2162,7 +2611,7 @@ async def add_reminders_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -2176,6 +2625,7 @@ async def add_reminders_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2183,7 +2633,7 @@ async def add_reminders_async( return json.loads(response.text) - async def get_envelope_document_tabs_async( + def list_envelope_document_tabs( self, account_id: str, envelope_id: str, @@ -2193,11 +2643,32 @@ async def get_envelope_document_tabs_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get document tabs from envelope Get document tabs from envelope + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetEnvelopeDocumentTabs`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + document_id: Enter a document ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2209,29 +2680,50 @@ async def get_envelope_document_tabs_async( f"/{quote(str(document_id), safe='')}" f"/tabs" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("tabs", []): + yield item + + return None, items() - async def update_envelope_prefill_tabs_async( + return ItemPaged(get_next, extract_data) + + def update_envelope_prefill_tabs( self, input: UpdateEnvelopePrefillTabsInput, account_id: str, @@ -2247,6 +2739,24 @@ async def update_envelope_prefill_tabs_async( Update envelope prefill tabs Update values for a list of prefill tabs + + Swagger operation ID: `UpdateEnvelopePrefillTabs`. + + Args: + input: The request body. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + document_id: Enter a document ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2259,7 +2769,7 @@ async def update_envelope_prefill_tabs_async( f"/tabs" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -2273,9 +2783,10 @@ async def update_envelope_prefill_tabs_async( request_url, response.status, response.text, + response=response, ) - async def get_template_document_tabs_async( + def list_template_document_tabs( self, account_id: str, template_id: str, @@ -2285,11 +2796,32 @@ async def get_template_document_tabs_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get document tabs from template Get document tabs from template + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTemplateDocumentTabs`. + + Args: + account_id: Enter or select an account ID. + template_id: Enter or select a template ID. + document_id: Enter a document ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2301,29 +2833,50 @@ async def get_template_document_tabs_async( f"/{quote(str(document_id), safe='')}" f"/tabs" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("tabs", []): + yield item - async def get_envelope_document_fields_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_envelope_document_fields( self, account_id: str, envelope_id: str, @@ -2333,11 +2886,32 @@ async def get_envelope_document_fields_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get document custom fields from envelope Get document custom fields from envelope + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetEnvelopeDocumentFields`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + document_id: Enter a document ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2349,37 +2923,58 @@ async def get_envelope_document_fields_async( f"/{quote(str(document_id), safe='')}" f"/fields" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("envelopeDocumentFields", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def composite_templates_async( + def composite_templates( self, - input: CompositeTemplateSchema, + input: CompositeTemplateSchema | Mapping[str, Any], account_id: str, email_subject: str, status: str, + *, email_body: Optional[str] = None, merge_roles_on_draft: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2389,6 +2984,27 @@ async def composite_templates_async( Create envelope using composite templates Create envelope using composite templates + + Swagger operation ID: `CompositeTemplates`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + email_subject: Subject of the email. + status: Envelope status. + email_body: Body of the email. + merge_roles_on_draft: Merge roles and delete empty recipients. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2419,7 +3035,7 @@ async def composite_templates_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2433,6 +3049,7 @@ async def composite_templates_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2440,9 +3057,10 @@ async def composite_templates_async( return json.loads(response.text) - async def search_list_envelopes_async( + def search_list_envelopes( self, account_id: str, + *, recipient_name: Optional[str] = None, recipient_email_id: Optional[str] = None, envelope_title: Optional[str] = None, @@ -2456,7 +3074,6 @@ async def search_list_envelopes_async( skip: Optional[int] = None, from_date: Optional[str] = None, to_date: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2471,6 +3088,39 @@ async def search_list_envelopes_async( title, description, Envelope ID, document names, sender names, envelope status, status date, date sent, and a URL of the envelope which can be used as a link to view the envelope in Docusign. + + Swagger operation ID: `SearchListEnvelopes`. + + Args: + account_id: Enter or select an account ID. + recipient_name: This action lists envelopes based on recipient + name. + recipient_email_id: Filters envelopes by recipient email. + envelope_title: Filters envelopes by envelope subject. + custom_field_name: This action lists envelopes based on a name of + its custom fields. + custom_field_value: Filters by custom field value. + search_text: Enter one keyword to find matches in envelope + subjects, recipients, and custom fields. + envelope_status: This action lists envelopes based on status of the + envelope. + folder_ids: Filters envelopes by the selected folder. + order_by: Sorts envelopes in the selected order. + top: Specify the number of envelopes to return (default is 10; + maximum is 1,000). + skip: Specify the number of envelopes to skip from the start. + from_date: Enter start date-time in UTC format: 2017-05-02T01:44z. + to_date: Enter end date-time in UTC format: 2017-05-02T01:44z. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2548,7 +3198,7 @@ async def search_list_envelopes_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2562,6 +3212,7 @@ async def search_list_envelopes_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2569,7 +3220,7 @@ async def search_list_envelopes_async( return json.loads(response.text) - async def create_envelope_from_template_no_recipients_async( + def create_envelope_from_template_no_recipients( self, account_id: str, template_id: str, @@ -2584,6 +3235,23 @@ async def create_envelope_from_template_no_recipients_async( Create envelope using template Create a new envelope using a specified template. + + Swagger operation ID: `CreateEnvelopeFromTemplateNoRecipients`. + + Args: + account_id: Enter or select an account ID. + template_id: Enter or select a template ID. + status: Envelope status. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2604,7 +3272,7 @@ async def create_envelope_from_template_no_recipients_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -2618,6 +3286,7 @@ async def create_envelope_from_template_no_recipients_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2625,15 +3294,15 @@ async def create_envelope_from_template_no_recipients_async( return json.loads(response.text) - async def send_envelope_async( + def send_envelope( self, - input: DynamicSigners, + input: DynamicSigners | Mapping[str, Any], account_id: str, status: str, template_id: str, + *, email_subject: Optional[str] = None, email_body: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2644,6 +3313,27 @@ async def send_envelope_async( Create a new envelope using a specified template and specify recipients. + + Swagger operation ID: `SendEnvelope`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + status: Envelope status. + template_id: Enter or select a template ID. + email_subject: Email subject. + email_body: Email body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2671,7 +3361,7 @@ async def send_envelope_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2685,6 +3375,7 @@ async def send_envelope_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2692,14 +3383,14 @@ async def send_envelope_async( return json.loads(response.text) - async def send_envelope_with_recipient_fields_async( + def send_envelope_with_recipient_fields( self, - input: DynamicRecipients, + input: DynamicRecipients | Mapping[str, Any], account_id: str, template_id: str, + *, merge_roles_on_draft: Optional[str] = None, email_subject: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2709,6 +3400,26 @@ async def send_envelope_with_recipient_fields_async( Create envelope using template with recipients and tabs Create envelope using template with recipients and tabs + + Swagger operation ID: `SendEnvelopeWithRecipientFields`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + template_id: Enter or select a template ID. + merge_roles_on_draft: Merge roles and delete empty recipients. + email_subject: Email subject. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2735,7 +3446,7 @@ async def send_envelope_with_recipient_fields_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2749,6 +3460,7 @@ async def send_envelope_with_recipient_fields_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2756,7 +3468,7 @@ async def send_envelope_with_recipient_fields_async( return json.loads(response.text) - async def send_draft_envelope_async( + def send_draft_envelope( self, account_id: str, envelope_id: str, @@ -2770,6 +3482,22 @@ async def send_draft_envelope_async( Send envelope Send an existing envelope. + + Swagger operation ID: `SendDraftEnvelope`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2779,7 +3507,7 @@ async def send_draft_envelope_async( f"/{quote(str(envelope_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -2793,6 +3521,7 @@ async def send_draft_envelope_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2800,7 +3529,7 @@ async def send_draft_envelope_async( return json.loads(response.text) - async def get_envelope_custom_field_async( + def get_envelope_custom_field( self, account_id: str, envelope_id: str, @@ -2815,8 +3544,25 @@ async def get_envelope_custom_field_async( Get envelope custom field info Get envelope custom field info. - """ - request_url = ( + + Swagger operation ID: `GetEnvelopeCustomField`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + field_name: Custom Field Name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( f"{self._connection_runtime_url}" f"/accounts" f"/{quote(str(account_id), safe='')}" @@ -2832,7 +3578,7 @@ async def get_envelope_custom_field_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2846,6 +3592,7 @@ async def get_envelope_custom_field_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2853,7 +3600,7 @@ async def get_envelope_custom_field_async( return json.loads(response.text) - async def update_envelope_custom_field_async( + def update_envelope_custom_field( self, account_id: str, envelope_id: str, @@ -2871,6 +3618,26 @@ async def update_envelope_custom_field_async( Update envelope custom field Update value for the specified envelope custom field + + Swagger operation ID: `UpdateEnvelopeCustomField`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + field_id: Custom Field ID. + field_type: Custom Field Type. + name: Custom Field Name. + value: Custom Field Value. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2900,7 +3667,7 @@ async def update_envelope_custom_field_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -2914,6 +3681,7 @@ async def update_envelope_custom_field_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2921,9 +3689,9 @@ async def update_envelope_custom_field_async( return json.loads(response.text) - async def generate_embedded_sender_url_async( + def generate_embedded_sender_url( self, - input: AdditionalURLForSenderView, + input: AdditionalURLForSenderView | Mapping[str, Any], account_id: str, envelope_id: str, open_in: str, @@ -2938,6 +3706,26 @@ async def generate_embedded_sender_url_async( Generate Embedded Sender URL Generate Embedded Sender URL + + Swagger operation ID: `GenerateEmbeddedSenderURL`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + open_in: Open in. + return_url: Return URL. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2960,7 +3748,7 @@ async def generate_embedded_sender_url_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2974,6 +3762,7 @@ async def generate_embedded_sender_url_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2981,7 +3770,7 @@ async def generate_embedded_sender_url_async( return json.loads(response.text) - async def get_recipient_status_async( + def get_recipient_status( self, account_id: str, envelope_id: str, @@ -2995,6 +3784,22 @@ async def get_recipient_status_async( List recipients from an envelope List recipients from an envelope + + Swagger operation ID: `GetRecipientStatus`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3005,7 +3810,7 @@ async def get_recipient_status_async( f"/recipients" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3019,6 +3824,7 @@ async def get_recipient_status_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3026,7 +3832,7 @@ async def get_recipient_status_async( return json.loads(response.text) - async def remove_recipient_from_envelope_async( + def remove_recipient_from_envelope( self, account_id: str, envelope_id: str, @@ -3042,6 +3848,24 @@ async def remove_recipient_from_envelope_async( Remove recipient from an envelope Remove recipient from an envelope + + Swagger operation ID: `RemoveRecipientFromEnvelope`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + folder_id: Folder ID. + remove_recipient_from_envelope_recipient_id: Recipient ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3063,7 +3887,7 @@ async def remove_recipient_from_envelope_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -3077,6 +3901,7 @@ async def remove_recipient_from_envelope_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3084,15 +3909,15 @@ async def remove_recipient_from_envelope_async( return json.loads(response.text) - async def get_recipient_fields_async( + def get_recipient_fields( self, account_id: str, envelope_id: str, + *, recipient_email: Optional[str] = None, area_code: Optional[str] = None, phone_number: Optional[str] = None, recipient_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3102,6 +3927,26 @@ async def get_recipient_fields_async( Get recipient info from envelope Get recipient info from envelope + + Swagger operation ID: `GetRecipientFields`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_email: Recipient email. + area_code: Area code of the recipient. + phone_number: Phone number of the recipient. + recipient_id: Enter a recipient ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3135,7 +3980,7 @@ async def get_recipient_fields_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3149,6 +3994,7 @@ async def get_recipient_fields_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3156,7 +4002,7 @@ async def get_recipient_fields_async( return json.loads(response.text) - async def get_audit_events_async( + def get_audit_events( self, account_id: str, envelope_id: str, @@ -3170,6 +4016,22 @@ async def get_audit_events_async( Get audit event list Get audit event list + + Swagger operation ID: `GetAuditEvents`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3180,7 +4042,7 @@ async def get_audit_events_async( f"/audit_events" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3194,6 +4056,7 @@ async def get_audit_events_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3201,9 +4064,9 @@ async def get_audit_events_async( return json.loads(response.text) - async def add_verification_to_recipient_async( + def add_verification_to_recipient( self, - input: AdditionalRecipientData, + input: AdditionalRecipientData | Mapping[str, Any], account_id: str, envelope_id: str, recipient_id: str, @@ -3219,6 +4082,27 @@ async def add_verification_to_recipient_async( Add verification type to a recipient Add verification type to a recipient. + + Swagger operation ID: `AddVerificationToRecipient`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_id: Enter a recipient ID. + recipient_type: Enter or select a recipient type. + verification_type: Verification type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3245,7 +4129,7 @@ async def add_verification_to_recipient_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -3259,6 +4143,7 @@ async def add_verification_to_recipient_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3266,13 +4151,14 @@ async def add_verification_to_recipient_async( return json.loads(response.text) - async def update_envelope_recipient_async( + def update_envelope_recipient( self, - input: AdditionalRecipientParamsSchema, + input: AdditionalRecipientParamsSchema | Mapping[str, Any], account_id: str, envelope_id: str, recipient_id: str, recipient_type: str, + *, signature_type: Optional[str] = None, client_user_id: Optional[str] = None, embedded_recipient_start_u_r_l: Optional[str] = None, @@ -3285,7 +4171,6 @@ async def update_envelope_recipient_async( country_code: Optional[str] = None, phone_number: Optional[str] = None, signing_group_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3295,6 +4180,41 @@ async def update_envelope_recipient_async( Update recipient on an envelope Update recipient on an envelope + + Swagger operation ID: `UpdateEnvelopeRecipient`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_id: Enter a recipient ID. + recipient_type: Recipient type. + signature_type: DocuSign standards-based-signature (SBS) types. + client_user_id: Client user ID for embedded signer. + embedded_recipient_start_u_r_l: A sender-provided URL string for + redirecting an embedded recipient. + routing_order: The signing order of the recipient. + email_notification_language: Language for the email notification. + email_notification_subject: Subject of the email notification. + email_notification_body: Body of the email notification. + note: Custom note for the recipient. + role_name: Role name associated with the recipient. + country_code: For SMS notifications, the country code, without + leading + sign. + phone_number: Signer email or SMS phone required. Exclude country + code for phone number. + signing_group_id: Signing Group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3377,7 +4297,7 @@ async def update_envelope_recipient_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -3391,6 +4311,7 @@ async def update_envelope_recipient_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3398,14 +4319,14 @@ async def update_envelope_recipient_async( return json.loads(response.text) - async def apply_templates_to_documents_async( + def apply_templates_to_documents( self, - input: ApplyTemplatesToDocumentsInput, + input: ApplyTemplatesToDocumentsInput | Mapping[str, Any], account_id: str, envelope_id: str, template_id: str, - preserve_template_recipient: Optional[str] = None, *, + preserve_template_recipient: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3415,6 +4336,26 @@ async def apply_templates_to_documents_async( Apply a template to documents Apply a template to documents + + Swagger operation ID: `ApplyTemplatesToDocuments`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + template_id: Enter or select a template ID. + preserve_template_recipient: False. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3437,7 +4378,7 @@ async def apply_templates_to_documents_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3451,11 +4392,12 @@ async def apply_templates_to_documents_async( request_url, response.status, response.text, + response=response, ) - async def create_bulk_send_list_async( + def create_bulk_send_list( self, - input: CreateBulkSendListInput, + input: CreateBulkSendListInput | Mapping[str, Any], account_id: str, name: str, *, @@ -3468,6 +4410,24 @@ async def create_bulk_send_list_async( Create bulk send list Create bulk send list + + Swagger operation ID: `CreateBulkSendList`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + name: Bulk send list name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3481,7 +4441,7 @@ async def create_bulk_send_list_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3495,6 +4455,7 @@ async def create_bulk_send_list_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3502,7 +4463,7 @@ async def create_bulk_send_list_async( return json.loads(response.text) - async def bulk_send_async( + def bulk_send( self, account_id: str, bulk_send_list_id: str, @@ -3517,6 +4478,24 @@ async def bulk_send_async( Bulk send envelope using template Bulk send envelope using template + + Swagger operation ID: `BulkSend`. + + Args: + account_id: Enter or select an account ID. + bulk_send_list_id: Bulk send list GUID. + envelope_or_template_id: Enter the template ID, or choose a + template from the dropdown. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3534,7 +4513,7 @@ async def bulk_send_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -3548,6 +4527,7 @@ async def bulk_send_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3555,43 +4535,82 @@ async def bulk_send_async( return json.loads(response.text) - async def get_login_accounts_async( + def list_login_accounts( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Login Login + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetLoginAccounts`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/oauth/userinfo" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("loginAccounts", []): + yield item - async def get_envelope_templates_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_envelope_templates( self, account_id: str, *, @@ -3599,41 +4618,81 @@ async def get_envelope_templates_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List templates List templates for a specific account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetEnvelopeTemplates`. + + Args: + account_id: Enter or select an account ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/accounts/{quote(str(account_id), safe='')}/templates" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("envelopeTemplates", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def add_documents_to_envelope_async( + def add_documents_to_envelope( self, - input: AddDocumentsToEnvelopeInput, + input: AddDocumentsToEnvelopeInput | Mapping[str, Any], account_id: str, envelope_id: str, *, @@ -3646,6 +4705,24 @@ async def add_documents_to_envelope_async( Add documents to an envelope Add documents to an envelope. + + Swagger operation ID: `AddDocumentsToEnvelope`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3656,7 +4733,7 @@ async def add_documents_to_envelope_async( f"/documents" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -3670,6 +4747,7 @@ async def add_documents_to_envelope_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3677,7 +4755,7 @@ async def add_documents_to_envelope_async( return json.loads(response.text) - async def list_template_documents_async( + def list_template_documents( self, account_id: str, template_id: str, @@ -3686,11 +4764,31 @@ async def list_template_documents_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List documents from a template List documents from a template + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTemplateDocuments`. + + Args: + account_id: Enter or select an account ID. + template_id: Enter or select a template ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3700,29 +4798,50 @@ async def list_template_documents_async( f"/{quote(str(template_id), safe='')}" f"/documents" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("templateDocuments", []): + yield item + + return None, items() - async def list_envelope_documents_async( + return ItemPaged(get_next, extract_data) + + def list_envelope_documents( self, account_id: str, envelope_id: str, @@ -3731,11 +4850,31 @@ async def list_envelope_documents_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List documents from an envelope List documents from an envelope + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListEnvelopeDocuments`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3745,29 +4884,50 @@ async def list_envelope_documents_async( f"/{quote(str(envelope_id), safe='')}" f"/envelopeDocuments" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("envelopeDocuments", []): + yield item + + return None, items() - async def get_envelope_document_info_async( + return ItemPaged(get_next, extract_data) + + def get_envelope_document_info( self, account_id: str, envelope_id: str, @@ -3782,6 +4942,23 @@ async def get_envelope_document_info_async( Get document info from envelope Get document info from envelope + + Swagger operation ID: `GetEnvelopeDocumentInfo`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + document_name: File name with extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3799,7 +4976,7 @@ async def get_envelope_document_info_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3813,6 +4990,7 @@ async def get_envelope_document_info_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3820,7 +4998,7 @@ async def get_envelope_document_info_async( return json.loads(response.text) - async def get_tab_info_async( + def get_tab_info( self, account_id: str, envelope_id: str, @@ -3836,6 +5014,24 @@ async def get_tab_info_async( Get info for recipient tab Returns the value of the tab for the given recipient + + Swagger operation ID: `GetTabInfo`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_id: Enter a recipient ID. + tab_label: Tab label. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3855,7 +5051,7 @@ async def get_tab_info_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3869,6 +5065,7 @@ async def get_tab_info_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3876,9 +5073,9 @@ async def get_tab_info_async( return json.loads(response.text) - async def add_recipient_tabs_async( + def add_recipient_tabs( self, - input: AnchorTabSchema, + input: AnchorTabSchema | Mapping[str, Any], account_id: str, envelope_id: str, recipient_id: str, @@ -3893,6 +5090,26 @@ async def add_recipient_tabs_async( Add tabs for a recipient on an envelope Add tabs for a recipient on an envelope + + Swagger operation ID: `AddRecipientTabs`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_id: Enter a recipient ID. + tab_type: Tab type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3912,7 +5129,7 @@ async def add_recipient_tabs_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3926,6 +5143,7 @@ async def add_recipient_tabs_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3933,7 +5151,7 @@ async def add_recipient_tabs_async( return json.loads(response.text) - async def update_recipient_tabs_values_async( + def update_recipient_tabs_values( self, input: UpdateRecipientTabsValuesInput, account_id: str, @@ -3949,6 +5167,24 @@ async def update_recipient_tabs_values_async( Update recipient tab values on an envelope Update recipient tab values on an envelope + + Swagger operation ID: `UpdateRecipientTabsValues`. + + Args: + input: The request body. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_id: Enter a recipient ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3961,7 +5197,7 @@ async def update_recipient_tabs_values_async( f"/tabs" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -3975,9 +5211,10 @@ async def update_recipient_tabs_values_async( request_url, response.status, response.text, + response=response, ) - async def get_envelope_recipient_tabs_async( + def list_envelope_recipient_tabs( self, account_id: str, envelope_id: str, @@ -3987,11 +5224,32 @@ async def get_envelope_recipient_tabs_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get recipient tabs from envelope Get recipient tabs from envelope + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetEnvelopeRecipientTabs`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_id: Enter a recipient ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4003,31 +5261,52 @@ async def get_envelope_recipient_tabs_async( f"/{quote(str(recipient_id), safe='')}" f"/recipientTabs" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("recipientTabs", []): + yield item + + return None, items() - async def trigger_maestro_flow_async( + return ItemPaged(get_next, extract_data) + + def trigger_maestro_flow( self, - input: MaestroInputVariables, + input: MaestroInputVariables | Mapping[str, Any], account_id: str, workflow_id: str, instance_name: str, @@ -4041,6 +5320,26 @@ async def trigger_maestro_flow_async( Start Docusign workflow Start Docusign workflow + + Swagger operation ID: `TriggerMaestroFlow`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + workflow_id: Enter the workflow ID or select the workflow name from + the dropdown. + instance_name: Name of the workflow instance. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4058,7 +5357,7 @@ async def trigger_maestro_flow_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4072,6 +5371,7 @@ async def trigger_maestro_flow_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4079,9 +5379,9 @@ async def trigger_maestro_flow_async( return json.loads(response.text) - async def build_number_async( + def build_number( self, - input: BuildNumberSchema, + input: BuildNumberSchema | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -4093,10 +5393,26 @@ async def build_number_async( execution) Identifier for the currently deployed build. + + Swagger operation ID: `BuildNumber`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/build_number" - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -4110,6 +5426,7 @@ async def build_number_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4117,12 +5434,13 @@ async def build_number_async( return json.loads(response.text) - async def add_recipient_to_envelope_async( + def add_recipient_to_envelope( self, - input: AdditionalRecipientParamsSchema, + input: AdditionalRecipientParamsSchema | Mapping[str, Any], account_id: str, envelope_id: str, recipient_type: str, + *, client_user_id: Optional[str] = None, recipient_id: Optional[str] = None, embedded_recipient_start_u_r_l: Optional[str] = None, @@ -4137,7 +5455,6 @@ async def add_recipient_to_envelope_async( signing_group_id: Optional[str] = None, signature_type: Optional[str] = None, workflow_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4147,6 +5464,43 @@ async def add_recipient_to_envelope_async( Add recipient to an envelope Add recipient to an envelope. + + Swagger operation ID: `AddRecipientToEnvelopeV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + recipient_type: Enter or select a recipient type. + client_user_id: Client user ID for embedded signer. + recipient_id: Enter a recipient ID. + embedded_recipient_start_u_r_l: A sender-provided URL string for + redirecting an embedded recipient. + routing_order: The signing order of the recipient. + email_notification_language: Language for the email notification. + email_notification_subject: Subject of the email notification. + email_notification_body: Body of the email notification. + note: Custom note for the recipient. + role_name: Role name associated with the recipient. + country_code: For SMS notifications, the country code, without + leading + sign. + phone_number: Signer email or SMS phone required. Exclude country + code for phone number. + signing_group_id: Signing Group. + signature_type: DocuSign standards-based-signature (SBS) types. + workflow_id: IDV workflows with pen signature types must be + selected here. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4235,7 +5589,7 @@ async def add_recipient_to_envelope_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4249,6 +5603,7 @@ async def add_recipient_to_envelope_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4256,9 +5611,9 @@ async def add_recipient_to_envelope_async( return json.loads(response.text) - async def create_blank_envelope_async( + def create_blank_envelope( self, - input: CombinedEmailBodyAndCustomFields, + input: CombinedEmailBodyAndCustomFields | Mapping[str, Any], account_id: str, email_subject: str, *, @@ -4271,6 +5626,24 @@ async def create_blank_envelope_async( Create envelope Create a new blank envelope. + + Swagger operation ID: `CreateBlankEnvelopeV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + email_subject: Subject of the email. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4287,7 +5660,7 @@ async def create_blank_envelope_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4301,6 +5674,7 @@ async def create_blank_envelope_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4308,9 +5682,9 @@ async def create_blank_envelope_async( return json.loads(response.text) - async def generate_embedded_signing_url_async( + def generate_embedded_signing_url( self, - input: DynamicSigningUrlFields, + input: DynamicSigningUrlFields | Mapping[str, Any], account_id: str, envelope_id: str, is_in_person_signer: str, @@ -4326,6 +5700,27 @@ async def generate_embedded_signing_url_async( Generate Embedded Signing URL Generate Embedded Signing URL + + Swagger operation ID: `GenerateEmbeddedSigningURLV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + is_in_person_signer: Yes/No. + authentication_method: Authentication Method. + return_url: Return URL. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4352,7 +5747,7 @@ async def generate_embedded_signing_url_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4366,6 +5761,7 @@ async def generate_embedded_signing_url_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4373,13 +5769,13 @@ async def generate_embedded_signing_url_async( return json.loads(response.text) - async def get_documents_async( + def get_documents( self, account_id: str, envelope_id: str, document_id: str, - language: Optional[str] = None, *, + language: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4389,6 +5785,25 @@ async def get_documents_async( Get documents from an envelope Get documents from an envelope + + Swagger operation ID: `GetDocumentsV2`. + + Args: + account_id: Enter or select an account ID. + envelope_id: Enter an envelope ID. + document_id: Enter \"string(document ID)\" to get a single + document, or select a format. + language: Select language. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4409,7 +5824,7 @@ async def get_documents_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4423,6 +5838,7 @@ async def get_documents_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4430,18 +5846,36 @@ async def get_documents_async( return json.loads(response.text) - async def get_organizations_async( + def list_organizations( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get organizations Get organizations + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetOrganizations`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/Management/v2/organizations" @@ -4450,29 +5884,50 @@ async def get_organizations_async( query_params.append("mode=" + quote("org_admin", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("organizations", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_account_custom_fields_async( + def get_account_custom_fields( self, account_id: str, *, @@ -4485,6 +5940,21 @@ async def get_account_custom_fields_async( Get account custom fields Get the custom fields for a specified account. + + Swagger operation ID: `GetAccountCustomFields`. + + Args: + account_id: Account id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4493,7 +5963,7 @@ async def get_account_custom_fields_async( f"/account_custom_fields" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4507,9 +5977,10 @@ async def get_account_custom_fields_async( request_url, response.status, response.text, + response=response, ) - async def get_folder_list_async( + def list_get_folder( self, account_id: str, *, @@ -4517,39 +5988,79 @@ async def get_folder_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List folders List folders for a specific account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetFolderList`. + + Args: + account_id: Account id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/accounts/{quote(str(account_id), safe='')}/folders" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("folders", []): + yield item + + return None, items() - async def get_folder_envelope_list_async( + return ItemPaged(get_next, extract_data) + + def list_get_folder_envelope( self, account_id: str, folder_id: str, @@ -4558,11 +6069,31 @@ async def get_folder_envelope_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List envelopes List envelopes under a particular folder. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetFolderEnvelopeList`. + + Args: + account_id: Enter or select an account ID. + folder_id: Folder id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4571,101 +6102,200 @@ async def get_folder_envelope_list_async( f"/folders" f"/{quote(str(folder_id), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("folderItems", []): + yield item + + return None, items() - async def static_response_for_recipient_types_async( + return ItemPaged(get_next, extract_data) + + def list_static_response_for_recipient_types( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ StaticResponseForRecipientTypes Get recipient types. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `StaticResponseForRecipientTypes`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/recipient_types" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("tabTypes", []): + yield item + + return None, items() - async def static_response_for_signature_types_async( + return ItemPaged(get_next, extract_data) + + def list_static_response_for_signature_types( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ StaticResponseForSignatureTypes Get signature types. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `StaticResponseForSignatureTypes`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/signature_types" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("tabTypes", []): + yield item + + return None, items() - async def get_signing_groups_async( + return ItemPaged(get_next, extract_data) + + def list_signing_groups( self, account_id: str, *, @@ -4673,75 +6303,154 @@ async def get_signing_groups_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ GetSigningGroups List signing groups for a specific account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetSigningGroups`. + + Args: + account_id: Account id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/accounts/{quote(str(account_id), safe='')}/signing_groups" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("signingGroups", []): + yield item - async def static_response_for_tab_types_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_static_response_for_tab_types( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ StaticResponseForTabTypes Get tab types. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `StaticResponseForTabTypes`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/tab_types" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("tabTypes", []): + yield item + + return None, items() - async def get_maestro_workflow_definitions_async( + return ItemPaged(get_next, extract_data) + + def list_maestro_workflow_definitions( self, account_id: str, *, @@ -4749,39 +6458,79 @@ async def get_maestro_workflow_definitions_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Maestro Workflow Definitions Get Maestro Workflow Definitions + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMaestroWorkflowDefinitions`. + + Args: + account_id: accountId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/accounts/{quote(str(account_id), safe='')}/maestro-workflows" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("WorkflowDefinitions", []): + yield item - async def get_all_workflow_i_ds_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_all_workflow_i_ds( self, account_id: str, *, @@ -4789,11 +6538,30 @@ async def get_all_workflow_i_ds_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get All Workflow Ids Get All workflow ids + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAllWorkflowIDs`. + + Args: + account_id: Account id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4801,29 +6569,50 @@ async def get_all_workflow_i_ds_async( f"/{quote(str(account_id), safe='')}" f"/all_identity_verification" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("workflowIds", []): + yield item - async def get_maestro_workflow_definition_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_maestro_workflow_definition( self, account_id: str, workflow_id: str, @@ -4837,6 +6626,22 @@ async def get_maestro_workflow_definition_async( Get Maestro Workflow Definition Get Maestro Workflow Definition + + Swagger operation ID: `GetMaestroWorkflowDefinition`. + + Args: + account_id: accountId. + workflow_id: workflowId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4846,7 +6651,7 @@ async def get_maestro_workflow_definition_async( f"/{quote(str(workflow_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4860,6 +6665,7 @@ async def get_maestro_workflow_definition_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4867,7 +6673,7 @@ async def get_maestro_workflow_definition_async( return json.loads(response.text) - async def get_dynamic_signers_async( + def get_dynamic_signers( self, account_id: str, template_id: str, @@ -4881,6 +6687,22 @@ async def get_dynamic_signers_async( Get the signers of a template in dynamic schema format Get the signers of a template in dynamic schema format. + + Swagger operation ID: `GetDynamicSigners`. + + Args: + account_id: Account to get the signers for. + template_id: Template to get the signers for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4892,7 +6714,7 @@ async def get_dynamic_signers_async( f"/recipients" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4906,6 +6728,7 @@ async def get_dynamic_signers_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4913,7 +6736,7 @@ async def get_dynamic_signers_async( return json.loads(response.text) - async def get_dynamic_recipients_async( + def get_dynamic_recipients( self, account_id: str, template_id: str, @@ -4927,6 +6750,22 @@ async def get_dynamic_recipients_async( Get the signers of a template in dynamic schema format Get the signers of a template in dynamic schema format. + + Swagger operation ID: `GetDynamicRecipients`. + + Args: + account_id: Account to get the signers for. + template_id: Template to get the signers for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4937,7 +6776,7 @@ async def get_dynamic_recipients_async( f"/{quote(str(template_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4951,6 +6790,7 @@ async def get_dynamic_recipients_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4958,11 +6798,11 @@ async def get_dynamic_recipients_async( return json.loads(response.text) - async def static_response_for_recipient_type_schema_async( + def static_response_for_recipient_type_schema( self, recipient_type: str, - signature_type: Optional[str] = None, *, + signature_type: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4972,6 +6812,22 @@ async def static_response_for_recipient_type_schema_async( StaticResponseForRecipientTypeSchema Get schema for a specific recipient type. + + Swagger operation ID: `StaticResponseForRecipientTypeSchema`. + + Args: + recipient_type: recipient type. + signature_type: signature type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/recipienttype_schema" query_params = [] @@ -4987,7 +6843,7 @@ async def static_response_for_recipient_type_schema_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5001,6 +6857,7 @@ async def static_response_for_recipient_type_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5008,7 +6865,7 @@ async def static_response_for_recipient_type_schema_async( return json.loads(response.text) - async def static_response_for_verification_type_schema_async( + def static_response_for_verification_type_schema( self, verification_type: str, *, @@ -5021,6 +6878,21 @@ async def static_response_for_verification_type_schema_async( StaticResponseForVerificationTypeSchema Get schema for a verification type. + + Swagger operation ID: `StaticResponseForVerificationTypeSchema`. + + Args: + verification_type: Verification Type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/verificationtype_schema" query_params = [] @@ -5031,7 +6903,7 @@ async def static_response_for_verification_type_schema_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5045,6 +6917,7 @@ async def static_response_for_verification_type_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5052,7 +6925,7 @@ async def static_response_for_verification_type_schema_async( return json.loads(response.text) - async def static_response_for_embedded_sender_schema_async( + def static_response_for_embedded_sender_schema( self, return_url: str, *, @@ -5065,6 +6938,21 @@ async def static_response_for_embedded_sender_schema_async( StaticResponseForEmbeddedSenderSchema Get schema for return URL. + + Swagger operation ID: `StaticResponseForEmbeddedSenderSchema`. + + Args: + return_url: Return URL. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/embeddedSender_schema" query_params = [] @@ -5075,7 +6963,7 @@ async def static_response_for_embedded_sender_schema_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5089,6 +6977,7 @@ async def static_response_for_embedded_sender_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5096,7 +6985,7 @@ async def static_response_for_embedded_sender_schema_async( return json.loads(response.text) - async def static_response_for_embedded_signing_schema_async( + def static_response_for_embedded_signing_schema( self, return_url: str, is_in_person_signer: str, @@ -5110,6 +6999,22 @@ async def static_response_for_embedded_signing_schema_async( StaticResponseForEmbeddedSigningSchema Get schema for return URL. + + Swagger operation ID: `StaticResponseForEmbeddedSigningSchemaV2`. + + Args: + return_url: Return URL. + is_in_person_signer: Is this an in-person signer? + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/embeddedSigning_schema_v2" @@ -5126,7 +7031,7 @@ async def static_response_for_embedded_signing_schema_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5140,6 +7045,7 @@ async def static_response_for_embedded_signing_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5147,7 +7053,7 @@ async def static_response_for_embedded_signing_schema_async( return json.loads(response.text) - async def static_response_for_build_number_schema_async( + def static_response_for_build_number_schema( self, *, timeout: Optional[float] = None, @@ -5159,10 +7065,24 @@ async def static_response_for_build_number_schema_async( StaticResponseForBuildNumberSchema Get schema for a build number. + + Swagger operation ID: `StaticResponseForBuildNumberSchema`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/build_number_schema" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5176,6 +7096,7 @@ async def static_response_for_build_number_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5183,7 +7104,7 @@ async def static_response_for_build_number_schema_async( return json.loads(response.text) - async def get_custom_fields_async( + def get_custom_fields( self, account_id: str, *, @@ -5196,13 +7117,28 @@ async def get_custom_fields_async( Get custom fields from an account Get custom fields from an account + + Swagger operation ID: `GetCustomFields`. + + Args: + account_id: Account id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/accounts/{quote(str(account_id), safe='')}/custom_fields" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5216,9 +7152,10 @@ async def get_custom_fields_async( request_url, response.status, response.text, + response=response, ) - async def static_response_for_anchor_tab_schema_async( + def static_response_for_anchor_tab_schema( self, tab_type: str, *, @@ -5231,6 +7168,21 @@ async def static_response_for_anchor_tab_schema_async( StaticResponseForAnchorTabSchema Get schema for a specific anchor tab. + + Swagger operation ID: `StaticResponseForAnchorTabSchema`. + + Args: + tab_type: tab type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/anchortab_schema" query_params = [] @@ -5241,7 +7193,7 @@ async def static_response_for_anchor_tab_schema_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5255,6 +7207,7 @@ async def static_response_for_anchor_tab_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5262,7 +7215,7 @@ async def static_response_for_anchor_tab_schema_async( return json.loads(response.text) - async def static_response_for_composite_templates_async( + def static_response_for_composite_templates( self, *, timeout: Optional[float] = None, @@ -5274,12 +7227,26 @@ async def static_response_for_composite_templates_async( StaticResponseForCompositeTemplates Get schema for a composite templates. + + Swagger operation ID: `StaticResponseForCompositeTemplates`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/composite_templates_schema" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5293,6 +7260,7 @@ async def static_response_for_composite_templates_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/docuware.py b/src/azure/connectors/docuware.py index d3db694..5fa6b2c 100644 --- a/src/azure/connectors/docuware.py +++ b/src/azure/connectors/docuware.py @@ -5,21 +5,43 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "DocuwareClient", + "GetDialogFieldsResponse", + "GetDialogsResponse", + "GetDocumentInformationResponse", + "GetFileCabinetFieldsResponse", + "GetFileCabinetsResponse", + "GetOrganizationResponse", + "GetStampFieldsResponse", + "GetStampsResponse", + "ListDocumentsInDocumentTrayResponse", + "PlaceAStampInput", + "PlaceAStampResponse", + "SearchForDocumentsInFileCabinetInput", + "SearchForDocumentsInFileCabinetResponse", + "TransferDocumentInput", + "TransferDocumentResponse", + "UpdateIndexFieldsInput", + "UpdateIndexFieldsResponse", +] + # Type Definitions @@ -29,7 +51,7 @@ class SearchForDocumentsInFileCabinetInput: Search in file cabinet """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -42,10 +64,15 @@ class SearchForDocumentsInFileCabinetResponse: Response for Search in file cabinet """ - count: Optional[int] = field(default=None, metadata={"wire_name": "Count"}) + count: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Count"}, + ) """Count""" - documents: Optional[List[Dict[str, Any]]] = field( + documents: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Documents"}, ) """Documents""" @@ -57,7 +84,11 @@ class GetOrganizationResponse: Response for Get organization """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Name""" @@ -67,8 +98,9 @@ class GetFileCabinetsResponse: Response for Get file cabinets and document trays """ - file_cabinets: Optional[List[Dict[str, Any]]] = field( + file_cabinets: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileCabinets"}, ) """FileCabinets""" @@ -80,53 +112,63 @@ class GetDocumentInformationResponse: Response for Get document information """ - sections: Optional[List[Dict[str, Any]]] = field( + sections: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sections"}, ) """Sections""" - document_id: Optional[int] = field( + document_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DocumentId"}, ) """DocumentId""" - index_fields: Optional[Dict[str, Any]] = field( + index_fields: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IndexFields"}, ) """IndexFields""" - document_title: Optional[str] = field( + document_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DocumentTitle"}, ) """DocumentTitle""" - file_cabinet_id: Optional[str] = field( + file_cabinet_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileCabinetId"}, ) """FileCabinetId""" - total_pages: Optional[int] = field( + total_pages: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TotalPages"}, ) """TotalPages""" - file_size: Optional[int] = field( + file_size: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileSize"}, ) """FileSize""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentType"}, ) """ContentType""" - version_status: Optional[str] = field( + version_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VersionStatus"}, ) """VersionStatus""" - document_flags: Optional[Dict[str, Any]] = field( + document_flags: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DocumentFlags"}, ) """DocumentFlags""" @@ -141,53 +183,63 @@ class UpdateIndexFieldsResponse: Response for Update index fields """ - sections: Optional[List[Dict[str, Any]]] = field( + sections: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sections"}, ) """Sections""" - document_id: Optional[int] = field( + document_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DocumentId"}, ) """DocumentId""" - index_fields: Optional[Dict[str, Any]] = field( + index_fields: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IndexFields"}, ) """IndexFields""" - document_title: Optional[str] = field( + document_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DocumentTitle"}, ) """DocumentTitle""" - file_cabinet_id: Optional[str] = field( + file_cabinet_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileCabinetId"}, ) """FileCabinetId""" - total_pages: Optional[int] = field( + total_pages: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TotalPages"}, ) """TotalPages""" - file_size: Optional[int] = field( + file_size: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileSize"}, ) """FileSize""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentType"}, ) """ContentType""" - version_status: Optional[str] = field( + version_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VersionStatus"}, ) """VersionStatus""" - document_flags: Optional[Dict[str, Any]] = field( + document_flags: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DocumentFlags"}, ) """DocumentFlags""" @@ -199,22 +251,24 @@ class TransferDocumentInput: Transfer documents """ - source_file_cabinet_id: Optional[str] = field( - default=None, + source_file_cabinet_id: str = dataclass_field( metadata={"wire_name": "SourceFileCabinetId"}, ) """Select the source File Cabinet or Document Tray.""" - documents: Optional[List[Dict[str, Any]]] = field( + documents: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Documents"}, ) - keep_source: Optional[bool] = field( + keep_source: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "KeepSource"}, ) """Choose whether the source documents should be deleted or not.""" - fill_intellix: Optional[bool] = field( + fill_intellix: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FillIntellix"}, ) """Choose whether intelligent indexing should be used when storing.""" @@ -226,10 +280,15 @@ class TransferDocumentResponse: Response for Transfer documents """ - count: Optional[int] = field(default=None, metadata={"wire_name": "Count"}) + count: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Count"}, + ) """Count""" - documents: Optional[List[Dict[str, Any]]] = field( + documents: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Documents"}, ) """Documents""" @@ -241,40 +300,35 @@ class PlaceAStampInput: Place a stamp """ - file_number: Optional[int] = field( - default=None, - metadata={"wire_name": "FileNumber"}, - ) + file_number: int = dataclass_field(metadata={"wire_name": "FileNumber"}) """Specify the file/section containing the page to be stamped.""" - page_number: Optional[int] = field( - default=None, - metadata={"wire_name": "PageNumber"}, - ) + page_number: int = dataclass_field(metadata={"wire_name": "PageNumber"}) """Specify the page number to place the stamp on.""" - layer: Optional[int] = field(default=None, metadata={"wire_name": "Layer"}) + layer: int = dataclass_field(metadata={"wire_name": "Layer"}) """Specify the document layer to place the stamp on [1-5]""" - position_x: Optional[float] = field( + position_x: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PositionX"}, ) """[Optional] Position from the left edge of the page in mm.""" - position_y: Optional[float] = field( + position_y: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PositionY"}, ) """[Optional] Position from the upper edge of the page in mm.""" - stamp_id: Optional[str] = field( - default=None, - metadata={"wire_name": "StampId"}, - ) + stamp_id: str = dataclass_field(metadata={"wire_name": "StampId"}) """Select or specify the stamp to be used.""" - password: Optional[str] = field( + password: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Password"}, ) """Specify the password for the stamp (if required).""" - fields: Optional[List[Dict[str, Any]]] = field( + fields: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Fields"}, ) @@ -285,31 +339,47 @@ class PlaceAStampResponse: Response for Place a stamp """ - created: Optional[Dict[str, Any]] = field( + created: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Created"}, ) """Created""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Type"}, + ) """Type""" - color: Optional[str] = field(default=None, metadata={"wire_name": "Color"}) + color: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Color"}, + ) """Color""" - rotation: Optional[int] = field( + rotation: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Rotation"}, ) """Rotation""" - transparent: Optional[bool] = field( + transparent: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Transparent"}, ) """Transparent""" - stroke_width: Optional[int] = field( + stroke_width: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StrokeWidth"}, ) """StrokeWidth""" - guid: Optional[str] = field(default=None, metadata={"wire_name": "Guid"}) + guid: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Guid"}, + ) """Guid""" @@ -319,8 +389,9 @@ class GetDialogsResponse: Response for Get dialogs """ - dialogs: Optional[List[Dict[str, Any]]] = field( + dialogs: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Dialogs"}, ) """Dialogs""" @@ -332,8 +403,9 @@ class GetStampsResponse: Response for Get stamps """ - stamps: Optional[List[Dict[str, Any]]] = field( + stamps: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Stamps"}, ) """Stamps""" @@ -345,8 +417,9 @@ class GetStampFieldsResponse: Response for Get stamp fields """ - fields: Optional[List[Dict[str, Any]]] = field( + fields: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Fields"}, ) """Fields""" @@ -358,8 +431,9 @@ class GetFileCabinetFieldsResponse: Response for Get file cabinet fields """ - fields: Optional[List[Dict[str, Any]]] = field( + fields: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Fields"}, ) """Fields""" @@ -371,8 +445,9 @@ class GetDialogFieldsResponse: Response for Get dialog fields """ - fields: Optional[List[Dict[str, Any]]] = field( + fields: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Fields"}, ) """Fields""" @@ -384,10 +459,15 @@ class ListDocumentsInDocumentTrayResponse: Response for List documents in document tray """ - count: Optional[int] = field(default=None, metadata={"wire_name": "Count"}) + count: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Count"}, + ) """Count""" - documents: Optional[List[Dict[str, Any]]] = field( + documents: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Documents"}, ) @@ -400,16 +480,16 @@ class DocuwareClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -420,8 +500,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -429,8 +509,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -442,7 +522,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -457,9 +537,48 @@ def __init__( def connector_name(self) -> str: return "docuware" - async def search_for_documents_in_file_cabinet_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def search_for_documents_in_file_cabinet( self, - input: SearchForDocumentsInFileCabinetInput, + input: SearchForDocumentsInFileCabinetInput | Mapping[str, Any], file_cabinet: str, search_dialog_id: str, *, @@ -472,6 +591,24 @@ async def search_for_documents_in_file_cabinet_async( Search in file cabinet Search a file cabinet for documents matching the specified criteria. + + Swagger operation ID: `SearchForDocumentsInFileCabinet`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + file_cabinet: Select the File Cabinet to search. + search_dialog_id: Select the search dialog to use for searching. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -485,7 +622,7 @@ async def search_for_documents_in_file_cabinet_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -499,6 +636,7 @@ async def search_for_documents_in_file_cabinet_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -506,7 +644,7 @@ async def search_for_documents_in_file_cabinet_async( return json.loads(response.text) - async def get_organization_async( + def get_organization( self, *, timeout: Optional[float] = None, @@ -518,10 +656,24 @@ async def get_organization_async( Get organization Get the organization name. + + Swagger operation ID: `GetOrganization`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Organization" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -535,6 +687,7 @@ async def get_organization_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -542,7 +695,7 @@ async def get_organization_async( return json.loads(response.text) - async def get_file_cabinets_async( + def list_file_cabinets( self, file_cabinet_type: str, *, @@ -550,11 +703,30 @@ async def get_file_cabinets_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get file cabinets and document trays Gets a list of file cabinets and/or document trays. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetFileCabinets`. + + Args: + file_cabinet_type: Select which types you want returned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/FileCabinets" query_params = [] @@ -564,29 +736,50 @@ async def get_file_cabinets_async( query_params.append(f"FileCabinetType={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("FileCabinets", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_document_information_async( + def get_document_information( self, file_cabinet_id: str, document_id: int, @@ -600,6 +793,24 @@ async def get_document_information_async( Get document information Gets information about a document. + + Swagger operation ID: `GetDocumentInformation`. + + Args: + file_cabinet_id: Select the File Cabinet or Document Tray with your + document. + document_id: Specify the ID of the document you want information + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -609,7 +820,7 @@ async def get_document_information_async( f"/{quote(str(document_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -623,6 +834,7 @@ async def get_document_information_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -630,7 +842,7 @@ async def get_document_information_async( return json.loads(response.text) - async def delete_document_async( + def delete_document( self, file_cabinet_id: str, document_id: int, @@ -644,6 +856,23 @@ async def delete_document_async( Delete a document Deletes a document from a file cabinet or document tray. + + Swagger operation ID: `DeleteDocument`. + + Args: + file_cabinet_id: Select the File Cabinet or Document Tray with your + document. + document_id: Specify the ID of the document you want to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -653,7 +882,7 @@ async def delete_document_async( f"/{quote(str(document_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -667,9 +896,10 @@ async def delete_document_async( request_url, response.status, response.text, + response=response, ) - async def download_file_async( + def download_file( self, file_cabinet_id: str, document_id: int, @@ -686,6 +916,27 @@ async def download_file_async( Downloads a file/section of a document stored in a file cabinet or document tray. + + Swagger operation ID: `DownloadFile`. + + Args: + file_cabinet_id: Select the File Cabinet or Document Tray with your + document. + document_id: Specify the ID of the document with the file you want + to download. + file_number: Specify the file number of the file you want to + download. + document_format: Select the format for the downloaded document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -705,7 +956,7 @@ async def download_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -719,11 +970,12 @@ async def download_file_async( request_url, response.status, response.text, + response=response, ) return response.content - async def download_document_async( + def download_document( self, file_cabinet_id: str, document_id: int, @@ -738,6 +990,24 @@ async def download_document_async( Download a document Downloads a document from a file cabinet or document tray. + + Swagger operation ID: `DownloadDocument`. + + Args: + file_cabinet_id: Select the File Cabinet or Document Tray with your + document. + document_id: Specify the ID of the document you want to download. + document_format: Select the format for the downloaded document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -755,7 +1025,7 @@ async def download_document_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -769,11 +1039,12 @@ async def download_document_async( request_url, response.status, response.text, + response=response, ) return response.content - async def update_index_fields_async( + def update_index_fields( self, input: UpdateIndexFieldsInput, file_cabinet_id: str, @@ -788,6 +1059,24 @@ async def update_index_fields_async( Update index fields Updates the index fields of a document. + + Swagger operation ID: `UpdateIndexFields`. + + Args: + input: The request body. + file_cabinet_id: Select the File Cabinet with the document to + update. + document_id: Specify the ID of the document to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -798,7 +1087,7 @@ async def update_index_fields_async( f"/Fields" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -812,6 +1101,7 @@ async def update_index_fields_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -819,12 +1109,12 @@ async def update_index_fields_async( return json.loads(response.text) - async def transfer_document_async( + def transfer_document( self, - input: TransferDocumentInput, + input: TransferDocumentInput | Mapping[str, Any], destination_file_cabinet_id: str, - store_dialog_id: Optional[str] = None, *, + store_dialog_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -835,6 +1125,26 @@ async def transfer_document_async( Moves one or more documents from one file cabinet/document tray to another. + + Swagger operation ID: `TransferDocument`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + destination_file_cabinet_id: Select the destination File Cabinet or + Document Tray. + store_dialog_id: Select the store dialog for indexing the documents + being moved. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -852,7 +1162,7 @@ async def transfer_document_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -866,6 +1176,7 @@ async def transfer_document_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -873,9 +1184,9 @@ async def transfer_document_async( return json.loads(response.text) - async def place_a_stamp_async( + def place_a_stamp( self, - input: PlaceAStampInput, + input: PlaceAStampInput | Mapping[str, Any], file_cabinet_id: str, document_id: int, *, @@ -888,6 +1199,25 @@ async def place_a_stamp_async( Place a stamp Places a stamp on a document. + + Swagger operation ID: `PlaceAStamp`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + file_cabinet_id: Select the File Cabinet or Document Tray with your + document. + document_id: Specify the ID of the document you want to stamp. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -898,7 +1228,7 @@ async def place_a_stamp_async( f"/Annotation" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -912,6 +1242,7 @@ async def place_a_stamp_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -919,20 +1250,41 @@ async def place_a_stamp_async( return json.loads(response.text) - async def get_dialogs_async( + def list_dialogs( self, file_cabinet: str, - dialog_type: Optional[str] = None, *, + dialog_type: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get dialogs Gets a list of dialogs for a file cabinet or document tray. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetDialogs`. + + Args: + file_cabinet: Select the File Cabinet or Document Tray to get + dialogs from. + dialog_type: Select the type of dialogs to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -946,29 +1298,50 @@ async def get_dialogs_async( query_params.append(f"DialogType={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("Dialogs", []): + yield item - async def get_stamps_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_stamps( self, file_cabinet: str, *, @@ -976,39 +1349,80 @@ async def get_stamps_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get stamps Gets a list of stamps for a file cabinet or document tray. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetStamps`. + + Args: + file_cabinet: Select the File Cabinet or Document Tray to get + stamps from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/FileCabinets/{quote(str(file_cabinet), safe='')}/Stamps" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("Stamps", []): + yield item + + return None, items() - async def get_stamp_fields_async( + return ItemPaged(get_next, extract_data) + + def list_stamp_fields( self, file_cabinet: str, stamp: str, @@ -1017,11 +1431,32 @@ async def get_stamp_fields_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get stamp fields Gets a list of fields for a stamp. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetStampFields`. + + Args: + file_cabinet: Select the File Cabinet or Document Tray with the + desired stamp. + stamp: Select the stamp to get its fields. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1031,42 +1466,83 @@ async def get_stamp_fields_async( f"/{quote(str(stamp), safe='')}" f"/Fields" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("Fields", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_file_cabinet_fields_async( + def list_file_cabinet_fields( self, file_cabinet: str, - field_type: Optional[str] = None, *, + field_type: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get file cabinet fields Gets a list of fields for a file cabinet. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetFileCabinetFields`. + + Args: + file_cabinet: Select the File Cabinet to get fields for. + field_type: Select the type of fields to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1080,29 +1556,50 @@ async def get_file_cabinet_fields_async( query_params.append(f"FieldType={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("Fields", []): + yield item + + return None, items() - async def get_dialog_fields_async( + return ItemPaged(get_next, extract_data) + + def list_dialog_fields( self, file_cabinet: str, dialog_id: str, @@ -1111,11 +1608,31 @@ async def get_dialog_fields_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get dialog fields Gets the fields for a dialog + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetDialogFields`. + + Args: + file_cabinet: Select the File Cabinet. + dialog_id: Select the dialog to get the fields for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1125,29 +1642,50 @@ async def get_dialog_fields_async( f"/{quote(str(dialog_id), safe='')}" f"/Fields" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("Fields", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def list_documents_in_document_tray_async( + def list_documents_in_document_tray( self, document_tray: str, *, @@ -1155,34 +1693,74 @@ async def list_documents_in_document_tray_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List documents in document tray List documents from the specified document tray. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListDocumentsInDocumentTray`. + + Args: + document_tray: Select the Document Tray to search. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/DocumentTrays/{quote(str(document_tray), safe='')}/Search" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("Documents", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/dropbox.py b/src/azure/connectors/dropbox.py index d7d8540..7fda1d7 100644 --- a/src/azure/connectors/dropbox.py +++ b/src/azure/connectors/dropbox.py @@ -5,21 +5,34 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "DropboxClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "BlobMetadataPage", + "BlobMetadataResponse", + "DataSetsMetadata", + "ObjectEntity", + "TabularDataSetsMetadata", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,41 +42,66 @@ class BlobMetadata: Response for Get file metadata """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The filelocator of the file or folder.""" @@ -75,8 +113,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -85,25 +133,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -115,15 +167,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -135,7 +189,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -148,41 +202,66 @@ class BlobMetadataResponse: Definition: BlobMetadataResponse """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The filelocator of the file or folder.""" @@ -194,7 +273,12 @@ class BlobMetadataPage: Definition: BlobMetadataPage """ - value: Optional[List[BlobMetadata]] = None + value: Optional[ + List[BlobMetadata | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Blob metadata collection.""" @@ -206,16 +290,16 @@ class DropboxClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -226,8 +310,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -235,8 +319,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -248,7 +332,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -263,7 +347,46 @@ def __init__( def connector_name(self) -> str: return "dropbox" - async def get_file_metadata_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def get_file_metadata( self, id: str, *, @@ -276,6 +399,21 @@ async def get_file_metadata_async( Get file metadata This operation gets the metadata for a file. + + Swagger operation ID: `GetFileMetadata`. + + Args: + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -285,7 +423,7 @@ async def get_file_metadata_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -299,6 +437,7 @@ async def get_file_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -306,7 +445,7 @@ async def get_file_metadata_async( return json.loads(response.text) - async def update_file_async( + def update_file( self, input: bytes, id: str, @@ -320,6 +459,22 @@ async def update_file_async( Update file This operation updates a file. + + Swagger operation ID: `UpdateFile`. + + Args: + input: The binary request body. + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -329,7 +484,7 @@ async def update_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, @@ -346,6 +501,7 @@ async def update_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -353,7 +509,7 @@ async def update_file_async( return json.loads(response.text) - async def delete_file_async( + def delete_file( self, id: str, *, @@ -366,6 +522,21 @@ async def delete_file_async( Delete file This operation deletes a file. + + Swagger operation ID: `DeleteFile`. + + Args: + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -375,7 +546,7 @@ async def delete_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -389,9 +560,10 @@ async def delete_file_async( request_url, response.status, response.text, + response=response, ) - async def get_file_metadata_by_path_async( + def get_file_metadata_by_path( self, path: str, *, @@ -404,6 +576,21 @@ async def get_file_metadata_by_path_async( Get file metadata using path This operation gets the metadata of a file using the path. + + Swagger operation ID: `GetFileMetadataByPath`. + + Args: + path: The unique path of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/GetFileByPath" @@ -417,7 +604,7 @@ async def get_file_metadata_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -431,6 +618,7 @@ async def get_file_metadata_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -438,11 +626,11 @@ async def get_file_metadata_by_path_async( return json.loads(response.text) - async def get_file_content_by_path_async( + def get_file_content_by_path( self, path: str, - infer_content_type: Optional[bool] = None, *, + infer_content_type: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -452,6 +640,23 @@ async def get_file_content_by_path_async( Get file content using path This operation gets the content of a file using the path. + + Swagger operation ID: `GetFileContentByPath`. + + Args: + path: The unique path of the file. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -471,7 +676,7 @@ async def get_file_content_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -485,15 +690,16 @@ async def get_file_content_by_path_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_file_content_async( + def get_file_content( self, id: str, - infer_content_type: Optional[bool] = None, *, + infer_content_type: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -503,6 +709,23 @@ async def get_file_content_async( Get file content This operation gets the content of a file. + + Swagger operation ID: `GetFileContent`. + + Args: + id: The unique identifier of the file. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -521,7 +744,7 @@ async def get_file_content_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -535,11 +758,12 @@ async def get_file_content_async( request_url, response.status, response.text, + response=response, ) return response.content - async def create_file_async( + def create_file( self, input: bytes, folder_path: str, @@ -554,6 +778,23 @@ async def create_file_async( Create file This operation creates a file in a folder. + + Swagger operation ID: `CreateFile`. + + Args: + input: The binary request body. + folder_path: The path to the folder. + name: The name of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/datasets/default/files" query_params = [] @@ -569,7 +810,7 @@ async def create_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -586,6 +827,7 @@ async def create_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -593,12 +835,12 @@ async def create_file_async( return json.loads(response.text) - async def copy_file_async( + def copy_file( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -608,6 +850,23 @@ async def copy_file_async( Copy file This operation copies a file to Dropbox. + + Swagger operation ID: `CopyFile`. + + Args: + source: The url to source file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/copyFile" @@ -630,7 +889,7 @@ async def copy_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -644,6 +903,7 @@ async def copy_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -651,7 +911,7 @@ async def copy_file_async( return json.loads(response.text) - async def list_folder_async( + def list_folder( self, id: str, *, @@ -659,11 +919,30 @@ async def list_folder_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List files in folder This operation gets the list of files and subfolders in a folder. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListFolder`. + + Args: + id: The unique identifier of the folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -672,73 +951,133 @@ async def list_folder_async( f"/folders" f"/{quote(quote(str(id), safe=''), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def list_root_folder_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_root_folder( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List files in root folder This operation gets the list of files and subfolders in the root folder. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListRootFolder`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/folders" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def extract_folder_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def extract_folder( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -748,6 +1087,23 @@ async def extract_folder_async( Extract archive to folder This operation extracts an archive file into a folder (example: .zip). + + Swagger operation ID: `ExtractFolderV2`. + + Args: + source: The path to the archive file. + destination: The path to extract the archive contents. + overwrite: Overwrites the destination files if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/extractFolderV2" @@ -770,7 +1126,7 @@ async def extract_folder_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -784,6 +1140,7 @@ async def extract_folder_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/dynamicsax.py b/src/azure/connectors/dynamicsax.py index 736bae8..e9e12d5 100644 --- a/src/azure/connectors/dynamicsax.py +++ b/src/azure/connectors/dynamicsax.py @@ -5,21 +5,61 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "DynamicsaxClient", + "AxOnlineProcedureResult", + "BlobDataSetsMetadata", + "BusinessEventData", + "BusinessEventSubscription", + "BusinessEventSubscriptionResponse", + "BusinessEventsList", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "ExecuteProcedureInput", + "ExportableItem", + "ExportableItemsList", + "GetItemResponse", + "Item", + "ItemsList", + "ObjectEntity", + "PassThroughNativeQuery", + "PatchItemInput", + "PatchItemResponse", + "PostItemInput", + "PostItemResponse", + "Procedure", + "ProcedureMetadata", + "ProceduresList", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TablesList", + "TabularDataSetsMetadata", + "TriggerFieldData", + "TriggerFieldDataList", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,17 +69,19 @@ class BusinessEventSubscriptionResponse: Response for When a Business Event occurs """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id of the subscription""" - resource: Optional[str] = None + resource: Optional[str] = dataclass_field(default=None, kw_only=True) """Resource of the subscription request""" - notification_type: Optional[str] = field( + notification_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notificationType"}, ) """Notification Type""" - notification_url: Optional[str] = field( + notification_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notificationUrl"}, ) """Notification Url""" @@ -51,7 +93,7 @@ class ExecuteProcedureInput: Execute action """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -64,10 +106,11 @@ class AxOnlineProcedureResult: Response for Execute action """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Output parameter values""" - output_parameters: Optional[Dict[str, ObjectEntity]] = field( + output_parameters: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OutputParameters"}, ) """Output parameter values""" @@ -79,10 +122,16 @@ class ItemsList: Response for Lists items present in table """ - value: Optional[List[Item]] = None + value: Optional[ + List[Item | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Items""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -94,7 +143,7 @@ class PostItemInput: Create record """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -107,7 +156,7 @@ class PostItemResponse: Response for Create record """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -120,7 +169,7 @@ class GetItemResponse: Response for Get a record """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -133,7 +182,7 @@ class PatchItemInput: Update a record """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -146,7 +195,7 @@ class PatchItemResponse: Response for Update a record """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -159,7 +208,12 @@ class TablesList: Response for Get list of entities """ - value: Optional[List[Table]] = None + value: Optional[ + List[Table | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Tables""" @@ -169,7 +223,12 @@ class DataSetsList: Response for Get instances """ - value: Optional[List[DataSet]] = None + value: Optional[ + List[DataSet | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of datasets""" @@ -179,7 +238,12 @@ class TriggerFieldDataList: Response for Gets business events categories """ - value: Optional[List[TriggerFieldData]] = None + value: Optional[ + List[TriggerFieldData | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of business event categories""" @@ -189,7 +253,12 @@ class BusinessEventsList: Response for Gets business events """ - value: Optional[List[BusinessEventData]] = None + value: Optional[ + List[BusinessEventData | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of business events""" @@ -199,7 +268,12 @@ class ProceduresList: Response for Get actions """ - value: Optional[List[Procedure]] = None + value: Optional[ + List[Procedure | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Procedures""" @@ -209,11 +283,11 @@ class ProcedureMetadata: Response for Get actions metadata """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Procedure name""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Procedure title""" - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -222,26 +296,30 @@ class TableMetadata: Response for Get entity metadata """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Table name""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Table title""" - x_ms_permission: Optional[str] = field( + x_ms_permission: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-permission"}, ) """Table permission""" - x_ms_capabilities: Optional[TableCapabilitiesMetadata] = field( + x_ms_capabilities: Optional[TableCapabilitiesMetadata | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-capabilities"}, ) - schema: Optional[ObjectEntity] = None - referenced_entities: Optional[ObjectEntity] = field( + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + referenced_entities: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "referencedEntities"}, ) - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webUrl"}, ) """Url link""" @@ -253,7 +331,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -266,8 +344,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -276,25 +364,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -306,15 +398,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -326,30 +420,42 @@ class TableCapabilitiesMetadata: Definition: TableCapabilitiesMetadata """ - sort_restrictions: Optional[TableSortRestrictionsMetadata] = field( + sort_restrictions: Optional[ + TableSortRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sortRestrictions"}, ) - filter_restrictions: Optional[TableFilterRestrictionsMetadata] = field( + filter_restrictions: Optional[ + TableFilterRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterRestrictions"}, ) - select_restrictions: Optional[TableSelectRestrictionsMetadata] = field( + select_restrictions: Optional[ + TableSelectRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selectRestrictions"}, ) - is_only_server_pagable: Optional[bool] = field( + is_only_server_pagable: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isOnlyServerPagable"}, ) """Server paging restrictions""" - filter_function_support: Optional[List[str]] = field( + filter_function_support: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterFunctionSupport"}, ) """List of supported filter capabilities""" - server_paging_options: Optional[List[str]] = field( + server_paging_options: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "serverPagingOptions"}, ) """List of supported server-driven paging capabilities""" @@ -361,15 +467,17 @@ class TableSortRestrictionsMetadata: Definition: TableSortRestrictionsMetadata """ - sortable: Optional[bool] = None + sortable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has sortable columns""" - unsortable_properties: Optional[List[str]] = field( + unsortable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "unsortableProperties"}, ) """List of unsortable properties""" - ascending_only_properties: Optional[List[str]] = field( + ascending_only_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ascendingOnlyProperties"}, ) """List of properties which support ascending order only""" @@ -381,15 +489,17 @@ class TableFilterRestrictionsMetadata: Definition: TableFilterRestrictionsMetadata """ - filterable: Optional[bool] = None + filterable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has filterable columns""" - non_filterable_properties: Optional[List[str]] = field( + non_filterable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nonFilterableProperties"}, ) """List of non filterable properties""" - required_properties: Optional[List[str]] = field( + required_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredProperties"}, ) """List of required properties""" @@ -401,7 +511,7 @@ class TableSelectRestrictionsMetadata: Definition: TableSelectRestrictionsMetadata """ - selectable: Optional[bool] = None + selectable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has selectable columns""" @@ -411,8 +521,7 @@ class BusinessEventSubscription: Definition: BusinessEventSubscription """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "NotificationUrl"}, ) """ @@ -427,12 +536,21 @@ class BusinessEventData: Definition: BusinessEventData """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Business event Id""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Business event data name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Business event data display name""" @@ -444,10 +562,15 @@ class TriggerFieldData: Definition: TriggerFieldData """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Business event data name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Business event data display name""" @@ -459,10 +582,15 @@ class Procedure: Definition: Procedure """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Procedure name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Procedure display name""" @@ -474,14 +602,24 @@ class DataSet: Definition: DataSet """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Dataset name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Dataset display name""" - query: Optional[List[PassThroughNativeQuery]] = None + query: Optional[ + List[PassThroughNativeQuery | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Pass-through Native Queries""" @@ -491,15 +629,21 @@ class Table: Definition: Table """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the table. The name is used at runtime.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the table.""" - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DynamicProperties"}, ) """Additional table properties provided by the connector to the clients.""" @@ -511,8 +655,9 @@ class PassThroughNativeQuery: Definition: PassThroughNativeQuery """ - language: Optional[str] = field( + language: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Language"}, ) """Query language""" @@ -524,8 +669,9 @@ class Item: Definition: Item """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) @@ -536,7 +682,12 @@ class ExportableItemsList: Definition: ExportableItemsList """ - value: Optional[List[ExportableItem]] = None + value: Optional[ + List[ExportableItem | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Items.""" @@ -546,8 +697,9 @@ class ExportableItem: Definition: ExportableItem """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) @@ -560,16 +712,16 @@ class DynamicsaxClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -580,8 +732,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -589,8 +741,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -602,7 +754,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -624,7 +776,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -656,9 +808,9 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def execute_procedure_async( + def execute_procedure( self, - input: ExecuteProcedureInput, + input: ExecuteProcedureInput | Mapping[str, Any], dataset: str, procedure: str, *, @@ -671,6 +823,24 @@ async def execute_procedure_async( Execute action Execute action + + Swagger operation ID: `ExecuteProcedure`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: The Dynamics 365 for Fin & Ops instance. + procedure: Name of action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -680,7 +850,7 @@ async def execute_procedure_async( f"/{quote(quote(str(procedure), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -694,6 +864,7 @@ async def execute_procedure_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -701,10 +872,11 @@ async def execute_procedure_async( return json.loads(response.text) - async def get_items_async( + def list_items( self, dataset: str, table: str, + *, apply: Optional[str] = None, filter: Optional[str] = None, orderby: Optional[str] = None, @@ -712,19 +884,44 @@ async def get_items_async( skip: Optional[int] = None, select: Optional[str] = None, cross_company: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Lists items present in table Lists items present in table - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItems`. + + Args: + dataset: The Dynamics 365 for Fin & Ops instance. + table: Entity name. + apply: A sequence of OData aggregation transformations. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + cross_company: Query across companies (default = no). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -772,11 +969,18 @@ async def get_items_async( query_params.append(f"cross-company={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -789,25 +993,34 @@ async def get_items_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def post_item_async( + return ItemPaged(get_next, extract_data) + + def post_item( self, - input: PostItemInput, + input: PostItemInput | Mapping[str, Any], dataset: str, table: str, *, @@ -820,6 +1033,24 @@ async def post_item_async( Create record Create a new record in an entity + + Swagger operation ID: `PostItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: The Dynamics 365 for Fin & Ops instance. + table: Entity name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -830,7 +1061,7 @@ async def post_item_async( f"/items" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -844,6 +1075,7 @@ async def post_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -851,7 +1083,7 @@ async def post_item_async( return json.loads(response.text) - async def get_item_async( + def get_item( self, dataset: str, table: str, @@ -866,6 +1098,23 @@ async def get_item_async( Get a record Retrieves a single record + + Swagger operation ID: `GetItem`. + + Args: + dataset: The Dynamics 365 for Fin & Ops instance. + table: Entity name. + id: Unique identifier of the object to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -877,7 +1126,7 @@ async def get_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -891,6 +1140,7 @@ async def get_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -898,7 +1148,7 @@ async def get_item_async( return json.loads(response.text) - async def delete_item_async( + def delete_item( self, dataset: str, table: str, @@ -913,6 +1163,23 @@ async def delete_item_async( Delete record Deletes a single record in an entity + + Swagger operation ID: `DeleteItem`. + + Args: + dataset: The Dynamics 365 for Fin & Ops instance. + table: Entity name. + id: Unique identifier of the object to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -924,7 +1191,7 @@ async def delete_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -938,11 +1205,12 @@ async def delete_item_async( request_url, response.status, response.text, + response=response, ) - async def patch_item_async( + def patch_item( self, - input: PatchItemInput, + input: PatchItemInput | Mapping[str, Any], dataset: str, table: str, id: str, @@ -956,6 +1224,25 @@ async def patch_item_async( Update a record Updates a single record in an entity + + Swagger operation ID: `PatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: The Dynamics 365 for Fin & Ops instance. + table: Entity name. + id: Unique identifier of the object to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -967,7 +1254,7 @@ async def patch_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -981,6 +1268,7 @@ async def patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -988,7 +1276,7 @@ async def patch_item_async( return json.loads(response.text) - async def get_tables_async( + def list_tables( self, dataset: str, *, @@ -996,75 +1284,154 @@ async def get_tables_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get list of entities Retrieves a list of entities + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTables`. + + Args: + dataset: The Dynamics 365 for Fin & Ops instance. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/datasets/{quote(quote(str(dataset), safe=''), safe='')}/tables" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_data_sets_async( + def list_data_sets( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get instances Retrieves a list of accessable Dynamics 365 for Fin & Ops instances + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetDataSets`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/datasets" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - async def get_business_event_categories_async( + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_business_event_categories( self, dataset: str, *, @@ -1072,11 +1439,30 @@ async def get_business_event_categories_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Gets business events categories Gets business events categories. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetBusinessEventCategories`. + + Args: + dataset: Data set. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1084,29 +1470,50 @@ async def get_business_event_categories_async( f"/{quote(quote(str(dataset), safe=''), safe='')}" f"/businesseventcategories" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_business_events_async( + def list_business_events( self, dataset: str, businesseventcategory: str, @@ -1115,11 +1522,31 @@ async def get_business_events_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Gets business events Gets business events. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetBusinessEvents`. + + Args: + dataset: Data set. + businesseventcategory: Business event category. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1129,29 +1556,50 @@ async def get_business_events_async( f"/{quote(quote(str(businesseventcategory), safe=''), safe='')}" f"/businessevents" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def get_legal_entities_async( + return ItemPaged(get_next, extract_data) + + def list_legal_entities( self, dataset: str, businesseventcategory: str, @@ -1161,11 +1609,32 @@ async def get_legal_entities_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Gets legal entities Gets legal entities. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetLegalEntities`. + + Args: + dataset: Data set. + businesseventcategory: Business event category. + businessevent: Business event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1184,29 +1653,50 @@ async def get_legal_entities_async( query_params.append(f"businessevent={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_procedures_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_procedures( self, dataset: str, *, @@ -1214,11 +1704,30 @@ async def get_procedures_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get actions Get actions + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetProcedures`. + + Args: + dataset: The Dynamics 365 for Fin & Ops instance. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1226,29 +1735,50 @@ async def get_procedures_async( f"/{quote(quote(str(dataset), safe=''), safe='')}" f"/procedures" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - async def get_procedure_async( + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_procedure( self, dataset: str, procedure: str, @@ -1262,6 +1792,22 @@ async def get_procedure_async( Get actions metadata Get actions metadata. + + Swagger operation ID: `GetProcedure`. + + Args: + dataset: The Dynamics 365 for Fin & Ops instance. + procedure: Name of action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1272,7 +1818,7 @@ async def get_procedure_async( f"/{quote(quote(str(procedure), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1286,6 +1832,7 @@ async def get_procedure_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1293,7 +1840,7 @@ async def get_procedure_async( return json.loads(response.text) - async def get_table_async( + def get_table( self, dataset: str, table: str, @@ -1307,6 +1854,22 @@ async def get_table_async( Get entity metadata Retrieves metadata for an entity + + Swagger operation ID: `GetTable`. + + Args: + dataset: The Dynamics 365 for Fin & Ops instance. + table: Entity name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1317,7 +1880,7 @@ async def get_table_async( f"/{quote(quote(str(table), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1331,6 +1894,7 @@ async def get_table_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/elfsquaddata.py b/src/azure/connectors/elfsquaddata.py index 2d78b78..8f07abd 100644 --- a/src/azure/connectors/elfsquaddata.py +++ b/src/azure/connectors/elfsquaddata.py @@ -5,21 +5,35 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "ElfsquaddataClient", + "CreateTriggerInput", + "GetEntitiesResponse", + "GetEntityByIdResponse", + "InvokeFunctionInput", + "InvokeFunctionResponse", + "PostEntityByIdInput", + "PostEntityByIdResponse", + "PutEntityByIdInput", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,10 +43,7 @@ class CreateTriggerInput: Custom trigger """ - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) @dataclass @@ -41,9 +52,10 @@ class GetEntitiesResponse: Response for Get entities """ - value: Optional[List[Any]] = None - next_link: Optional[str] = field( + value: Optional[List[Any]] = dataclass_field(default=None, kw_only=True) + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """Link to get next page of results""" @@ -55,7 +67,7 @@ class PostEntityByIdInput: Create entity """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -68,7 +80,7 @@ class PostEntityByIdResponse: Response for Create entity """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -81,7 +93,7 @@ class GetEntityByIdResponse: Response for Get entity by id """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -94,7 +106,7 @@ class PutEntityByIdInput: Update entity """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -107,7 +119,7 @@ class InvokeFunctionInput: Invoke function """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -120,7 +132,7 @@ class InvokeFunctionResponse: Response for Invoke function """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -135,16 +147,16 @@ class ElfsquaddataClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -155,8 +167,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -164,8 +176,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -177,7 +189,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -199,7 +211,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -231,9 +243,10 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def get_entities_async( + def list_entities( self, entity_name: str, + *, top: Optional[int] = None, skip: Optional[int] = None, orderby: Optional[str] = None, @@ -241,19 +254,41 @@ async def get_entities_async( select: Optional[str] = None, expand: Optional[str] = None, count: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get entities Get entities - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `get_entities`. + + Args: + entity_name: Entity name. + top: Top. + skip: Skip. + orderby: Order by. + filter: Filter items. + select: Select properties. + expand: Expand. + count: Count. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -297,11 +332,18 @@ async def get_entities_async( query_params.append(f"$count={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -314,25 +356,34 @@ async def get_entities_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def post_entity_by_id_async( + return ItemPaged(get_next, extract_data) + + def post_entity_by_id( self, - input: PostEntityByIdInput, + input: PostEntityByIdInput | Mapping[str, Any], entity_name: str, *, timeout: Optional[float] = None, @@ -344,13 +395,30 @@ async def post_entity_by_id_async( Create entity Create entity + + Swagger operation ID: `post_entity_by_id`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entity_name: Entity name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/data/1/{quote(str(entity_name), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -364,6 +432,7 @@ async def post_entity_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -371,7 +440,7 @@ async def post_entity_by_id_async( return json.loads(response.text) - async def get_entity_by_id_async( + def get_entity_by_id( self, entity_name: str, id: str, @@ -385,6 +454,22 @@ async def get_entity_by_id_async( Get entity by id Get entity by id + + Swagger operation ID: `get_entity_by_id`. + + Args: + entity_name: Entity name. + id: Identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -393,7 +478,7 @@ async def get_entity_by_id_async( f"/{quote(str(entity_name), safe='')}({quote(str(id), safe='')})" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -407,6 +492,7 @@ async def get_entity_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -414,7 +500,7 @@ async def get_entity_by_id_async( return json.loads(response.text) - async def delete_entity_by_id_async( + def delete_entity_by_id( self, entity_name: str, id: str, @@ -428,6 +514,22 @@ async def delete_entity_by_id_async( Delete entity Delete entity + + Swagger operation ID: `delete_entity_by_id`. + + Args: + entity_name: Entity name. + id: Identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -436,7 +538,7 @@ async def delete_entity_by_id_async( f"/{quote(str(entity_name), safe='')}({quote(str(id), safe='')})" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -450,11 +552,12 @@ async def delete_entity_by_id_async( request_url, response.status, response.text, + response=response, ) - async def put_entity_by_id_async( + def put_entity_by_id( self, - input: PutEntityByIdInput, + input: PutEntityByIdInput | Mapping[str, Any], entity_name: str, id: str, *, @@ -467,6 +570,24 @@ async def put_entity_by_id_async( Update entity Update entity + + Swagger operation ID: `put_entity_by_id`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entity_name: Entity name. + id: Identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -475,7 +596,7 @@ async def put_entity_by_id_async( f"/{quote(str(entity_name), safe='')}({quote(str(id), safe='')})" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -489,11 +610,12 @@ async def put_entity_by_id_async( request_url, response.status, response.text, + response=response, ) - async def invoke_function_async( + def invoke_function( self, - input: InvokeFunctionInput, + input: InvokeFunctionInput | Mapping[str, Any], function_path: str, *, timeout: Optional[float] = None, @@ -505,13 +627,30 @@ async def invoke_function_async( Invoke function Invoke function + + Swagger operation ID: `invoke_function`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + function_path: Function path. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/{quote(str(function_path), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -525,6 +664,7 @@ async def invoke_function_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -532,7 +672,7 @@ async def invoke_function_async( return json.loads(response.text) - async def get_triggers_async( + def get_triggers( self, *, timeout: Optional[float] = None, @@ -542,10 +682,24 @@ async def get_triggers_async( ) -> None: """ Get triggers + + Swagger operation ID: `get_triggers`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/data/1/$triggers" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -559,9 +713,10 @@ async def get_triggers_async( request_url, response.status, response.text, + response=response, ) - async def get_schemas_async( + def get_schemas( self, *, timeout: Optional[float] = None, @@ -571,10 +726,24 @@ async def get_schemas_async( ) -> None: """ Get schemas + + Swagger operation ID: `get_schemas`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/data/1" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -588,9 +757,10 @@ async def get_schemas_async( request_url, response.status, response.text, + response=response, ) - async def get_schema_async( + def get_schema( self, entity_name: str, *, @@ -601,13 +771,28 @@ async def get_schema_async( ) -> None: """ Get schema + + Swagger operation ID: `get_schema`. + + Args: + entity_name: entity_name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/data/1/{quote(str(entity_name), safe='')}/$schema" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -621,9 +806,10 @@ async def get_schema_async( request_url, response.status, response.text, + response=response, ) - async def get_functions_async( + def get_functions( self, *, timeout: Optional[float] = None, @@ -633,10 +819,24 @@ async def get_functions_async( ) -> None: """ Get function + + Swagger operation ID: `get_functions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/data/1/$functions" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -650,9 +850,10 @@ async def get_functions_async( request_url, response.status, response.text, + response=response, ) - async def get_function_definition_async( + def get_function_definition( self, function_path: str, *, @@ -663,13 +864,28 @@ async def get_function_definition_async( ) -> None: """ Get function definition + + Swagger operation ID: `get_function_definition`. + + Args: + function_path: function_path. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/data/1/$functions/$schema/{quote(str(function_path), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -683,9 +899,10 @@ async def get_function_definition_async( request_url, response.status, response.text, + response=response, ) - async def get_trigger_schema_async( + def get_trigger_schema( self, trigger_name: str, *, @@ -696,13 +913,28 @@ async def get_trigger_schema_async( ) -> None: """ Get trigger schema + + Swagger operation ID: `get_trigger_schema`. + + Args: + trigger_name: trigger_name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/data/1/$triggers/{quote(str(trigger_name), safe='')}/$schema" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -716,6 +948,7 @@ async def get_trigger_schema_async( request_url, response.status, response.text, + response=response, ) diff --git a/src/azure/connectors/etsy.py b/src/azure/connectors/etsy.py index dcacd41..2dca2f5 100644 --- a/src/azure/connectors/etsy.py +++ b/src/azure/connectors/etsy.py @@ -5,14 +5,13 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, List, Literal, Any, Mapping from urllib.parse import quote import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, @@ -20,6 +19,114 @@ ConnectorResponseHook, ) +__all__ = [ + "EtsyClient", + "ApplicationListingsInventoryRequest", + "ApplicationShopsListingsVariationImagesRequest", + "Channel", + "DestinationRegion", + "DestinationRegion1", + "ErrorSchema", + "Include", + "Includes", + "Includes1", + "ItemDimensionsUnit", + "ItemDimensionsUnit2", + "ItemWeightUnit", + "ItemWeightUnit2", + "ListingCreateInput", + "ListingCreateTranslationInput", + "ListingImage", + "ListingImages", + "ListingInventory", + "ListingInventoryProduct", + "ListingInventoryProductOffering", + "ListingInventoryWithAssociations", + "ListingPropertyValue", + "ListingPropertyValues", + "ListingTranslation", + "ListingUpdateInput", + "ListingUpdateInventoryInput", + "ListingUpdatePropertyInput", + "ListingUpdateTranslationInput", + "ListingUpdateVariationInput", + "ListingUploadImageInput", + "ListingUploadInput", + "ListingVariationImage", + "ListingVariationImages", + "Money", + "Occasion", + "Offering", + "Payment", + "PaymentAccountLedgerEntries", + "PaymentAccountLedgerEntry", + "PaymentAdjustment", + "Payments", + "Pong", + "ProcessingTimeUnit", + "Product", + "ProfileType", + "PropertyValue", + "ReceiptCreateShipmentInput", + "Recipient", + "SellerTaxonomyNode", + "SellerTaxonomyNodes", + "ShippingCarrier", + "ShippingCarrierMailClass", + "ShippingCarriers", + "ShippingCreateDestinationInput", + "ShippingCreateProfileInput", + "ShippingCreateUpgradeInput", + "ShippingUpdateProfileDestinationInput", + "ShippingUpdateProfileInput", + "ShippingUpdateProfileUpgradeInput", + "Shop", + "ShopCreateSectionInput", + "ShopListing", + "ShopListingFile", + "ShopListingFiles", + "ShopListingWithAssociations", + "ShopListings", + "ShopListingsWithAssociations", + "ShopProductionPartner", + "ShopProductionPartners", + "ShopReceipt", + "ShopReceiptShipment", + "ShopReceiptTransaction", + "ShopReceiptTransactions", + "ShopReceipts", + "ShopSection", + "ShopSections", + "ShopShippingProfile", + "ShopShippingProfileDestination", + "ShopShippingProfileDestinations", + "ShopShippingProfileUpgrade", + "ShopShippingProfileUpgrades", + "ShopShippingProfiles", + "ShopUpdateInput", + "Shops", + "SortOn", + "SortOrder", + "State", + "State2", + "TaxonomyNodeProperties", + "TaxonomyNodeProperty", + "TaxonomyPropertyScale", + "TaxonomyPropertyValue", + "TransactionReview", + "TransactionReviews", + "Type", + "Type1", + "User", + "UserAddress", + "UserAddresses", + "VariationImage", + "WhenMade", + "WhenMade2", + "WhoMade", + "WhoMade2", +] + # Type Definitions @@ -29,7 +136,7 @@ class Pong: Response for Ping """ - application_id: Optional[int] = None + application_id: int """The authenticated application's ID""" @@ -39,9 +146,9 @@ class PaymentAccountLedgerEntries: Response for Get a shop payment account ledger's entries """ - count: Optional[int] = None + count: int """The number of payment account ledger entry resources found.""" - results: Optional[List[PaymentAccountLedgerEntry]] = None + results: List[PaymentAccountLedgerEntry | Mapping[str, Any]] """The payment account ledger entry resources found.""" @@ -51,9 +158,9 @@ class Payments: Response for Get a payment from a payment account ledger entry ID """ - count: Optional[int] = None + count: int """The number of payments in the response.""" - results: Optional[List[Payment]] = None + results: List[Payment | Mapping[str, Any]] """A list of payments.""" @@ -63,52 +170,52 @@ class ShopReceipt: Response for Get a receipt """ - receipt_id: Optional[int] = None + receipt_id: int """The numeric ID for the receipt associated to this transaction.""" - receipt_type: Optional[int] = None + receipt_type: int """ The numeric value for the Etsy channel that serviced the purchase: 0 for Etsy.com, 1 for a Pattern shop. """ - seller_user_id: Optional[int] = None + seller_user_id: int """The numeric ID for the user (seller) fulfilling the purchase.""" - seller_email: Optional[str] = None + seller_email: str """The email address string for the seller of the listing.""" - buyer_user_id: Optional[int] = None + buyer_user_id: int """The numeric ID for the user making the purchase.""" - buyer_email: Optional[str] = None + buyer_email: str """The email address string for the buyer of the listing.""" - name: Optional[str] = None + name: str """The name string for the recipient in the shipping address.""" - first_line: Optional[str] = None + first_line: str """ The first address line string for the recipient in the shipping address. """ - second_line: Optional[str] = None + second_line: str """ The optional second address line string for the recipient in the shipping address. """ - city: Optional[str] = None + city: str """The city string for the recipient in the shipping address.""" - state: Optional[str] = None + state: str """The state string for the recipient in the shipping address.""" - zip: Optional[str] = None + zip: str """ The zip code string (not necessarily a number) for the recipient in the shipping address. """ - formatted_address: Optional[str] = None + formatted_address: str """ The formatted shipping address string for the recipient in the shipping address. """ - country_iso: Optional[str] = None + country_iso: str """ The ISO-3166 alpha-2 country code string for the recipient in the shipping address. """ - payment_method: Optional[str] = None + payment_method: str """ The payment method string identifying purchaser's payment method, which must be one of: 'cc' (credit card), 'paypal', 'check', 'mo' (money order), @@ -116,36 +223,36 @@ class ShopReceipt: 'android_pay', 'google_pay', 'klarna', 'k_pay_in_4' (klarna), or 'k_financing' (klarna). """ - payment_email: Optional[str] = None + payment_email: str """ The email address string for the email address to which to send payment confirmation """ - message_from_seller: Optional[str] = None + message_from_seller: str """An optional message string from the seller.""" - message_from_buyer: Optional[str] = None + message_from_buyer: str """An optional message string from the buyer.""" - message_from_payment: Optional[str] = None + message_from_payment: str """The machine-generated acknowledgement string from the payment system.""" - is_paid: Optional[bool] = None + is_paid: bool """When true, buyer paid for this purchase.""" - is_shipped: Optional[bool] = None + is_shipped: bool """When true, seller shipped the products.""" - create_timestamp: Optional[int] = None + create_timestamp: int """The receipt's creation time, in epoch seconds.""" - update_timestamp: Optional[int] = None + update_timestamp: int """The time of the last update to the receipt, in epoch seconds.""" - gift_message: Optional[str] = None + gift_message: str """A gift message string the buyer requests delivered with the product.""" - grandtotal: Optional[Money] = None - subtotal: Optional[Money] = None - total_price: Optional[Money] = None - total_shipping_cost: Optional[Money] = None - total_tax_cost: Optional[Money] = None - total_vat_cost: Optional[Money] = None - discount_amt: Optional[Money] = None - gift_wrap_price: Optional[Money] = None - shipments: Optional[List[ShopReceiptShipment]] = None + grandtotal: Money | Mapping[str, Any] + subtotal: Money | Mapping[str, Any] + total_price: Money | Mapping[str, Any] + total_shipping_cost: Money | Mapping[str, Any] + total_tax_cost: Money | Mapping[str, Any] + total_vat_cost: Money | Mapping[str, Any] + discount_amt: Money | Mapping[str, Any] + gift_wrap_price: Money | Mapping[str, Any] + shipments: List[ShopReceiptShipment | Mapping[str, Any]] """A list of shipment statements for this receipt.""" @@ -155,9 +262,9 @@ class ShopReceipts: Response for Get receipts """ - count: Optional[int] = None + count: int """The number of Shop Receipts found.""" - results: Optional[List[ShopReceipt]] = None + results: List[ShopReceipt | Mapping[str, Any]] """ List of Shop Receipt resources found, with all Shop Receipt fields for each resource. @@ -170,11 +277,11 @@ class ReceiptCreateShipmentInput: Create a Shipment Receipt """ - tracking_code: Optional[str] = None + tracking_code: Optional[str] = dataclass_field(default=None, kw_only=True) """The tracking code for this receipt.""" - carrier_name: Optional[str] = None + carrier_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The carrier name for this receipt.""" - send_bcc: Optional[bool] = None + send_bcc: Optional[bool] = dataclass_field(default=None, kw_only=True) """If true, the shipping notification will be sent to the seller as well""" @@ -184,9 +291,9 @@ class ShopReceiptTransactions: Response for Retrieve a listing's transactions """ - count: Optional[int] = None + count: int """The number of shop receipt transaction resources found.""" - results: Optional[List[ShopReceiptTransaction]] = None + results: List[ShopReceiptTransaction | Mapping[str, Any]] """The shop receipt transaction resources found.""" @@ -196,42 +303,42 @@ class ShopReceiptTransaction: Response for Get a transaction """ - transaction_id: Optional[int] = None + transaction_id: int """The unique numeric ID for a transaction.""" - title: Optional[str] = None + title: str """The title string of the listing purchased in this transaction.""" - description: Optional[str] = None + description: str """The description string of the listing purchased in this transaction.""" - seller_user_id: Optional[int] = None + seller_user_id: int """The numeric user ID for the seller in this transaction.""" - buyer_user_id: Optional[int] = None + buyer_user_id: int """The numeric user ID for the buyer in this transaction.""" - create_timestamp: Optional[int] = None + create_timestamp: int """The transaction's creation date and time, in epoch seconds.""" - paid_timestamp: Optional[int] = None + paid_timestamp: int """The transaction's paid date and time, in epoch seconds.""" - shipped_timestamp: Optional[int] = None + shipped_timestamp: int """The transaction's shipping date and time, in epoch seconds.""" - quantity: Optional[int] = None + quantity: int """The numeric quantity of products purchased in this transaction.""" - listing_image_id: Optional[int] = None + listing_image_id: int """The numeric ID of the primary listing image for this transaction.""" - receipt_id: Optional[int] = None + receipt_id: int """The numeric ID for the receipt associated to this transaction.""" - is_digital: Optional[bool] = None + is_digital: bool """ When true, the transaction recorded the purchase of a digital listing. """ - file_data: Optional[str] = None + file_data: str """A string describing the files purchased in this transaction.""" - listing_id: Optional[int] = None + listing_id: int """The numeric ID for the listing associated to this transaction.""" - transaction_type: Optional[str] = None + transaction_type: str """The type string for the transaction, usually listing""" - product_id: Optional[int] = None + product_id: int """The numeric ID for a specific product purchased from a listing.""" - price: Optional[Money] = None - shipping_cost: Optional[Money] = None + price: Money | Mapping[str, Any] + shipping_cost: Money | Mapping[str, Any] @dataclass @@ -240,9 +347,9 @@ class TransactionReviews: Response for Get reviews """ - count: Optional[int] = None + count: int """The number of TransactionReview resources found.""" - results: Optional[List[TransactionReview]] = None + results: List[TransactionReview | Mapping[str, Any]] """The TransactionReview resources found.""" @@ -252,8 +359,8 @@ class ShippingCarriers: Response for Get shipping carriers """ - count: Optional[int] = None - results: Optional[List[ShippingCarrier]] = None + count: int + results: List[ShippingCarrier | Mapping[str, Any]] @dataclass @@ -262,37 +369,37 @@ class ShopShippingProfile: Response for Get shipping profiles """ - shipping_profile_id: Optional[int] = None + shipping_profile_id: int """The numeric ID of the shipping profile.""" - title: Optional[str] = None + title: str """The name string of this shipping profile.""" - user_id: Optional[int] = None + user_id: int """The numeric ID for the user who owns the shipping profile.""" - min_processing_days: Optional[int] = None + min_processing_days: int """The minimum number of days for processing the listing.""" - max_processing_days: Optional[int] = None + max_processing_days: int """The maximum number of days for processing the listing.""" - processing_days_display_label: Optional[str] = None + processing_days_display_label: str """Translated display label string for processing days.""" - origin_country_iso: Optional[str] = None + origin_country_iso: str """The ISO code of the country from which the listing ships.""" - is_deleted: Optional[bool] = None + is_deleted: bool """When true, someone deleted this shipping profile.""" - shipping_profile_destinations: Optional[List[ShopShippingProfileDestination]] = None + shipping_profile_destinations: List[ShopShippingProfileDestination | Mapping[str, Any]] """ A list of shipping profile destinations available for this shipping profile. """ - shipping_profile_upgrades: Optional[List[ShopShippingProfileUpgrade]] = None + shipping_profile_upgrades: List[ShopShippingProfileUpgrade | Mapping[str, Any]] """ A list of shipping profile upgrades available for this shipping profile. """ - origin_postal_code: Optional[str] = None + origin_postal_code: str """ The postal code string (not necessarily a number) for the location from which the listing ships. """ - profile_type: Optional[ProfileType] = None + profile_type: Optional[ProfileType] = dataclass_field(default=None, kw_only=True) @dataclass @@ -301,38 +408,38 @@ class ShippingCreateProfileInput: Create a shipping profile """ - title: Optional[str] = None + title: str """The name string of this shipping profile.""" - origin_country_iso: Optional[str] = None + origin_country_iso: str """The ISO code of the country from which the listing ships.""" - primary_cost: Optional[float] = None + primary_cost: float """ The cost of shipping to this country/region alone, measured in the store's default currency. """ - secondary_cost: Optional[float] = None + secondary_cost: float """ The cost of shipping to this country/region with another item, measured in the store's default currency. """ - min_processing_time: Optional[int] = None + min_processing_time: int """ The minimum time required to process to ship listings with this shipping profile. """ - max_processing_time: Optional[int] = None + max_processing_time: int """The maximum processing time the listing needs to ship.""" - processing_time_unit: Optional[str] = None + processing_time_unit: Optional[str] = dataclass_field(default=None, kw_only=True) """ The unit used to represent how long a processing time is. A week is equivalent to 5 business days. """ - destination_country_iso: Optional[str] = None + destination_country_iso: Optional[str] = dataclass_field(default=None, kw_only=True) """ The ISO code of the country to which the listing ships. If null, request sets destination to destination region. """ - destination_region: Optional[str] = None + destination_region: Optional[str] = dataclass_field(default=None, kw_only=True) """ The code of the region to which the listing ships. A region represents a set of countries. Supported regions are Europe Union and Non-Europe Union @@ -340,27 +447,27 @@ class ShippingCreateProfileInput: destination country ISO, or everywhere if destination country ISO is also null. """ - origin_postal_code: Optional[str] = None + origin_postal_code: Optional[str] = dataclass_field(default=None, kw_only=True) """ The postal code string (not necessarily a number) for the location from which the listing ships. """ - shipping_carrier_id: Optional[int] = None + shipping_carrier_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ The unique ID of a supported shipping carrier, which is used to calculate an estimated delivery date. """ - mail_class: Optional[str] = None + mail_class: Optional[str] = dataclass_field(default=None, kw_only=True) """ The unique ID string of a shipping carrier's mail class, which is used to calculate an estimated delivery date. """ - min_delivery_days: Optional[int] = None + min_delivery_days: Optional[int] = dataclass_field(default=None, kw_only=True) """ The minimum number of business days a buyer can expect to wait to receive their purchased item once it has shipped. """ - max_delivery_days: Optional[int] = None + max_delivery_days: Optional[int] = dataclass_field(default=None, kw_only=True) """ The maximum number of business days a buyer can expect to wait to receive their purchased item once it has shipped. @@ -373,24 +480,24 @@ class ShippingUpdateProfileInput: Update a shipping profile """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The name string of this shipping profile.""" - origin_country_iso: Optional[str] = None + origin_country_iso: Optional[str] = dataclass_field(default=None, kw_only=True) """The ISO code of the country from which the listing ships.""" - min_processing_time: Optional[int] = None + min_processing_time: Optional[int] = dataclass_field(default=None, kw_only=True) """ The minimum time required to process to ship listings with this shipping profile. """ - max_processing_time: Optional[int] = None + max_processing_time: Optional[int] = dataclass_field(default=None, kw_only=True) """The maximum processing time the listing needs to ship.""" - processing_time_unit: Optional[str] = None + processing_time_unit: Optional[str] = dataclass_field(default=None, kw_only=True) """ The unit used to represent how long a processing time is. A week is equivalent to 5 business days. If none is provided, the unit is set to business_days. """ - origin_postal_code: Optional[str] = None + origin_postal_code: Optional[str] = dataclass_field(default=None, kw_only=True) """ The postal code string (not necessarily a number) for the location from which the listing ships. @@ -403,9 +510,9 @@ class ShopShippingProfileDestinations: Response for Get profile destinations by shipping profile """ - count: Optional[int] = None + count: int """The number of results.""" - results: Optional[List[ShopShippingProfileDestination]] = None + results: List[ShopShippingProfileDestination | Mapping[str, Any]] """The list of requested resources.""" @@ -415,27 +522,27 @@ class ShippingCreateDestinationInput: Create a shipping profile destination """ - primary_cost: Optional[float] = None + primary_cost: float """ The cost of shipping to this country/region alone, measured in the store's default currency. """ - secondary_cost: Optional[str] = None + secondary_cost: str """ The cost of shipping to this country/region with another item, measured in the store's default currency. """ - destination_country_iso: Optional[str] = None + destination_country_iso: Optional[str] = dataclass_field(default=None, kw_only=True) """destination_country_iso""" - destination_region: Optional[str] = None + destination_region: Optional[str] = dataclass_field(default=None, kw_only=True) """destination_region""" - shipping_carrier_id: Optional[int] = None + shipping_carrier_id: Optional[int] = dataclass_field(default=None, kw_only=True) """shipping_carrier_id""" - mail_class: Optional[str] = None + mail_class: Optional[str] = dataclass_field(default=None, kw_only=True) """mail_class""" - min_delivery_days: Optional[int] = None + min_delivery_days: Optional[int] = dataclass_field(default=None, kw_only=True) """min_delivery_days""" - max_delivery_days: Optional[int] = None + max_delivery_days: Optional[int] = dataclass_field(default=None, kw_only=True) """max_delivery_days""" @@ -445,39 +552,39 @@ class ShopShippingProfileDestination: Response for Create a shipping profile destination """ - shipping_profile_destination_id: Optional[int] = None + shipping_profile_destination_id: int """ The numeric ID of the shipping profile destination in the shipping profile associated with the listing. """ - shipping_profile_id: Optional[int] = None + shipping_profile_id: int """The numeric ID of the shipping profile.""" - origin_country_iso: Optional[str] = None + origin_country_iso: str """The ISO code of the country from which the listing ships.""" - destination_country_iso: Optional[str] = None + destination_country_iso: str """ The ISO code of the country to which the listing ships. If null, request sets destination to destination_region """ - destination_region: Optional[DestinationRegion] = None - primary_cost: Optional[Money] = None - secondary_cost: Optional[Money] = None - shipping_carrier_id: Optional[int] = None + destination_region: DestinationRegion + primary_cost: Money | Mapping[str, Any] + secondary_cost: Money | Mapping[str, Any] + shipping_carrier_id: int """ The unique ID of a supported shipping carrier, which is used to calculate an Estimated Delivery Date. """ - mail_class: Optional[str] = None + mail_class: str """ The unique ID string of a shipping carrier's mail class, which is used to calculate an estimated delivery date. """ - min_delivery_days: Optional[int] = None + min_delivery_days: int """ The minimum number of business days a buyer can expect to wait to receive their purchased item once it has shipped. """ - max_delivery_days: Optional[int] = None + max_delivery_days: int """ The maximum number of business days a buyer can expect to wait to receive their purchased item once it has shipped. @@ -490,21 +597,21 @@ class ShippingUpdateProfileDestinationInput: Update a shipping profile destination """ - primary_cost: Optional[str] = None + primary_cost: Optional[str] = dataclass_field(default=None, kw_only=True) """primary_cost""" - secondary_cost: Optional[str] = None + secondary_cost: Optional[str] = dataclass_field(default=None, kw_only=True) """secondary_cost""" - destination_country_iso: Optional[str] = None + destination_country_iso: Optional[str] = dataclass_field(default=None, kw_only=True) """destination_country_iso""" - destination_region: Optional[str] = None + destination_region: Optional[str] = dataclass_field(default=None, kw_only=True) """destination_region""" - shipping_carrier_id: Optional[int] = None + shipping_carrier_id: Optional[int] = dataclass_field(default=None, kw_only=True) """shipping_carrier_id""" - mail_class: Optional[str] = None + mail_class: Optional[str] = dataclass_field(default=None, kw_only=True) """mail_class""" - min_delivery_days: Optional[int] = None + min_delivery_days: Optional[int] = dataclass_field(default=None, kw_only=True) """min_delivery_days""" - max_delivery_days: Optional[int] = None + max_delivery_days: Optional[int] = dataclass_field(default=None, kw_only=True) """max_delivery_days""" @@ -514,9 +621,9 @@ class ShopShippingProfileUpgrades: Response for Get shipping profile upgrades """ - count: Optional[int] = None + count: int """The number of results.""" - results: Optional[List[ShopShippingProfileUpgrade]] = None + results: List[ShopShippingProfileUpgrade | Mapping[str, Any]] """The list of requested resources.""" @@ -526,32 +633,32 @@ class ShippingCreateUpgradeInput: Create a shipping profile upgrade """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """The type of the shipping upgrade. Domestic (0) or international (1).""" - upgrade_name: Optional[str] = None + upgrade_name: str """ Name for the shipping upgrade shown to shoppers at checkout, e.g. USPS Priority. """ - price: Optional[float] = None + price: float """Additional cost of adding the shipping upgrade.""" - secondary_price: Optional[float] = None + secondary_price: float """ Additional cost of adding the shipping upgrade for each additional item. """ - shipping_carrier_id: Optional[int] = None + shipping_carrier_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ The unique ID of a supported shipping carrier, which is used to calculate an Estimated Delivery Date. """ - mail_class: Optional[str] = None + mail_class: Optional[str] = dataclass_field(default=None, kw_only=True) """ The unique ID string of a shipping carrier's mail class, which is used to calculate an estimated delivery date. """ - min_delivery_days: Optional[int] = None + min_delivery_days: Optional[int] = dataclass_field(default=None, kw_only=True) """min_delivery_days""" - max_delivery_days: Optional[int] = None + max_delivery_days: Optional[int] = dataclass_field(default=None, kw_only=True) """ The maximum number of business days a buyer can expect to wait to receive their purchased item once it has shipped. @@ -564,45 +671,45 @@ class ShopShippingProfileUpgrade: Response for Create a shipping profile upgrade """ - shipping_profile_id: Optional[int] = None + shipping_profile_id: int """The numeric ID of the base shipping profile.""" - upgrade_id: Optional[int] = None + upgrade_id: int """The numeric ID that is associated with a shipping upgrade""" - upgrade_name: Optional[str] = None + upgrade_name: str """ Name for the shipping upgrade shown to shoppers at checkout, e.g. USPS Priority. """ - type_: Optional[Type] = field(default=None, metadata={"wire_name": "type"}) - rank: Optional[int] = None + type_: Type = dataclass_field(metadata={"wire_name": "type"}) + rank: int """ The positive non-zero numeric position in the images displayed in a listing, with rank 1 images appearing in the left-most position in a listing. """ - language: Optional[str] = None + language: str """ The IETF language tag for the language of the shipping profile. Ex: de, en, es, fr, it, ja, nl, pl, pt, ru. """ - price: Optional[Money] = None - secondary_price: Optional[Money] = None - shipping_carrier_id: Optional[int] = None + price: Money | Mapping[str, Any] + secondary_price: Money | Mapping[str, Any] + shipping_carrier_id: int """ The unique ID of a supported shipping carrier, which is used to calculate an Estimated Delivery Date. """ - mail_class: Optional[str] = None + mail_class: str """ The unique ID string of a shipping carrier's mail class, which is used to calculate an estimated delivery date. """ - min_delivery_days: Optional[int] = None + min_delivery_days: int """ The minimum number of business days a buyer can expect to wait to receive their purchased item once it has shipped. """ - max_delivery_days: Optional[int] = None + max_delivery_days: int """ The maximum number of business days a buyer can expect to wait to receive their purchased item once it has shipped. @@ -615,32 +722,36 @@ class ShippingUpdateProfileUpgradeInput: Update a shipping profile upgrade """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type of the shipping upgrade. Domestic (0) or international (1).""" - upgrade_name: Optional[str] = None + upgrade_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name for the shipping upgrade shown to shoppers at checkout, e.g. USPS Priority. """ - price: Optional[float] = None + price: Optional[float] = dataclass_field(default=None, kw_only=True) """Additional cost of adding the shipping upgrade.""" - secondary_price: Optional[float] = None + secondary_price: Optional[float] = dataclass_field(default=None, kw_only=True) """ Additional cost of adding the shipping upgrade for each additional item. """ - shipping_carrier_id: Optional[int] = None + shipping_carrier_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ The unique ID of a supported shipping carrier, which is used to calculate an Estimated Delivery Date. """ - mail_class: Optional[str] = None + mail_class: Optional[str] = dataclass_field(default=None, kw_only=True) """ The unique ID string of a shipping carrier's mail class, which is used to calculate an estimated delivery date. """ - min_delivery_days: Optional[int] = None + min_delivery_days: Optional[int] = dataclass_field(default=None, kw_only=True) """min_delivery_days""" - max_delivery_days: Optional[int] = None + max_delivery_days: Optional[int] = dataclass_field(default=None, kw_only=True) """ The maximum number of business days a buyer can expect to wait to receive their purchased item once it has shipped. @@ -653,17 +764,17 @@ class ShopUpdateInput: Update a shop """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """A brief heading string for the shop's main page.""" - announcement: Optional[str] = None + announcement: Optional[str] = dataclass_field(default=None, kw_only=True) """ An announcement string to buyers that displays on the shop's homepage. """ - sale_message: Optional[str] = None + sale_message: Optional[str] = dataclass_field(default=None, kw_only=True) """ A message string sent to users who complete a purchase from this shop. """ - digital_sale_message: Optional[str] = None + digital_sale_message: Optional[str] = dataclass_field(default=None, kw_only=True) """ A message string sent to users who purchase a digital item from this shop. """ @@ -675,120 +786,119 @@ class Shop: Response for Update a shop """ - shop_id: Optional[int] = None + shop_id: int """The unique positive non-zero numeric ID for an Etsy Shop.""" - user_id: Optional[int] = None + user_id: int """The numeric user ID of the user who owns this shop.""" - shop_name: Optional[str] = None + shop_name: str """The shop's name string.""" - create_date: Optional[int] = None + create_date: int """The date and time this shop was created, in epoch seconds.""" - title: Optional[str] = None + title: str """A brief heading string for the shop's main page.""" - announcement: Optional[str] = None + announcement: str """ An announcement string to buyers that displays on the shop's homepage. """ - currency_code: Optional[str] = None + currency_code: str """ The ISO (alphabetic) code for the shop's currency. The shop displays all prices in this currency by default. """ - is_vacation: Optional[bool] = None + is_vacation: bool """When true, this shop is not accepting purchases.""" - vacation_message: Optional[str] = None + vacation_message: str """The shop's message string displayed when is_vacation is true.""" - sale_message: Optional[str] = None + sale_message: str """ A message string sent to users who complete a purchase from this shop. """ - digital_sale_message: Optional[str] = None + digital_sale_message: str """ A message string sent to users who purchase a digital item from this shop. """ - update_date: Optional[int] = None + update_date: int """The date and time of the last update to the shop, in epoch seconds.""" - listing_active_count: Optional[int] = None + listing_active_count: int """The number of active listings in the shop.""" - digital_listing_count: Optional[int] = None + digital_listing_count: int """The number of digital listings in the shop.""" - login_name: Optional[str] = None + login_name: str """The shop owner's login name string.""" - accepts_custom_requests: Optional[bool] = None + accepts_custom_requests: bool """When true, the shop accepts customization requests.""" - policy_welcome: Optional[str] = None + policy_welcome: str """The shop's policy welcome string (may be blank).""" - policy_payment: Optional[str] = None + policy_payment: str """The shop's payment policy string (may be blank).""" - policy_shipping: Optional[str] = None + policy_shipping: str """The shop's shipping policy string (may be blank).""" - policy_refunds: Optional[str] = None + policy_refunds: str """The shop's refund policy string (may be blank).""" - policy_additional: Optional[str] = None + policy_additional: str """The shop's additional policies string (may be blank).""" - policy_seller_info: Optional[str] = None + policy_seller_info: str """The shop's seller infomation string (may be blank).""" - policy_update_date: Optional[int] = None + policy_update_date: int """ The date and time of the last update to the shop's policies, in epoch seconds. """ - policy_has_private_receipt_info: Optional[bool] = None + policy_has_private_receipt_info: bool """When true, EU receipts display private info.""" - has_unstructured_policies: Optional[bool] = None + has_unstructured_policies: bool """When true, the shop displays additional unstructured policy fields.""" - policy_privacy: Optional[str] = None + policy_privacy: str """The shop's privacy policy string (may be blank).""" - vacation_autoreply: Optional[str] = None + vacation_autoreply: str """ The shop's automatic reply string displayed in new conversations when is_vacation is true. """ - url: Optional[str] = None + url: str """The URL string for this shop.""" - image_url760x100: Optional[str] = field( - default=None, + image_url760x100: str = dataclass_field( metadata={"wire_name": "image_url_760x100"}, ) """The URL string for this shop's banner image.""" - num_favorers: Optional[int] = None + num_favorers: int """The number of users who marked this shop a favorite.""" - languages: Optional[List[str]] = None + languages: List[str] """A list of language strings for the shop's enrolled languages.""" - icon_url_fullxfull: Optional[str] = None + icon_url_fullxfull: str """The URL string for this shop's icon image.""" - is_using_structured_policies: Optional[bool] = None + is_using_structured_policies: bool """When true, the shop accepted using structured policies.""" - has_onboarded_structured_policies: Optional[bool] = None + has_onboarded_structured_policies: bool """ When true, the shop accepted OR declined after viewing structured policies onboarding. """ - include_dispute_form_link: Optional[bool] = None + include_dispute_form_link: bool """ When true, this shop's policies include a link to an EU online dispute form. """ - is_direct_checkout_onboarded: Optional[bool] = None + is_direct_checkout_onboarded: bool """When true, the shop has onboarded onto Etsy Payments.""" - is_calculated_eligible: Optional[bool] = None + is_calculated_eligible: bool """ When true, the shop is elegible for calculated shipping profiles. (Only available in the US and Canada) """ - is_opted_in_to_buyer_promise: Optional[bool] = None + is_opted_in_to_buyer_promise: bool """When true, the shop opted in to buyer promise.""" - is_shop_us_based: Optional[bool] = None + is_shop_us_based: bool """When true, the shop is based in the US.""" - transaction_sold_count: Optional[int] = None + transaction_sold_count: int """The total number of sales transactions for this shop""" - shipping_from_country_iso: Optional[str] = None + shipping_from_country_iso: str """The country iso the shop is shipping from.""" - shop_location_country_iso: Optional[str] = None + shop_location_country_iso: str """The country iso where the shop is located.""" - review_count: Optional[int] = None + review_count: int """Number of reviews of shop listings in the past year.""" - review_average: Optional[float] = None + review_average: float """Average rating based on reviews of shop listings in the past year.""" @@ -798,9 +908,9 @@ class Shops: Response for Search shops """ - count: Optional[int] = None + count: int """The total number of Shops""" - results: Optional[List[Shop]] = None + results: List[Shop | Mapping[str, Any]] """The Shop resources.""" @@ -810,9 +920,9 @@ class ShopSections: Response for Get shop sections """ - count: Optional[int] = None + count: int """The number of results.""" - results: Optional[List[ShopSection]] = None + results: List[ShopSection | Mapping[str, Any]] """The list of requested resources.""" @@ -822,7 +932,7 @@ class ShopCreateSectionInput: Create a shop section """ - title: Optional[str] = None + title: str """The title string for a shop section.""" @@ -832,18 +942,18 @@ class ShopSection: Response for Create a shop section """ - shop_section_id: Optional[int] = None + shop_section_id: int """The numeric ID of a section in a specific Etsy shop.""" - title: Optional[str] = None + title: str """The title string for a shop section.""" - rank: Optional[int] = None + rank: int """ The positive non-zero numeric position of this section in the section display order for a shop, with rank 1 sections appearing first. """ - user_id: Optional[int] = None + user_id: int """The numeric ID of the user who owns this shop section.""" - active_listing_count: Optional[int] = None + active_listing_count: int """The number of active listings in one section of a specific Etsy shop.""" @@ -853,38 +963,38 @@ class User: Response for Get user """ - user_id: Optional[int] = None + user_id: int """ The numeric ID of a user. This number is also a valid shop ID for the user's shop. """ - login_name: Optional[str] = None + login_name: str """The user's login name string.""" - primary_email: Optional[str] = None + primary_email: str """An email address string for the user's primary email address.""" - first_name: Optional[str] = None + first_name: str """The user's first name.""" - last_name: Optional[str] = None + last_name: str """The user's last name.""" - create_timestamp: Optional[int] = None + create_timestamp: int """The date and time the user created their account, in epoch seconds.""" - referred_by_user_id: Optional[int] = None + referred_by_user_id: int """The numeric ID of the user who referred this user.""" - use_new_inventory_endpoints: Optional[bool] = None + use_new_inventory_endpoints: bool """Deprecated. Always true.""" - is_seller: Optional[bool] = None + is_seller: bool """True if the user is seller.""" - bio: Optional[str] = None + bio: str """The user's biography.""" - gender: Optional[str] = None + gender: str """The user's gender.""" - birth_month: Optional[str] = None + birth_month: str """The user's month of birth.""" - birth_day: Optional[str] = None + birth_day: str """The user's day of birth.""" - transaction_buy_count: Optional[int] = None + transaction_buy_count: int """The number of transactions where the user has bought.""" - transaction_sold_count: Optional[int] = None + transaction_sold_count: int """The number of transactions where the user has sold.""" @@ -894,27 +1004,27 @@ class UserAddress: Response for Get user's address """ - user_address_id: Optional[int] = None + user_address_id: int """The numeric ID of the user's address.""" - user_id: Optional[int] = None + user_id: int """The user's numeric ID.""" - name: Optional[str] = None + name: str """The user's name for this address.""" - first_line: Optional[str] = None + first_line: str """The first line of the user's address.""" - second_line: Optional[str] = None + second_line: str """The second line of the user's address.""" - city: Optional[str] = None + city: str """The city field of the user's address.""" - state: Optional[str] = None + state: str """The state field of the user's address.""" - zip: Optional[str] = None + zip: str """The zip code field of the user's address.""" - iso_country_code: Optional[str] = None + iso_country_code: str """The ISO code of the country in this address.""" - country_name: Optional[str] = None + country_name: str """The name of the user's country.""" - is_default_shipping_address: Optional[bool] = None + is_default_shipping_address: bool """Is this the user's default shipping address.""" @@ -924,9 +1034,9 @@ class UserAddresses: Response for Get user addresses """ - count: Optional[int] = None + count: int """The number of UserAddress records being returned.""" - results: Optional[List[UserAddress]] = None + results: List[UserAddress | Mapping[str, Any]] """An array of UserAddress resources.""" @@ -936,9 +1046,9 @@ class SellerTaxonomyNodes: Response for Get seller taxonomy nodes """ - count: Optional[int] = None + count: int """The number of results.""" - results: Optional[List[SellerTaxonomyNode]] = None + results: List[SellerTaxonomyNode | Mapping[str, Any]] """The list of requested resources.""" @@ -948,9 +1058,9 @@ class TaxonomyNodeProperties: Response for Get product properties by taxonomy ID """ - count: Optional[int] = None + count: int """The number of results.""" - results: Optional[List[TaxonomyNodeProperty]] = None + results: List[TaxonomyNodeProperty | Mapping[str, Any]] """The list of requested resources.""" @@ -960,9 +1070,9 @@ class ShopListings: Response for Get listings by shop """ - count: Optional[int] = None + count: int """The number of shop listing resources found.""" - results: Optional[List[ShopListing]] = None + results: List[ShopListing | Mapping[str, Any]] """The shop listing resources found.""" @@ -972,126 +1082,126 @@ class ListingCreateInput: Create a draft listing """ - quantity: Optional[int] = None + quantity: int """ The positive non-zero number of products available for purchase in the listing. """ - title: Optional[str] = None + title: str """ The listing's title string. Valid title strings contain only letters, numbers, punctuation marks, mathematical symbols, whitespace characters, ™, ©, and ®. (regex: /[^\\p{L}\\p{Nd}\\p{P}\\p{Sm}\\p{Zs}™©®]/u) You can only use the %, :, & and + characters once each. """ - description: Optional[str] = None + description: str """A description string of the product for sale in the listing.""" - price: Optional[float] = None + price: float """ The positive non-zero price of the product. (Sold product listings are private) Note: The price is the minimum possible price. """ - who_made: Optional[str] = None + who_made: str """ An string inidcated who made the product. Helps buyers locate the listing under the Handmade heading. Requires 'is_supply' and 'when_made'. """ - when_made: Optional[str] = None + when_made: Optional[str] = dataclass_field(default=None, kw_only=True) """ A string for the era in which the maker made the product in this listing. Helps buyers locate the listing under the Vintage heading. Requires 'is_supply' and 'who_made'. """ - taxonomy_id: Optional[int] = None + taxonomy_id: int """ The numeric taxonomy ID of the listing. The seller manages listing taxonomy IDs for their shop. """ - shipping_profile_id: Optional[int] = None + shipping_profile_id: int """The numeric ID of the shipping profile associated with the listing.""" - materials: Optional[str] = None + materials: Optional[str] = dataclass_field(default=None, kw_only=True) """ A array of material strings for materials used in the product. Valid materials strings contain only letters, numbers, and whitespace characters. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}]/u) """ - shop_section_id: Optional[int] = None + shop_section_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numeric ID of the shop section for this listing.""" - processing_min: Optional[int] = None + processing_min: Optional[int] = dataclass_field(default=None, kw_only=True) """The minimum number of days required to process this listing.""" - processing_max: Optional[int] = None + processing_max: Optional[int] = dataclass_field(default=None, kw_only=True) """The maximum number of days required to process this listing.""" - tags: Optional[str] = None + tags: Optional[str] = dataclass_field(default=None, kw_only=True) """ An array of tag strings for the listing. Valid tag strings contain only letters, numbers, whitespace characters, -, ', ™, ©, and ®. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}-'™©®]/u) """ - recipient: Optional[str] = None + recipient: Optional[str] = dataclass_field(default=None, kw_only=True) """ A string indicating a person for whom this product would make an appropriate gift. """ - occasion: Optional[str] = None + occasion: Optional[str] = dataclass_field(default=None, kw_only=True) """ A string indicating an occassion for which this product would make an appropriate gift. """ - styles: Optional[str] = None + styles: Optional[str] = dataclass_field(default=None, kw_only=True) """ An array of style strings for this listing, each of which is free-form text string such as Formal, or Steampunk. A Listing may have up to two styles. Valid style strings contain only letters, numbers, and whitespace characters. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}]/u) """ - item_weight: Optional[float] = None + item_weight: Optional[float] = dataclass_field(default=None, kw_only=True) """ The numeric weight of the product measured in units set in item weight unit. """ - item_length: Optional[int] = None + item_length: Optional[int] = dataclass_field(default=None, kw_only=True) """ The numeric length of the product measured in units set in item dimensions unit. """ - item_width: Optional[float] = None + item_width: Optional[float] = dataclass_field(default=None, kw_only=True) """ The numeric width of the product measured in units set in 'item dimensions unit'. """ - item_height: Optional[float] = None + item_height: Optional[float] = dataclass_field(default=None, kw_only=True) """ The numeric height of the product measured in units set in 'item dimensions unit'. """ - item_weight_unit: Optional[str] = None + item_weight_unit: Optional[str] = dataclass_field(default=None, kw_only=True) """ A string defining the units used to measure the weight of the product. """ - item_dimensions_unit: Optional[str] = None + item_dimensions_unit: Optional[str] = dataclass_field(default=None, kw_only=True) """ A string defining the units used to measure the dimensions of the product. """ - is_personalizable: Optional[bool] = None + is_personalizable: Optional[bool] = dataclass_field(default=None, kw_only=True) """When true, this listing is personalizable.""" - image_ids: Optional[str] = None + image_ids: Optional[str] = dataclass_field(default=None, kw_only=True) """ An array of numeric image IDs of the images in a listing, which can include up to 10 images. """ - is_supply: Optional[bool] = None + is_supply: Optional[bool] = dataclass_field(default=None, kw_only=True) """ When true, tags the listing as a supply product, else indicates that it's a finished product. Helps buyers locate the listing under the Supplies heading. Requires 'who made' and 'when made'. """ - is_customizable: Optional[bool] = None + is_customizable: Optional[bool] = dataclass_field(default=None, kw_only=True) """ When true, a buyer may contact the seller for a customized order. The default value is true when a shop accepts custom orders. Does not apply to shops that do not accept custom orders. """ - is_taxable: Optional[bool] = None + is_taxable: Optional[bool] = dataclass_field(default=None, kw_only=True) """ When true, applicable shop tax rates apply to this listing at checkout. """ @@ -1103,146 +1213,146 @@ class ShopListing: Response for Create a draft listing """ - listing_id: Optional[int] = None + listing_id: int """The numeric ID for the listing associated to this transaction.""" - user_id: Optional[int] = None + user_id: int """The numeric ID for the user posting the listing.""" - shop_id: Optional[int] = None + shop_id: int """The unique positive non-zero numeric ID for an Etsy Shop.""" - title: Optional[str] = None + title: str """ The listing's title string. Valid title strings contain only letters, numbers, punctuation marks, mathematical symbols, whitespace characters, ™, ©, and ®. (regex: /[^\\\\p{L}\\\\p{Nd}\\\\p{P}\\\\p{Sm}\\\\p{Zs}™©®]/u) You can only use the %, :, & and + characters once each. """ - description: Optional[str] = None + description: str """A description string of the product for sale in the listing.""" - state: Optional[State] = None - creation_timestamp: Optional[int] = None + state: State + creation_timestamp: int """The listing's creation time, in epoch seconds.""" - ending_timestamp: Optional[int] = None + ending_timestamp: int """The listing's expiration time, in epoch seconds.""" - original_creation_timestamp: Optional[int] = None + original_creation_timestamp: int """The listing's creation time, in epoch seconds.""" - last_modified_timestamp: Optional[int] = None + last_modified_timestamp: int """The time of the last update to the listing, in epoch seconds.""" - state_timestamp: Optional[int] = None + state_timestamp: int """The date and time of the last state change of this listing.""" - quantity: Optional[int] = None + quantity: int """ The positive non-zero number of products available for purchase in the listing. Note: The listing quantity is the sum of available offering quantities. You can request the quantities for individual offerings from the ListingInventory resource using the get listing inventory endpoint. """ - shop_section_id: Optional[int] = None + shop_section_id: int """The numeric ID of a section in a specific Etsy shop.""" - featured_rank: Optional[int] = None + featured_rank: int """ The positive non-zero numeric position in the featured listings of the shop, with rank 1 listings appearing in the left-most position in featured listing on a shop's home page. """ - url: Optional[str] = None + url: str """The full URL to the listing's page on Etsy.""" - num_favorers: Optional[int] = None + num_favorers: int """The number of users who marked this listing a favorite.""" - non_taxable: Optional[bool] = None + non_taxable: bool """ When true, applicable shop tax rates do not apply to this listing at checkout. """ - is_customizable: Optional[bool] = None + is_customizable: bool """ When true, a buyer may contact the seller for a customized order. The default value is true when a shop accepts custom orders. Does not apply to shops that do not accept custom orders. """ - is_personalizable: Optional[bool] = None + is_personalizable: bool """When true, this listing is personalizable. The default value is null.""" - personalization_is_required: Optional[bool] = None + personalization_is_required: bool """ When true, this listing requires personalization. The default value is null. """ - personalization_char_count_max: Optional[int] = None + personalization_char_count_max: int """ This an integer value representing the maximum length for the personalization message entered by the buyer. """ - personalization_instructions: Optional[str] = None + personalization_instructions: str """ When true, this listing requires personalization. The default value is null. """ - listing_type: Optional[bool] = None + listing_type: bool """ An enumerated type string that indicates whether the listing is physical or a digital download. """ - tags: Optional[List[str]] = None + tags: List[str] """ A list of tag strings for the listing. Valid tag strings contain only letters, numbers, whitespace characters, -, ', ™, ©, and ®. (regex: /[^\\\\p{L}\\\\p{Nd}\\\\p{Zs}\\\\-'™©®]/u) Default value is null. """ - materials: Optional[List[str]] = None + materials: List[str] """ A list of material strings for materials used in the product. Valid materials strings contain only letters, numbers, and whitespace characters. (regex: /[^\\\\p{L}\\\\p{Nd}\\\\p{Zs}]/u) Default value is null. """ - shipping_profile_id: Optional[int] = None + shipping_profile_id: int """The numeric ID of the shipping profile associated with the listing.""" - processing_min: Optional[int] = None + processing_min: int """ The minimum number of days required to process this listing. Default value is null. """ - processing_max: Optional[int] = None + processing_max: int """ The maximum number of days required to process this listing. Default value is null. """ - who_made: Optional[WhoMade] = None - when_made: Optional[WhenMade] = None - is_supply: Optional[bool] = None + who_made: WhoMade + when_made: WhenMade + is_supply: bool """ When true, tags the listing as a supply product, else indicates that it's a finished product. Helps buyers locate the listing under the Supplies heading. Requires 'who_made' and 'when_made'. """ - item_weight: Optional[float] = None + item_weight: float """ The numeric weight of the product measured in units set in item weight unit. Default value is null. If set, the value must be greater than 0. """ - item_weight_unit: Optional[ItemWeightUnit] = None - item_length: Optional[float] = None + item_weight_unit: ItemWeightUnit + item_length: float """ The numeric length of the product measured in units set in item dimensions unit. Default value is null. If set, the value must be greater than 0. """ - item_width: Optional[float] = None + item_width: float """ The numeric width of the product measured in units set in item dimensions unit. Default value is null. If set, the value must be greater than 0. """ - item_height: Optional[float] = None + item_height: float """ The numeric length of the product measured in units set in item dimensions unit. Default value is null. If set, the value must be greater than 0. """ - item_dimensions_unit: Optional[ItemDimensionsUnit] = None - is_private: Optional[bool] = None + item_dimensions_unit: ItemDimensionsUnit + is_private: bool """ When true, this is a private listing intendend for a specific buyer and hidden from shop view. """ - recipient: Optional[Recipient] = None - occasion: Optional[Occasion] = None - style: Optional[List[str]] = None + recipient: Recipient + occasion: Occasion + style: List[str] """ An array of style strings for this listing, each of which is free-form text string such as Formal, or Steampunk. A Listing may have up to two styles. @@ -1250,11 +1360,11 @@ class ShopListing: characters. (regex: /[^\\\\p{L}\\\\p{Nd}\\\\p{Zs}]/u) Default value is null. """ - file_data: Optional[str] = None + file_data: str """A string describing the files attached to a digital listing.""" - has_variations: Optional[bool] = None + has_variations: bool """When true, the listing has variations.""" - should_auto_renew: Optional[bool] = None + should_auto_renew: bool """ When true, renews a listing for four months upon expriation. If set to true when previously false, etsy.com renews the listing before it expires, but @@ -1262,13 +1372,13 @@ class ShopListing: expiration date. Any unused time remaining on the listing is lost. Renewals result in charges to a user's bill. """ - language: Optional[str] = None + language: str """ The IETF language tag for the default language of the listing. Ex: `de`, `en`, `es`, `fr`, `it`, `ja`, `nl`, `pl`, `pt`, `ru`. """ - price: Optional[Money] = None - taxonomy_id: Optional[int] = None + price: Money | Mapping[str, Any] + taxonomy_id: int """ The numeric taxonomy ID of the listing. The seller manages listing taxonomy IDs for their shop. See seller taxonomy for more information. @@ -1281,9 +1391,9 @@ class ShopListingsWithAssociations: Response for Get listings by ID """ - count: Optional[int] = None + count: int """The number of shop listing resources found.""" - results: Optional[List[ShopListing]] = None + results: List[ShopListing | Mapping[str, Any]] """The shop listing resources found.""" @@ -1293,11 +1403,11 @@ class ListingUpdatePropertyInput: Update a listing property """ - value_ids: Optional[int] = None + value_ids: int """The numeric ID of a single Etsy.com measurement scale.""" - values: Optional[str] = None + values: str """An array of value strings for multiple Etsy listing property values.""" - scale_id: Optional[int] = None + scale_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numeric ID of a single Etsy.com measurement scale.""" @@ -1307,17 +1417,17 @@ class ListingPropertyValue: Response for Update a listing property """ - property_id: Optional[int] = None + property_id: int """The numeric ID of the Property.""" - property_name: Optional[str] = None + property_name: str """The name of the Property.""" - scale_id: Optional[int] = None + scale_id: int """The numeric ID of the scale (if any).""" - scale_name: Optional[str] = None + scale_name: str """The label used to describe the chosen scale (if any).""" - value_ids: Optional[List[int]] = None + value_ids: List[int] """The numeric IDs of the property values""" - values: Optional[List[str]] = None + values: List[str] """The property values""" @@ -1327,9 +1437,9 @@ class ListingPropertyValues: Response for Get a listing's properties """ - count: Optional[int] = None + count: int """The number of shop listing resources found.""" - results: Optional[List[ListingPropertyValue]] = None + results: List[ListingPropertyValue | Mapping[str, Any]] """The shop listing resources found.""" @@ -1339,136 +1449,136 @@ class ListingUpdateInput: Update a listing """ - quantity: Optional[int] = None + quantity: Optional[int] = dataclass_field(default=None, kw_only=True) """ The positive non-zero number of products available for purchase in the listing. """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """ The listing's title string. Valid title strings contain only letters, numbers, punctuation marks, mathematical symbols, whitespace characters, ™, ©, and ®. (regex: /[^\\p{L}\\p{Nd}\\p{P}\\p{Sm}\\p{Zs}™©®]/u) You can only use the %, :, & and + characters once each. """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """A description string of the product for sale in the listing.""" - price: Optional[float] = None + price: Optional[float] = dataclass_field(default=None, kw_only=True) """ The positive non-zero price of the product. (Sold product listings are private) Note: The price is the minimum possible price. """ - who_made: Optional[str] = None + who_made: Optional[str] = dataclass_field(default=None, kw_only=True) """ An string inidcated who made the product. Helps buyers locate the listing under the Handmade heading. Requires 'is_supply' and 'when_made'. """ - when_made: Optional[str] = None + when_made: Optional[str] = dataclass_field(default=None, kw_only=True) """ A string for the era in which the maker made the product in this listing. Helps buyers locate the listing under the Vintage heading. Requires 'is_supply' and 'who_made'. """ - taxonomy_id: Optional[int] = None + taxonomy_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ The numeric taxonomy ID of the listing. The seller manages listing taxonomy IDs for their shop. """ - shipping_profile_id: Optional[int] = None + shipping_profile_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numeric ID of the shipping profile associated with the listing.""" - materials: Optional[str] = None + materials: Optional[str] = dataclass_field(default=None, kw_only=True) """ A array of material strings for materials used in the product. Valid materials strings contain only letters, numbers, and whitespace characters. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}]/u) """ - shop_section_id: Optional[int] = None + shop_section_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numeric ID of the shop section for this listing.""" - processing_min: Optional[int] = None + processing_min: Optional[int] = dataclass_field(default=None, kw_only=True) """The minimum number of days required to process this listing.""" - processing_max: Optional[int] = None + processing_max: Optional[int] = dataclass_field(default=None, kw_only=True) """The maximum number of days required to process this listing.""" - tags: Optional[str] = None + tags: Optional[str] = dataclass_field(default=None, kw_only=True) """ An array of tag strings for the listing. Valid tag strings contain only letters, numbers, whitespace characters, -, ', ™, ©, and ®. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}-'™©®]/u) """ - recipient: Optional[str] = None + recipient: Optional[str] = dataclass_field(default=None, kw_only=True) """ A string indicating a person for whom this product would make an appropriate gift. """ - occasion: Optional[str] = None + occasion: Optional[str] = dataclass_field(default=None, kw_only=True) """ A string indicating an occassion for which this product would make an appropriate gift. """ - styles: Optional[str] = None + styles: Optional[str] = dataclass_field(default=None, kw_only=True) """ An array of style strings for this listing, each of which is free-form text string such as Formal, or Steampunk. A Listing may have up to two styles. Valid style strings contain only letters, numbers, and whitespace characters. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}]/u) """ - item_weight: Optional[float] = None + item_weight: Optional[float] = dataclass_field(default=None, kw_only=True) """ The numeric weight of the product measured in units set in item weight unit. """ - item_length: Optional[int] = None + item_length: Optional[int] = dataclass_field(default=None, kw_only=True) """ The numeric length of the product measured in units set in item dimensions unit. """ - item_width: Optional[float] = None + item_width: Optional[float] = dataclass_field(default=None, kw_only=True) """ The numeric width of the product measured in units set in 'item dimensions unit'. """ - item_height: Optional[float] = None + item_height: Optional[float] = dataclass_field(default=None, kw_only=True) """ The numeric height of the product measured in units set in 'item dimensions unit'. """ - item_weight_unit: Optional[str] = None + item_weight_unit: Optional[str] = dataclass_field(default=None, kw_only=True) """ A string defining the units used to measure the weight of the product. """ - item_dimensions_unit: Optional[str] = None + item_dimensions_unit: Optional[str] = dataclass_field(default=None, kw_only=True) """ A string defining the units used to measure the dimensions of the product. """ - is_personalizable: Optional[bool] = None + is_personalizable: Optional[bool] = dataclass_field(default=None, kw_only=True) """When true, this listing is personalizable.""" - image_ids: Optional[str] = None + image_ids: Optional[str] = dataclass_field(default=None, kw_only=True) """ An array of numeric image IDs of the images in a listing, which can include up to 10 images. """ - is_supply: Optional[bool] = None + is_supply: Optional[bool] = dataclass_field(default=None, kw_only=True) """ When true, tags the listing as a supply product, else indicates that it's a finished product. Helps buyers locate the listing under the Supplies heading. Requires 'who made' and 'when made'. """ - is_customizable: Optional[bool] = None + is_customizable: Optional[bool] = dataclass_field(default=None, kw_only=True) """ When true, a buyer may contact the seller for a customized order. The default value is true when a shop accepts custom orders. Does not apply to shops that do not accept custom orders. """ - is_taxable: Optional[bool] = None + is_taxable: Optional[bool] = dataclass_field(default=None, kw_only=True) """ When true, applicable shop tax rates apply to this listing at checkout. """ - featured_rank: Optional[int] = None + featured_rank: Optional[int] = dataclass_field(default=None, kw_only=True) """ The positive non-zero numeric position in the featured listings of the shop with rank 1 listings appearing in the left-most position in featured listing on a shop's home page. """ - should_auto_renew: Optional[bool] = None + should_auto_renew: Optional[bool] = dataclass_field(default=None, kw_only=True) """ When true, renews a listing for four months upon expriation. If set to true when previously false, etsy.com renews the listing before it expires, but @@ -1476,9 +1586,13 @@ class ListingUpdateInput: expiration date. Any unused time remaining on the listing is lost. Renewals result in charges to a user's bill. """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Indicates whether the listing is physical or a digital download.""" - channels: Optional[str] = None + channels: Optional[str] = dataclass_field(default=None, kw_only=True) """ An array of enumerated channel ID strings. A channel is a venue for sellers to reach buyers in order to make sales. @@ -1491,24 +1605,24 @@ class ShopListingFile: Response for Get a file from a listing """ - listing_file_id: Optional[int] = None + listing_file_id: int """The unique numeric ID of a file associated with a digital listing.""" - listing_id: Optional[int] = None + listing_id: int """The numeric ID for the listing associated to this transaction.""" - rank: Optional[int] = None + rank: int """ The numeric index of the display order position of this file in the listing, starting at 1. """ - filename: Optional[str] = None + filename: str """The file name string for a file associated with a digital listing.""" - filesize: Optional[str] = None + filesize: str """A human-readable format size string for the size of a file.""" - size_bytes: Optional[int] = None + size_bytes: int """A number indicating the size of a file, measured in bytes.""" - filetype: Optional[str] = None + filetype: str """A type string indicating a file's MIME type.""" - create_timestamp: Optional[int] = None + create_timestamp: int """ The unique numeric timestamp of a file associated with a digital listing. """ @@ -1520,9 +1634,9 @@ class ShopListingFiles: Response for Get all listing files """ - count: Optional[int] = None + count: int """The number of ShopListingFiles being returned..""" - results: Optional[List[ShopListingFile]] = None + results: List[ShopListingFile | Mapping[str, Any]] """An array of ShopListingFile resources.""" @@ -1532,13 +1646,13 @@ class ListingUploadInput: Upload a listing file """ - listing_file_id: Optional[int] = None + listing_file_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The unique numeric ID of a file associated with a digital listing.""" - file: Optional[str] = None + file: str """A binary file to upload.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The file name string of a file to upload""" - rank: Optional[int] = None + rank: Optional[int] = dataclass_field(default=None, kw_only=True) """ The positive non-zero numeric position in the images displayed in a listing, with rank 1 images appearing in the left-most position in a @@ -1552,80 +1666,71 @@ class ListingImage: Response for Get a listing image """ - listing_id: Optional[int] = None + listing_id: int """The numeric ID for the listing associated to this transaction.""" - listing_image_id: Optional[int] = None + listing_image_id: int """The numeric ID of the primary listing image for this transaction.""" - hex_code: Optional[str] = None + hex_code: str """The webhex string for the image's average color, in webhex notation.""" - red: Optional[int] = None + red: int """ The numeric red value equal to the image's average red value, from 0-255 (RGB color). """ - green: Optional[int] = None + green: int """ The numeric red value equal to the image's average red value, from 0-255 (RGB color). """ - blue: Optional[int] = None + blue: int """ The numeric red value equal to the image's average red value, from 0-255 (RGB color). """ - hue: Optional[int] = None + hue: int """ The numeric hue equal to the image's average hue, from 0-360 (HSV color). """ - saturation: Optional[int] = None + saturation: int """ The numeric saturation equal to the image's average saturation, from 0-100 (HSV color). """ - brightness: Optional[int] = None + brightness: int """ The numeric brightness equal to the image's average brightness, from 0-100 (HSV color). """ - is_black_and_white: Optional[bool] = None + is_black_and_white: bool """When true, the image is in black & white.""" - creation_tsz: Optional[int] = None + creation_tsz: int """The listing image's creation time, in epoch seconds.""" - rank: Optional[int] = None + rank: int """ The positive non-zero numeric position in the images displayed in a listing, with rank 1 images appearing in the left-most position in a listing. """ - url75x75: Optional[str] = field( - default=None, - metadata={"wire_name": "url_75x75"}, - ) + url75x75: str = dataclass_field(metadata={"wire_name": "url_75x75"}) """The url string for a 75x75 pixel thumbnail of the image.""" - url170x135: Optional[str] = field( - default=None, - metadata={"wire_name": "url_170x135"}, - ) + url170x135: str = dataclass_field(metadata={"wire_name": "url_170x135"}) """The url string for a 170x135 pixel thumbnail of the image.""" - url570x_n: Optional[str] = field( - default=None, - metadata={"wire_name": "url_570xN"}, - ) + url570x_n: str = dataclass_field(metadata={"wire_name": "url_570xN"}) """ The url string for a thumbnail of the image, no more than 570 pixels wide with variable height. """ - url_fullxfull: Optional[str] = None + url_fullxfull: str """ The url string for the full-size image, up to 3000 pixels in each dimension. """ - full_height: Optional[int] = None + full_height: int """ The numeric height, measured in pixels, of the full-sized image referenced in url_fullxfull. """ - full_width: Optional[int] = None + full_width: int """ The numeric width, measured in pixels, of the full-sized image referenced in url_fullxfull. @@ -1638,9 +1743,9 @@ class ListingImages: Response for Get a listing's images """ - count: Optional[int] = None + count: int """The number of results.""" - results: Optional[List[ListingImage]] = None + results: List[ListingImage | Mapping[str, Any]] """The list of requested resources.""" @@ -1650,19 +1755,19 @@ class ListingUploadImageInput: Upload a listing image """ - image: Optional[str] = None + image: Optional[str] = dataclass_field(default=None, kw_only=True) """The file name string of a file to upload.""" - listing_image_id: Optional[int] = None + listing_image_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numeric ID of the primary listing image for this transaction.""" - rank: Optional[int] = None + rank: Optional[int] = dataclass_field(default=None, kw_only=True) """ The positive non-zero numeric position in the images displayed in a listing, with rank 1 images appearing in the left-most position in a listing. """ - overwrite: Optional[bool] = None + overwrite: Optional[bool] = dataclass_field(default=None, kw_only=True) """When true, this request replaces the existing image at a given rank.""" - is_watermarked: Optional[bool] = None + is_watermarked: Optional[bool] = dataclass_field(default=None, kw_only=True) """When true, indicates that the uploaded image has a watermark.""" @@ -1672,33 +1777,33 @@ class ListingInventoryWithAssociations: Response for Get a listing's inventory """ - products: Optional[List[ListingInventoryProduct]] = None + products: List[ListingInventoryProduct | Mapping[str, Any]] """ A JSON array of products available in a listing, even if only one product. All field names in the JSON blobs are lowercase. """ - price_on_property: Optional[List[int]] = None + price_on_property: List[int] """ An array of unique listing property ID integers for the properties that change product prices, if any. For example, if you charge specific prices for different sized products in the same listing, then this array contains the property ID for size. """ - quantity_on_property: Optional[List[int]] = None + quantity_on_property: List[int] """ An array of unique listing property ID integers for the properties that change the quantity of the products, if any. For example, if you stock specific quantities of different colored products in the same listing, then this array contains the property ID for color. """ - sku_on_property: Optional[List[int]] = None + sku_on_property: List[int] """ An array of unique listing property ID integers for the properties that change the product SKU, if any. For example, if you use specific skus for different colored products in the same listing, then this array contains the property ID for color. """ - listing: Optional[ShopListing] = None + listing: ShopListing | Mapping[str, Any] @dataclass @@ -1707,26 +1812,26 @@ class ListingUpdateInventoryInput: Update a listing's inventory """ - products: Optional[str] = None + products: str """ A JSON array of products available in a listing, even if only one product. All field names in the JSON blobs are lowercase. """ - price_on_property: Optional[str] = None + price_on_property: Optional[str] = dataclass_field(default=None, kw_only=True) """ An array of unique listing property ID integers for the properties that change product prices, if any. For example, if you charge specific prices for different sized products in the same listing, then this array contains the property ID for size. """ - quantity_on_property: Optional[str] = None + quantity_on_property: Optional[str] = dataclass_field(default=None, kw_only=True) """ An array of unique listing property ID integers for the properties that change the quantity of the products, if any. For example, if you stock specific quantities of different colored products in the same listing, then this array contains the property ID for color. """ - sku_on_property: Optional[str] = None + sku_on_property: Optional[str] = dataclass_field(default=None, kw_only=True) """ An array of unique listing property ID integers for the properties that change the product SKU, if any. For example, if you use specific skus for @@ -1741,26 +1846,26 @@ class ListingInventory: Response for Update a listing's inventory """ - products: Optional[List[ListingInventoryProduct]] = None + products: List[ListingInventoryProduct | Mapping[str, Any]] """ A JSON array of products available in a listing, even if only one product. All field names in the JSON blobs are lowercase. """ - price_on_property: Optional[List[int]] = None + price_on_property: List[int] """ An array of unique listing property ID integers for the properties that change product prices, if any. For example, if you charge specific prices for different sized products in the same listing, then this array contains the property ID for size. """ - quantity_on_property: Optional[List[int]] = None + quantity_on_property: List[int] """ An array of unique listing property ID integers for the properties that change the quantity of the products, if any. For example, if you stock specific quantities of different colored products in the same listing, then this array contains the property ID for color. """ - sku_on_property: Optional[List[int]] = None + sku_on_property: List[int] """ An array of unique listing property ID integers for the properties that change the product SKU, if any. For example, if you use specific skus for @@ -1775,15 +1880,15 @@ class ListingInventoryProductOffering: Response for Get a listing's offering """ - offering_id: Optional[int] = None + offering_id: int """The ID for the product offering""" - quantity: Optional[int] = None + quantity: int """The quantity the product offering""" - is_enabled: Optional[bool] = None + is_enabled: bool """Whether or not the offering can be shown to buyers.""" - is_deleted: Optional[bool] = None + is_deleted: bool """Whether or not the offering has been deleted.""" - price: Optional[Money] = None + price: Money | Mapping[str, Any] @dataclass @@ -1792,15 +1897,15 @@ class ListingInventoryProduct: Response for Get a listing's product """ - product_id: Optional[int] = None + product_id: int """The numeric ID for a specific product purchased from a listing.""" - sku: Optional[str] = None + sku: str """The SKU string for the product""" - is_deleted: Optional[bool] = None + is_deleted: bool """When true, someone deleted this product.""" - offerings: Optional[List[ListingInventoryProductOffering]] = None + offerings: List[ListingInventoryProductOffering | Mapping[str, Any]] """A list of product offering entries for this product.""" - property_values: Optional[List[ListingPropertyValue]] = None + property_values: List[ListingPropertyValue | Mapping[str, Any]] """A list of property value entries for this product.""" @@ -1810,17 +1915,17 @@ class ListingTranslation: Response for Get a listing's translation """ - listing_id: Optional[int] = None + listing_id: int """The numeric ID for the Listing.""" - language: Optional[str] = None + language: str """ The IETF language tag (e.g. 'fr') for the language of this translation. """ - title: Optional[str] = None + title: str """The title of the Listing of this Translation.""" - description: Optional[str] = None + description: str """The description of the Listing of this Translation.""" - tags: Optional[List[str]] = None + tags: List[str] """The tags of the Listing of this Translation.""" @@ -1830,11 +1935,11 @@ class ListingCreateTranslationInput: Create a listing translation """ - title: Optional[str] = None + title: str """The title of the Listing of this Translation.""" - description: Optional[str] = None + description: str """The description of the Listing of this Translation.""" - tags: Optional[str] = None + tags: Optional[str] = dataclass_field(default=None, kw_only=True) """The tags of the Listing of this Translation.""" @@ -1844,11 +1949,11 @@ class ListingUpdateTranslationInput: Update a listing translation """ - title: Optional[str] = None + title: str """The title of the Listing of this Translation.""" - description: Optional[str] = None + description: str """The description of the Listing of this Translation.""" - tags: Optional[str] = None + tags: Optional[str] = dataclass_field(default=None, kw_only=True) """The tags of the Listing of this Translation.""" @@ -1858,9 +1963,9 @@ class ListingVariationImages: Response for Get listing's variation images """ - count: Optional[int] = None + count: int """The count of variation images.""" - results: Optional[List[ListingVariationImage]] = None + results: List[ListingVariationImage | Mapping[str, Any]] """The variation images results.""" @@ -1870,7 +1975,7 @@ class ListingUpdateVariationInput: Update a listing's variation images """ - variation_images: Optional[str] = None + variation_images: str """A array of variation image data.""" @@ -1880,11 +1985,11 @@ class Money: Definition: Money """ - amount: Optional[int] = None + amount: int """The amount of represented by this data.""" - divisor: Optional[int] = None + divisor: int """The divisor to render the amount.""" - currency_code: Optional[str] = None + currency_code: str """The ISO currency code for this data.""" @@ -1894,7 +1999,7 @@ class ErrorSchema: Definition: ErrorSchema """ - error: Optional[str] = None + error: str """The error code.""" @@ -1904,146 +2009,146 @@ class ShopListingWithAssociations: Definition: ShopListingWithAssociations """ - listing_id: Optional[int] = None + listing_id: int """The numeric ID for the listing associated to this transaction.""" - user_id: Optional[int] = None + user_id: int """The numeric ID for the user posting the listing.""" - shop_id: Optional[int] = None + shop_id: int """The unique positive non-zero numeric ID for an Etsy Shop.""" - title: Optional[str] = None + title: str """ The listing's title string. Valid title strings contain only letters, numbers, punctuation marks, mathematical symbols, whitespace characters, ™, ©, and ®. (regex: /[^\\\\p{L}\\\\p{Nd}\\\\p{P}\\\\p{Sm}\\\\p{Zs}™©®]/u) You can only use the %, :, & and + characters once each. """ - description: Optional[str] = None + description: str """A description string of the product for sale in the listing.""" - state: Optional[State] = None - creation_timestamp: Optional[int] = None + state: State + creation_timestamp: int """The listing's creation time, in epoch seconds.""" - ending_timestamp: Optional[int] = None + ending_timestamp: int """The listing's expiration time, in epoch seconds.""" - original_creation_timestamp: Optional[int] = None + original_creation_timestamp: int """The listing's creation time, in epoch seconds.""" - last_modified_timestamp: Optional[int] = None + last_modified_timestamp: int """The time of the last update to the listing, in epoch seconds.""" - state_timestamp: Optional[int] = None + state_timestamp: int """The date and time of the last state change of this listing.""" - quantity: Optional[int] = None + quantity: int """ The positive non-zero number of products available for purchase in the listing. Note: The listing quantity is the sum of available offering quantities. You can request the quantities for individual offerings from the ListingInventory resource using the get listing inventory endpoint. """ - shop_section_id: Optional[int] = None + shop_section_id: int """The numeric ID of a section in a specific Etsy shop.""" - featured_rank: Optional[int] = None + featured_rank: int """ The positive non-zero numeric position in the featured listings of the shop, with rank 1 listings appearing in the left-most position in featured listing on a shop's home page. """ - url: Optional[str] = None + url: str """The full URL to the listing's page on Etsy.""" - num_favorers: Optional[int] = None + num_favorers: int """The number of users who marked this listing a favorite.""" - non_taxable: Optional[bool] = None + non_taxable: bool """ When true, applicable shop tax rates do not apply to this listing at checkout. """ - is_customizable: Optional[bool] = None + is_customizable: bool """ When true, a buyer may contact the seller for a customized order. The default value is true when a shop accepts custom orders. Does not apply to shops that do not accept custom orders. """ - is_personalizable: Optional[bool] = None + is_personalizable: bool """When true, this listing is personalizable. The default value is null.""" - personalization_is_required: Optional[bool] = None + personalization_is_required: bool """ When true, this listing requires personalization. The default value is null. """ - personalization_char_count_max: Optional[int] = None + personalization_char_count_max: int """ This an integer value representing the maximum length for the personalization message entered by the buyer. """ - personalization_instructions: Optional[str] = None + personalization_instructions: str """ When true, this listing requires personalization. The default value is null. """ - listing_type: Optional[bool] = None + listing_type: bool """ An enumerated type string that indicates whether the listing is physical or a digital download. """ - tags: Optional[List[str]] = None + tags: List[str] """ A list of tag strings for the listing. Valid tag strings contain only letters, numbers, whitespace characters, -, ', ™, ©, and ®. (regex: /[^\\\\p{L}\\\\p{Nd}\\\\p{Zs}\\\\-'™©®]/u) Default value is null. """ - materials: Optional[List[str]] = None + materials: List[str] """ A list of material strings for materials used in the product. Valid materials strings contain only letters, numbers, and whitespace characters. (regex: /[^\\\\p{L}\\\\p{Nd}\\\\p{Zs}]/u) Default value is null. """ - shipping_profile_id: Optional[int] = None + shipping_profile_id: int """The numeric ID of the shipping profile associated with the listing.""" - processing_min: Optional[int] = None + processing_min: int """ The minimum number of days required to process this listing. Default value is null. """ - processing_max: Optional[int] = None + processing_max: int """ The maximum number of days required to process this listing. Default value is null. """ - who_made: Optional[WhoMade] = None - when_made: Optional[WhenMade] = None - is_supply: Optional[bool] = None + who_made: WhoMade + when_made: WhenMade + is_supply: bool """ When true, tags the listing as a supply product, else indicates that it's a finished product. Helps buyers locate the listing under the Supplies heading. Requires 'who_made' and 'when_made'. """ - item_weight: Optional[float] = None + item_weight: float """ The numeric weight of the product measured in units set in item weight unit. Default value is null. If set, the value must be greater than 0. """ - item_weight_unit: Optional[ItemWeightUnit] = None - item_length: Optional[float] = None + item_weight_unit: ItemWeightUnit + item_length: float """ The numeric length of the product measured in units set in item dimensions unit. Default value is null. If set, the value must be greater than 0. """ - item_width: Optional[float] = None + item_width: float """ The numeric width of the product measured in units set in item dimensions unit. Default value is null. If set, the value must be greater than 0. """ - item_height: Optional[float] = None + item_height: float """ The numeric length of the product measured in units set in item dimensions unit. Default value is null. If set, the value must be greater than 0. """ - item_dimensions_unit: Optional[ItemDimensionsUnit] = None - is_private: Optional[bool] = None + item_dimensions_unit: ItemDimensionsUnit + is_private: bool """ When true, this is a private listing intendend for a specific buyer and hidden from shop view. """ - recipient: Optional[Recipient] = None - occasion: Optional[Occasion] = None - style: Optional[List[str]] = None + recipient: Recipient + occasion: Occasion + style: List[str] """ An array of style strings for this listing, each of which is free-form text string such as Formal, or Steampunk. A Listing may have up to two styles. @@ -2051,11 +2156,11 @@ class ShopListingWithAssociations: characters. (regex: /[^\\\\p{L}\\\\p{Nd}\\\\p{Zs}]/u) Default value is null. """ - file_data: Optional[str] = None + file_data: str """A string describing the files attached to a digital listing.""" - has_variations: Optional[bool] = None + has_variations: bool """When true, the listing has variations.""" - should_auto_renew: Optional[bool] = None + should_auto_renew: bool """ When true, renews a listing for four months upon expriation. If set to true when previously false, etsy.com renews the listing before it expires, but @@ -2063,25 +2168,25 @@ class ShopListingWithAssociations: expiration date. Any unused time remaining on the listing is lost. Renewals result in charges to a user's bill. """ - language: Optional[str] = None + language: str """ The IETF language tag for the default language of the listing. Ex: `de`, `en`, `es`, `fr`, `it`, `ja`, `nl`, `pl`, `pt`, `ru`. """ - price: Optional[Money] = None - taxonomy_id: Optional[int] = None + price: Money | Mapping[str, Any] + taxonomy_id: int """ The numeric taxonomy ID of the listing. The seller manages listing taxonomy IDs for their shop. See seller taxonomy for more information. """ - user: Optional[User] = None - shop: Optional[Shop] = None - images: Optional[List[ListingImage]] = None + user: User | Mapping[str, Any] + shop: Shop | Mapping[str, Any] + images: List[ListingImage | Mapping[str, Any]] """ Represents a list of listing image resources, each of which contains the reference URLs and metadata for an image """ - production_partners: Optional[List[ShopProductionPartner]] = None + production_partners: List[ShopProductionPartner | Mapping[str, Any]] """Represents a list of production partners for a shop.""" @@ -2091,11 +2196,11 @@ class ShopProductionPartner: Definition: ShopProductionPartner """ - production_partner_id: Optional[int] = None + production_partner_id: int """The numeric ID of a production partner.""" - partner_name: Optional[str] = None + partner_name: str """The name or title of the production partner.""" - location: Optional[str] = None + location: str """A string representing the production partner location.""" @@ -2105,11 +2210,11 @@ class ListingVariationImage: Definition: ListingVariationImage """ - property_id: Optional[int] = None + property_id: int """The numeric ID of the Property.""" - value_id: Optional[int] = None + value_id: int """The numeric ID of the Value.""" - image_id: Optional[int] = None + image_id: int """The numeric ID of the Image.""" @@ -2119,31 +2224,31 @@ class PaymentAccountLedgerEntry: Definition: PaymentAccountLedgerEntry """ - entry_id: Optional[int] = None + entry_id: int """The ledger entry's numeric ID.""" - ledger_id: Optional[int] = None + ledger_id: int """The ledger's numeric ID.""" - sequence_number: Optional[int] = None + sequence_number: int """ The sequence allows ledger entries to be sorted chronologically. The higher the sequence, the more recent the entry. """ - amount: Optional[int] = None + amount: int """The amount of money credited to the ledger.""" - currency: Optional[str] = None + currency: str """The currency of the entry on the ledger.""" - description: Optional[str] = None + description: str """ Details what kind of ledger entry this is: a payment, refund, reversal of a failed refund, disbursement, returned disbursement, recoupment, miscellaneous credit, miscellaneous debit, or bill payment. """ - balance: Optional[int] = None + balance: int """ The amount of money in the shop's ledger the moment after this entry was applied. """ - create_date: Optional[int] = None + create_date: int """The date and time the ledger entry was created in Epoch seconds..""" @@ -2153,53 +2258,58 @@ class Payment: Definition: Payment """ - payment_id: Optional[int] = None + payment_id: int """A unique numeric ID for a payment to a specific Etsy shop.""" - buyer_user_id: Optional[int] = None + buyer_user_id: int """The numeric ID for the user who paid the purchase.""" - shop_id: Optional[int] = None + shop_id: int """The unique positive non-zero numeric ID for an Etsy Shop.""" - receipt_id: Optional[int] = None + receipt_id: int """The numeric ID for the receipt associated to this transaction.""" - amount_gross: Optional[Money] = None - amount_fees: Optional[Money] = None - amount_net: Optional[Money] = None - posted_gross: Optional[Money] = None - posted_fees: Optional[Money] = None - posted_net: Optional[Money] = None - adjusted_gross: Optional[Money] = None - adjusted_fees: Optional[Money] = None - adjusted_net: Optional[Money] = None - currency: Optional[str] = None + amount_gross: Money | Mapping[str, Any] + amount_fees: Money | Mapping[str, Any] + amount_net: Money | Mapping[str, Any] + posted_gross: Optional[Money | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + posted_fees: Optional[Money | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + posted_net: Optional[Money | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + adjusted_gross: Optional[ + Money | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + adjusted_fees: Optional[Money | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + adjusted_net: Optional[Money | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + currency: str """The ISO (alphabetic) code string for the payment's currency.""" - shop_currency: Optional[str] = None + shop_currency: str """ The ISO (alphabetic) code for the shop's currency. The shop displays all prices in this currency by default. """ - buyer_currency: Optional[str] = None + buyer_currency: str """The currency string of the buyer.""" - shipping_user_id: Optional[int] = None + shipping_user_id: int """The numeric ID of the user to which the seller ships the order.""" - shipping_address_id: Optional[int] = None + shipping_address_id: int """The numeric id identifying the shipping address.""" - billing_address_id: Optional[int] = None + billing_address_id: int """The numeric ID identifying the billing address of the buyer.""" - status: Optional[str] = None + status: str """ A string indicating the current status of the payment, most commonly settled or authed. """ - shipped_timestamp: Optional[int] = None + shipped_timestamp: int """The transaction's shipping date and time, in epoch seconds.""" - create_timestamp: Optional[int] = None + create_timestamp: int """The transaction's creation date and time, in epoch seconds.""" - update_timestamp: Optional[int] = None + update_timestamp: int """ The date and time of the last change to the payment adjustment in epoch seconds. """ - payment_adjustments: Optional[List[PaymentAdjustment]] = None + payment_adjustments: List[PaymentAdjustment | Mapping[str, Any]] """ List of refund objects on an Etsy Payments transaction. All monetary amounts are in USD pennies unless otherwise specified. @@ -2212,35 +2322,35 @@ class PaymentAdjustment: Definition: PaymentAdjustment """ - payment_adjustment_id: Optional[int] = None + payment_adjustment_id: int """The numeric ID for a payment adjustment.""" - payment_id: Optional[int] = None + payment_id: int """A unique numeric ID for a payment to a specific Etsy shop.""" - status: Optional[str] = None + status: str """The status string of the payment adjustment.""" - is_success: Optional[bool] = None + is_success: bool """ When true, the payment adjustment was or is likely to complete successfully. """ - user_id: Optional[int] = None + user_id: int """The numeric ID for the user (seller) fulfilling the purchase.""" - reason_code: Optional[str] = None + reason_code: str """A human-readable string describing the reason for the refund.""" - total_adjustment_amount: Optional[int] = None + total_adjustment_amount: int """The total numeric amount of the refund in the payment currency.""" - shop_total_adjustment_amount: Optional[int] = None + shop_total_adjustment_amount: int """The numeric amount of the refund in the shop currency.""" - buyer_total_adjustment_amount: Optional[int] = None + buyer_total_adjustment_amount: int """The numeric amount of the refund in the buyer currency.""" - total_fee_adjustment_amount: Optional[int] = None + total_fee_adjustment_amount: int """ The numeric amount of card processing fees associated with a payment adjustment. """ - create_timestamp: Optional[int] = None + create_timestamp: int """The transaction's creation date and time, in epoch seconds.""" - update_timestamp: Optional[int] = None + update_timestamp: int """ The date and time of the last change to the payment adjustment in epoch seconds. @@ -2253,19 +2363,19 @@ class ShopReceiptShipment: Definition: ShopReceiptShipment """ - receipt_shipping_id: Optional[int] = None + receipt_shipping_id: int """The unique numeric ID of a Shop Receipt Shipment record.""" - shipment_notification_timestamp: Optional[int] = None + shipment_notification_timestamp: int """ The time at which Etsy notified the buyer of the shipment event, in epoch seconds. """ - carrier_name: Optional[str] = None + carrier_name: str """ The name string for the carrier/company responsible for delivering the shipment. """ - tracking_code: Optional[str] = None + tracking_code: str """ The tracking code string provided by the carrier/company for the shipment. """ @@ -2277,29 +2387,29 @@ class TransactionReview: Definition: TransactionReview """ - shop_id: Optional[int] = None + shop_id: int """The shop's numeric ID.""" - listing_id: Optional[int] = None + listing_id: int """The ID of the shop listing that the TransactionReview belongs to.""" - buyer_user_id: Optional[int] = None + buyer_user_id: int """ The numeric ID of the user who was the buyer in this transaction. Note: This field may be absent, depending on the buyer's privacy settings. """ - rating: Optional[int] = None + rating: int """Rating value on scale from 1 to 5""" - review: Optional[str] = None + review: str """A message left by the author, explaining the feedback.""" - language: Optional[str] = None + language: str """The language of the TransactionReview""" - image_url_fullxfull: Optional[str] = None + image_url_fullxfull: str """ The url to a photo provided with the feedback, dimensions fullxfull. Note: This field may be absent, depending on the buyer's privacy settings. """ - create_timestamp: Optional[int] = None + create_timestamp: int """The date and time the TransactionReview was created in epoch seconds.""" - update_timestamp: Optional[int] = None + update_timestamp: int """The date and time the TransactionReview was updated in epoch seconds.""" @@ -2309,7 +2419,7 @@ class SellerTaxonomyNode: Definition: SellerTaxonomyNode """ - id: Optional[int] = None + id: int """ The unique numeric ID of an Etsy taxonomy node, which is a metadata category for listings organized into the seller taxonomy hierarchy tree. @@ -2321,21 +2431,21 @@ class SellerTaxonomyNode: associated property names and IDs for EU shoe sizes, such as property `value_id`:1394, and `name`:38. """ - level: Optional[int] = None + level: int """ The integer depth of this taxonomy node in the seller taxonomy tree, with roots at level 0. """ - name: Optional[str] = None + name: str """The name string for this taxonomy node.""" - parent_id: Optional[int] = None + parent_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numeric taxonomy ID of the parent of this node.""" - children: Optional[List[SellerTaxonomyNode]] = None + children: List[SellerTaxonomyNode | Mapping[str, Any]] """ An array of taxonomy nodes for all the direct children of this taxonomy node in the seller taxanomy tree. """ - full_path_taxonomy_ids: Optional[List[int]] = None + full_path_taxonomy_ids: List[int] """ An array of taxonomy IDs including this node and all of its direct parents in the seller taxonomy tree up to a root node. They are listed in order @@ -2349,27 +2459,27 @@ class TaxonomyNodeProperty: Definition: TaxonomyNodeProperty """ - property_id: Optional[int] = None + property_id: int """The unique numeric ID of this product property.""" - name: Optional[str] = None + name: str """The name string for this taxonomy node.""" - display_name: Optional[str] = None + display_name: str """The human-readable product property name string.""" - scales: Optional[List[TaxonomyPropertyScale]] = None + scales: List[TaxonomyPropertyScale | Mapping[str, Any]] """A list of available scales.""" - is_required: Optional[bool] = None + is_required: bool """ When true, listings assigned eligible taxonomy IDs require this property. """ - supports_attributes: Optional[bool] = None + supports_attributes: bool """When true, you can use this property in listing attributes.""" - supports_variations: Optional[bool] = None + supports_variations: bool """When true, you can use this property in listing variations.""" - is_multivalued: Optional[bool] = None + is_multivalued: bool """When true, you can assign multiple property values to this property""" - possible_values: Optional[List[TaxonomyPropertyValue]] = None + possible_values: List[TaxonomyPropertyValue | Mapping[str, Any]] """A list of supported property value strings for this property.""" - selected_values: Optional[List[TaxonomyPropertyValue]] = None + selected_values: List[TaxonomyPropertyValue | Mapping[str, Any]] """ A list of property value strings automatically and always selected for the given property. @@ -2382,11 +2492,11 @@ class TaxonomyPropertyScale: Definition: TaxonomyPropertyScale """ - scale_id: Optional[int] = None + scale_id: int """The unique numeric ID of a scale.""" - display_name: Optional[str] = None + display_name: str """The name string for a scale.""" - description: Optional[str] = None + description: str """The description string for a scale.""" @@ -2396,15 +2506,15 @@ class TaxonomyPropertyValue: Definition: TaxonomyPropertyValue """ - value_id: Optional[int] = None + value_id: int """The numeric ID of this property value.""" - name: Optional[str] = None + name: str """The name string of this property value.""" - scale_id: Optional[int] = None + scale_id: int """ The numeric scale ID of the scale to which this property value belongs. """ - equal_to: Optional[List[int]] = None + equal_to: List[int] """ A list of numeric property value IDs this property value is equal to (if any). @@ -2417,13 +2527,13 @@ class ShippingCarrier: Definition: ShippingCarrier """ - shipping_carrier_id: Optional[int] = None + shipping_carrier_id: int """The numeric ID of this shipping carrier.""" - name: Optional[str] = None + name: str """The name of this shipping carrier.""" - domestic_classes: Optional[List[ShippingCarrierMailClass]] = None + domestic_classes: List[ShippingCarrierMailClass | Mapping[str, Any]] """Set of domestic mail classes of this shipping carrier.""" - international_classes: Optional[List[ShippingCarrierMailClass]] = None + international_classes: List[ShippingCarrierMailClass | Mapping[str, Any]] """Set of international mail classes of this shipping carrier.""" @@ -2433,9 +2543,9 @@ class ShippingCarrierMailClass: Definition: ShippingCarrierMailClass """ - mail_class_key: Optional[str] = None + mail_class_key: str """The unique identifier of this mail class.""" - name: Optional[str] = None + name: str """The name of this mail class.""" @@ -2445,9 +2555,9 @@ class ShopProductionPartners: Definition: ShopProductionPartners """ - count: Optional[int] = None + count: int """The number of results.""" - results: Optional[List[ShopProductionPartner]] = None + results: List[ShopProductionPartner | Mapping[str, Any]] """The list of requested resources.""" @@ -2457,8 +2567,8 @@ class ShopShippingProfiles: Definition: ShopShippingProfiles """ - count: Optional[int] = None - results: Optional[List[ShopShippingProfile]] = None + count: int + results: List[ShopShippingProfile | Mapping[str, Any]] Channel = Literal["etsy.com", "wholesale", "pattern", "sell_on_facebook"] @@ -2534,11 +2644,11 @@ class Offering: Definition: Offering """ - price: Optional[float] = None + price: Optional[float] = dataclass_field(default=None, kw_only=True) """The price of the product.""" - quantity: Optional[int] = None + quantity: Optional[int] = dataclass_field(default=None, kw_only=True) """How many of this product are available?""" - is_enabled: Optional[bool] = None + is_enabled: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the offering is shown to buyers""" @@ -2551,11 +2661,21 @@ class Product: Definition: Product """ - sku: Optional[str] = None + sku: Optional[str] = dataclass_field(default=None, kw_only=True) """The SKU string for the product""" - property_values: Optional[List[PropertyValue]] = None + property_values: Optional[ + List[PropertyValue | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A list of property value entries for this product.""" - offerings: Optional[List[Offering]] = None + offerings: Optional[ + List[Offering | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A list of product offering entries for this product.""" @@ -2568,23 +2688,23 @@ class PropertyValue: Definition: PropertyValue """ - property_id: Optional[int] = None + property_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The unique ID of an Etsy listing property.""" - value_ids: Optional[List[int]] = None + value_ids: Optional[List[int]] = dataclass_field(default=None, kw_only=True) """ An array of unique IDs of multiple Etsy listing property values. For example, if your listing offers different sizes of a product, then the value ID list contains value IDs for each size. """ - scale_id: Optional[int] = None + scale_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ The numeric ID of a single Etsy.com measurement scale. For example, for shoe size, there are three `scale_id`s available - *UK*, *US/Canada*, and *EU*, where *US/Canada* has `scale_id` 19. """ - property_name: Optional[str] = None + property_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the property, in the requested locale language.""" - values: Optional[List[str]] = None + values: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """A list of property value entries for this product.""" @@ -2633,26 +2753,26 @@ class ApplicationListingsInventoryRequest: Definition: V3ApplicationListingsInventoryRequest """ - products: Optional[List[Product]] = None + products: List[Product | Mapping[str, Any]] """ A JSON array of products available in a listing, even if only one product. All field names in the JSON blobs are lowercase. """ - price_on_property: Optional[List[int]] = None + price_on_property: Optional[List[int]] = dataclass_field(default=None, kw_only=True) """ An array of unique listing property ID integers for the properties that change product prices, if any. For example, if you charge specific prices for different sized products in the same listing, then this array contains the property ID for size. """ - quantity_on_property: Optional[List[int]] = None + quantity_on_property: Optional[List[int]] = dataclass_field(default=None, kw_only=True) """ An array of unique listing property ID integers for the properties that change the quantity of the products, if any. For example, if you stock specific quantities of different colored products in the same listing, then this array contains the property ID for color. """ - sku_on_property: Optional[List[int]] = None + sku_on_property: Optional[List[int]] = dataclass_field(default=None, kw_only=True) """ An array of unique listing property ID integers for the properties that change the product SKU, if any. For example, if you use specific skus for @@ -2667,7 +2787,7 @@ class ApplicationShopsListingsVariationImagesRequest: Definition: V3ApplicationShopsListingsVariationImagesRequest """ - variation_images: Optional[List[VariationImage]] = None + variation_images: List[VariationImage | Mapping[str, Any]] """A list of variation image data.""" @@ -2677,9 +2797,9 @@ class VariationImage: Definition: VariationImage """ - property_id: Optional[int] = None - value_id: Optional[int] = None - image_id: Optional[int] = None + property_id: Optional[int] = dataclass_field(default=None, kw_only=True) + value_id: Optional[int] = dataclass_field(default=None, kw_only=True) + image_id: Optional[int] = dataclass_field(default=None, kw_only=True) WhenMade2 = Literal[ @@ -2742,16 +2862,16 @@ class EtsyClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -2762,8 +2882,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -2771,8 +2891,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -2784,7 +2904,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -2799,7 +2919,7 @@ def __init__( def connector_name(self) -> str: return "etsy" - async def ping_async( + def ping( self, *, timeout: Optional[float] = None, @@ -2811,10 +2931,24 @@ async def ping_async( Ping Check to confirm connectivity to the Etsy API with an application. + + Swagger operation ID: `Ping`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/openapi-ping" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2828,6 +2962,7 @@ async def ping_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2835,14 +2970,14 @@ async def ping_async( return json.loads(response.text) - async def payment_ledger_entries_async( + def payment_ledger_entries( self, shop_id: int, min_created: int, max_created: int, + *, limit: Optional[int] = None, offset: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2852,6 +2987,28 @@ async def payment_ledger_entries_async( Get a shop payment account ledger's entries Retrieve the entries of a shop's payment account ledger. + + Swagger operation ID: `PaymentLedgerEntries`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + min_created: The earliest unix timestamp for when a record was + created. + max_created: The latest unix timestamp for when a record was + created. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2882,7 +3039,7 @@ async def payment_ledger_entries_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2896,6 +3053,7 @@ async def payment_ledger_entries_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2903,7 +3061,7 @@ async def payment_ledger_entries_async( return json.loads(response.text) - async def payment_get_entry_id_async( + def payment_get_entry_id( self, shop_id: int, ledger_entry_ids: str, @@ -2917,6 +3075,22 @@ async def payment_get_entry_id_async( Get a payment from a payment account ledger entry ID Get a Payment from a Payment Account Ledger Entry ID, if applicable. + + Swagger operation ID: `PaymentGetEntryID`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + ledger_entry_ids: Array of integers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2934,7 +3108,7 @@ async def payment_get_entry_id_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2948,6 +3122,7 @@ async def payment_get_entry_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2955,7 +3130,7 @@ async def payment_get_entry_id_async( return json.loads(response.text) - async def payment_get_receipt_async( + def payment_get_receipt( self, shop_id: int, receipt_id: str, @@ -2970,6 +3145,23 @@ async def payment_get_receipt_async( Retrieves a payment from a specific receipt, identified by receipt ID, from a specific shop, identified by shop ID. + + Swagger operation ID: `PaymentGetReceipt`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + receipt_id: The numeric ID for the receipt associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2980,7 +3172,7 @@ async def payment_get_receipt_async( f"/payments" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2994,6 +3186,7 @@ async def payment_get_receipt_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3001,7 +3194,7 @@ async def payment_get_receipt_async( return json.loads(response.text) - async def payments_get_async( + def payments_get( self, shop_id: int, payment_ids: str, @@ -3016,6 +3209,22 @@ async def payments_get_async( Retrieves a list of payments from a shop identified by shop ID. You can also filter results using a list of payment IDs. + + Swagger operation ID: `PaymentsGet`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + payment_ids: A comma-separated array of Payment IDs numbers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3029,7 +3238,7 @@ async def payments_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3043,6 +3252,7 @@ async def payments_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3050,7 +3260,7 @@ async def payments_get_async( return json.loads(response.text) - async def receipt_get_async( + def receipt_get( self, shop_id: int, receipt_id: int, @@ -3064,6 +3274,23 @@ async def receipt_get_async( Get a receipt Retrieves a receipt, identified by a receipt ID, from an Etsy shop. + + Swagger operation ID: `ReceiptGet`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + receipt_id: The numeric ID for the receipt associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3073,7 +3300,7 @@ async def receipt_get_async( f"/{quote(str(receipt_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3087,6 +3314,7 @@ async def receipt_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3094,9 +3322,10 @@ async def receipt_get_async( return json.loads(response.text) - async def receipts_get_async( + def receipts_get( self, shop_id: int, + *, min_created: Optional[int] = None, max_created: Optional[int] = None, min_last_modified: Optional[int] = None, @@ -3105,7 +3334,6 @@ async def receipts_get_async( offset: Optional[int] = None, was_paid: Optional[bool] = None, was_shipped: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3116,6 +3344,36 @@ async def receipts_get_async( Requests the shop receipts from a specific shop, unfiltered or filtered by receipt ID range or offset, date, paid, and/or shipped purchases. + + Swagger operation ID: `ReceiptsGet`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + min_created: The earliest unix timestamp for when a record was + created. + max_created: The latest unix timestamp for when a record was + created. + min_last_modified: The earliest unix timestamp for when a record + last changed. + max_last_modified: The latest unix timestamp for when a record last + changed. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + was_paid: When true, the seller received payment for the product(s) + in this receipt. + was_shipped: When true, the seller shipped the product(s) in this + receipt. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3165,7 +3423,7 @@ async def receipts_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3179,6 +3437,7 @@ async def receipts_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3186,9 +3445,9 @@ async def receipts_get_async( return json.loads(response.text) - async def receipt_create_shipment_async( + def receipt_create_shipment( self, - input: ReceiptCreateShipmentInput, + input: ReceiptCreateShipmentInput | Mapping[str, Any], shop_id: int, receipt_id: int, *, @@ -3206,6 +3465,24 @@ async def receipt_create_shipment_async( the buyer User. When send BCC is true, Etsy sends shipping notifications to the seller as well. When tracking code and carrier name aren't sent, the receipt is marked as shipped only. + + Swagger operation ID: `ReceiptCreateShipment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + receipt_id: The receipt to submit tracking for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3216,7 +3493,7 @@ async def receipt_create_shipment_async( f"/tracking" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3230,6 +3507,7 @@ async def receipt_create_shipment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3237,13 +3515,13 @@ async def receipt_create_shipment_async( return json.loads(response.text) - async def transactions_listing_async( + def transactions_listing( self, shop_id: int, listing_id: int, + *, limit: Optional[int] = None, offset: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3253,6 +3531,26 @@ async def transactions_listing_async( Retrieve a listing's transactions Retrieves the list of transactions associated with a listing. + + Swagger operation ID: `TransactionsListing`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3276,7 +3574,7 @@ async def transactions_listing_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3290,6 +3588,7 @@ async def transactions_listing_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3297,7 +3596,7 @@ async def transactions_listing_async( return json.loads(response.text) - async def transaction_receipt_async( + def transaction_receipt( self, shop_id: int, receipt_id: int, @@ -3311,6 +3610,23 @@ async def transaction_receipt_async( Get a receipt's transaction Retrieves the list of transactions associated with a specific receipt. + + Swagger operation ID: `TransactionReceipt`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + receipt_id: The numeric ID for the receipt associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3321,7 +3637,7 @@ async def transaction_receipt_async( f"/transactions" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3335,6 +3651,7 @@ async def transaction_receipt_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3342,7 +3659,7 @@ async def transaction_receipt_async( return json.loads(response.text) - async def transaction_get_async( + def transaction_get( self, shop_id: int, transaction_id: int, @@ -3356,6 +3673,22 @@ async def transaction_get_async( Get a transaction Retrieves a transaction by transaction ID. + + Swagger operation ID: `TransactionGet`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + transaction_id: The unique numeric ID for a transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3365,7 +3698,7 @@ async def transaction_get_async( f"/{quote(str(transaction_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3379,6 +3712,7 @@ async def transaction_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3386,12 +3720,12 @@ async def transaction_get_async( return json.loads(response.text) - async def transaction_get_shop_async( + def transaction_get_shop( self, shop_id: int, + *, limit: Optional[int] = None, offset: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3401,6 +3735,24 @@ async def transaction_get_shop_async( Get a shop's transaction Retrieves the list of transactions associated with a shop. + + Swagger operation ID: `TransactionGetShop`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3420,7 +3772,7 @@ async def transaction_get_shop_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3434,6 +3786,7 @@ async def transaction_get_shop_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3441,12 +3794,12 @@ async def transaction_get_shop_async( return json.loads(response.text) - async def reviews_get_async( + def reviews_get( self, shop_id: int, + *, limit: Optional[int] = None, offset: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3456,6 +3809,24 @@ async def reviews_get_async( Get reviews Retrieves the reviews from a shop given its ID. + + Swagger operation ID: `ReviewsGet`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3475,7 +3846,7 @@ async def reviews_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3489,6 +3860,7 @@ async def reviews_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3496,7 +3868,7 @@ async def reviews_get_async( return json.loads(response.text) - async def shipping_carriers_async( + def shipping_carriers( self, origin_country_iso: str, *, @@ -3510,6 +3882,22 @@ async def shipping_carriers_async( Retrieves a list of available shipping carriers and the mail classes associated with them for a given country. + + Swagger operation ID: `ShippingCarriers`. + + Args: + origin_country_iso: The ISO code of the country from which the + listing ships. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/shipping-carriers" query_params = [] @@ -3520,7 +3908,7 @@ async def shipping_carriers_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3534,6 +3922,7 @@ async def shipping_carriers_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3541,7 +3930,7 @@ async def shipping_carriers_async( return json.loads(response.text) - async def shipping_profiles_async( + def shipping_profiles( self, shop_id: int, *, @@ -3555,13 +3944,28 @@ async def shipping_profiles_async( Retrieves a list of shipping profiles available in the specific Etsy shop identified by its shop ID. + + Swagger operation ID: `ShippingProfiles`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/shops/{quote(str(shop_id), safe='')}/shipping-profiles" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3575,6 +3979,7 @@ async def shipping_profiles_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3582,9 +3987,9 @@ async def shipping_profiles_async( return json.loads(response.text) - async def shipping_create_profile_async( + def shipping_create_profile( self, - input: ShippingCreateProfileInput, + input: ShippingCreateProfileInput | Mapping[str, Any], shop_id: int, *, timeout: Optional[float] = None, @@ -3599,13 +4004,30 @@ async def shipping_create_profile_async( region when creating a shipping profile, but not both. Only one is required. You must pass either a shipping carrier ID and mail class, or both min and max delivery days. + + Swagger operation ID: `ShippingCreateProfile`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/shops/{quote(str(shop_id), safe='')}/shipping-profiles" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3619,6 +4041,7 @@ async def shipping_create_profile_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3626,7 +4049,7 @@ async def shipping_create_profile_async( return json.loads(response.text) - async def shipping_get_profile_async( + def shipping_get_profile( self, shop_id: int, shipping_profile_id: int, @@ -3640,6 +4063,23 @@ async def shipping_get_profile_async( Get a shipping profile Retrieves a shipping profile referenced by shipping profile ID. + + Swagger operation ID: `ShippingGetProfile`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3649,7 +4089,7 @@ async def shipping_get_profile_async( f"/{quote(str(shipping_profile_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3663,9 +4103,10 @@ async def shipping_get_profile_async( request_url, response.status, response.text, + response=response, ) - async def shipping_delete_profile_async( + def shipping_delete_profile( self, shop_id: int, shipping_profile_id: int, @@ -3679,6 +4120,23 @@ async def shipping_delete_profile_async( Delete a shipping profile Deletes a shipping profile by given ID. + + Swagger operation ID: `ShippingDeleteProfile`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3688,7 +4146,7 @@ async def shipping_delete_profile_async( f"/{quote(str(shipping_profile_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -3702,6 +4160,7 @@ async def shipping_delete_profile_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3709,9 +4168,9 @@ async def shipping_delete_profile_async( return json.loads(response.text) - async def shipping_update_profile_async( + def shipping_update_profile( self, - input: ShippingUpdateProfileInput, + input: ShippingUpdateProfileInput | Mapping[str, Any], shop_id: int, shipping_profile_id: int, *, @@ -3724,6 +4183,25 @@ async def shipping_update_profile_async( Update a shipping profile Changes the settings in a shipping profile. + + Swagger operation ID: `ShippingUpdateProfile`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3733,7 +4211,7 @@ async def shipping_update_profile_async( f"/{quote(str(shipping_profile_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -3747,6 +4225,7 @@ async def shipping_update_profile_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3754,13 +4233,13 @@ async def shipping_update_profile_async( return json.loads(response.text) - async def shipping_get_destinations_async( + def shipping_get_destinations( self, shop_id: int, shipping_profile_id: int, + *, limit: Optional[int] = None, offset: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3771,6 +4250,26 @@ async def shipping_get_destinations_async( Retrieves a list of shipping destination objects associated with a shipping profile. + + Swagger operation ID: `ShippingGetDestinations`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3794,7 +4293,7 @@ async def shipping_get_destinations_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3808,6 +4307,7 @@ async def shipping_get_destinations_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3815,9 +4315,9 @@ async def shipping_get_destinations_async( return json.loads(response.text) - async def shipping_create_destination_async( + def shipping_create_destination( self, - input: ShippingCreateDestinationInput, + input: ShippingCreateDestinationInput | Mapping[str, Any], shop_id: int, shipping_profile_id: int, *, @@ -3839,6 +4339,25 @@ async def shipping_create_destination_async( default destination is everywhere. You must also either assign both a shipping carrier ID and mail class or both min delivery days and max delivery days. + + Swagger operation ID: `ShippingCreateDestination`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3849,7 +4368,7 @@ async def shipping_create_destination_async( f"/destinations" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3863,6 +4382,7 @@ async def shipping_create_destination_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3870,7 +4390,7 @@ async def shipping_create_destination_async( return json.loads(response.text) - async def shipping_delete_profile_destination_async( + def shipping_delete_profile_destination( self, shop_id: int, shipping_profile_id: int, @@ -3890,6 +4410,26 @@ async def shipping_delete_profile_destination_async( cannot delete the final shipping destination for any shipping profile. To delete the final shipping destination from a shipping profile, you must delete the entire shipping profile. + + Swagger operation ID: `ShippingDeleteProfileDestination`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + shipping_profile_destination_id: The numeric ID of the shipping + profile destination in the shipping profile associated with the + listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3901,7 +4441,7 @@ async def shipping_delete_profile_destination_async( f"/{quote(str(shipping_profile_destination_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -3915,11 +4455,12 @@ async def shipping_delete_profile_destination_async( request_url, response.status, response.text, + response=response, ) - async def shipping_update_profile_destination_async( + def shipping_update_profile_destination( self, - input: ShippingUpdateProfileDestinationInput, + input: ShippingUpdateProfileDestinationInput | Mapping[str, Any], shop_id: int, shipping_profile_id: str, shipping_profile_destination_id: str, @@ -3934,6 +4475,27 @@ async def shipping_update_profile_destination_async( Updates an existing shipping destination, which can set or reassign the shipping cost, carrier, and class for a destination. + + Swagger operation ID: `ShippingUpdateProfileDestination`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + shipping_profile_destination_id: The numeric ID of the shipping + profile destinationassociated with the listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3945,7 +4507,7 @@ async def shipping_update_profile_destination_async( f"/{quote(str(shipping_profile_destination_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -3959,6 +4521,7 @@ async def shipping_update_profile_destination_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3966,7 +4529,7 @@ async def shipping_update_profile_destination_async( return json.loads(response.text) - async def shipping_get_profile_upgrades_async( + def shipping_get_profile_upgrades( self, shop_id: int, shipping_profile_id: int, @@ -3981,6 +4544,23 @@ async def shipping_get_profile_upgrades_async( Retrieves the list of shipping profile upgrades assigned to a specific shipping profile. + + Swagger operation ID: `ShippingGetProfileUpgrades`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3991,7 +4571,7 @@ async def shipping_get_profile_upgrades_async( f"/upgrades" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4005,6 +4585,7 @@ async def shipping_get_profile_upgrades_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4012,9 +4593,9 @@ async def shipping_get_profile_upgrades_async( return json.loads(response.text) - async def shipping_create_upgrade_async( + def shipping_create_upgrade( self, - input: ShippingCreateUpgradeInput, + input: ShippingCreateUpgradeInput | Mapping[str, Any], shop_id: int, shipping_profile_id: int, *, @@ -4028,6 +4609,25 @@ async def shipping_create_upgrade_async( Creates a new shipping profile upgrade, which can establish a price for a shipping option, such as an alternate carrier or faster delivery. + + Swagger operation ID: `ShippingCreateUpgrade`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4038,7 +4638,7 @@ async def shipping_create_upgrade_async( f"/upgrades" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4052,6 +4652,7 @@ async def shipping_create_upgrade_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4059,7 +4660,7 @@ async def shipping_create_upgrade_async( return json.loads(response.text) - async def shipping_delete_profile_upgrade_async( + def shipping_delete_profile_upgrade( self, shop_id: int, shipping_profile_id: int, @@ -4075,6 +4676,24 @@ async def shipping_delete_profile_upgrade_async( Deletes a shipping profile upgrade and removes the upgrade option from every listing that uses the associated shipping profile. + + Swagger operation ID: `ShippingDeleteProfileUpgrade`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile. + upgrade_id: The numeric ID that is associated with a shipping + upgrade. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4086,7 +4705,7 @@ async def shipping_delete_profile_upgrade_async( f"/{quote(str(upgrade_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -4100,11 +4719,12 @@ async def shipping_delete_profile_upgrade_async( request_url, response.status, response.text, + response=response, ) - async def shipping_update_profile_upgrade_async( + def shipping_update_profile_upgrade( self, - input: ShippingUpdateProfileUpgradeInput, + input: ShippingUpdateProfileUpgradeInput | Mapping[str, Any], shop_id: int, shipping_profile_id: int, upgrade_id: int, @@ -4119,6 +4739,27 @@ async def shipping_update_profile_upgrade_async( Updates a shipping profile upgrade and updates any listings that use the shipping profile. + + Swagger operation ID: `ShippingUpdateProfileUpgrade`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shipping_profile_id: The numeric ID of the shipping profile + associated with the listing. + upgrade_id: The numeric ID that is associated with a shipping + upgrade. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4130,7 +4771,7 @@ async def shipping_update_profile_upgrade_async( f"/{quote(str(upgrade_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -4144,6 +4785,7 @@ async def shipping_update_profile_upgrade_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4151,9 +4793,9 @@ async def shipping_update_profile_upgrade_async( return json.loads(response.text) - async def shop_update_async( + def shop_update( self, - input: ShopUpdateInput, + input: ShopUpdateInput | Mapping[str, Any], shop_id: int, *, timeout: Optional[float] = None, @@ -4166,13 +4808,30 @@ async def shop_update_async( Update a shop. Assumes that all string parameters are provided in the shop's primary language. + + Swagger operation ID: `ShopUpdate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/shops/{quote(str(shop_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -4186,6 +4845,7 @@ async def shop_update_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4193,7 +4853,7 @@ async def shop_update_async( return json.loads(response.text) - async def shop_get_by_owner_id_async( + def shop_get_by_owner_id( self, user_id: str, *, @@ -4206,13 +4866,28 @@ async def shop_get_by_owner_id_async( Get shop by owner ID Retrieves the shop identified by the shop owner's user ID. + + Swagger operation ID: `ShopGetByOwnerID`. + + Args: + user_id: The numeric user ID of the user who owns this shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/users/{quote(str(user_id), safe='')}/shops" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4226,6 +4901,7 @@ async def shop_get_by_owner_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4233,12 +4909,12 @@ async def shop_get_by_owner_id_async( return json.loads(response.text) - async def shop_search_async( + def shop_search( self, shop_name: str, + *, limit: Optional[int] = None, offset: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4248,6 +4924,24 @@ async def shop_search_async( Search shops Returns a list of shops with the matching name. + + Swagger operation ID: `ShopSearch`. + + Args: + shop_name: The shop's name string. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/shops" query_params = [] @@ -4268,7 +4962,7 @@ async def shop_search_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4282,6 +4976,7 @@ async def shop_search_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4289,7 +4984,7 @@ async def shop_search_async( return json.loads(response.text) - async def shop_get_sections_async( + def shop_get_sections( self, shop_id: int, *, @@ -4303,13 +4998,28 @@ async def shop_get_sections_async( Retrieves the list of shop sections in a specific shop identified by shop ID. + + Swagger operation ID: `ShopGetSections`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/shops/{quote(str(shop_id), safe='')}/sections" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4323,6 +5033,7 @@ async def shop_get_sections_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4330,9 +5041,9 @@ async def shop_get_sections_async( return json.loads(response.text) - async def shop_create_section_async( + def shop_create_section( self, - input: ShopCreateSectionInput, + input: ShopCreateSectionInput | Mapping[str, Any], shop_id: int, *, timeout: Optional[float] = None, @@ -4344,13 +5055,30 @@ async def shop_create_section_async( Create a shop section Creates a new section in a specific shop. + + Swagger operation ID: `ShopCreateSection`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/shops/{quote(str(shop_id), safe='')}/sections" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4364,6 +5092,7 @@ async def shop_create_section_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4371,7 +5100,7 @@ async def shop_create_section_async( return json.loads(response.text) - async def user_get_async( + def user_get( self, user_id: int, *, @@ -4384,13 +5113,28 @@ async def user_get_async( Get user Returns user profile for the user identified by a user ID. + + Swagger operation ID: `UserGet`. + + Args: + user_id: The unique positive non-zero numeric ID for an user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/users/{quote(str(user_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4404,6 +5148,7 @@ async def user_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4411,7 +5156,7 @@ async def user_get_async( return json.loads(response.text) - async def shop_get_section_async( + def shop_get_section( self, shop_id: int, shop_section_id: int, @@ -4425,6 +5170,23 @@ async def shop_get_section_async( Get shop section Retrieves a shop section, referenced by section ID and shop ID. + + Swagger operation ID: `ShopGetSection`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shop_section_id: The numeric ID of a section in a specific Etsy + shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4434,7 +5196,7 @@ async def shop_get_section_async( f"/{quote(str(shop_section_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4448,6 +5210,7 @@ async def shop_get_section_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4455,7 +5218,7 @@ async def shop_get_section_async( return json.loads(response.text) - async def user_get_address_async( + def user_get_address( self, user_address_id: int, *, @@ -4469,13 +5232,28 @@ async def user_get_address_async( Retrieves the user's address. Development for this endpoint is in progress. It will only return a 501 response. + + Swagger operation ID: `UserGetAddress`. + + Args: + user_address_id: The numeric ID of the user's address. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/user/addresses/{quote(str(user_address_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4489,6 +5267,7 @@ async def user_get_address_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4496,11 +5275,11 @@ async def user_get_address_async( return json.loads(response.text) - async def user_get_addresses_async( + def user_get_addresses( self, + *, limit: Optional[int] = None, offset: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4510,6 +5289,23 @@ async def user_get_addresses_async( Get user addresses Retrieve a list of user addresses. + + Swagger operation ID: `UserGetAddresses`. + + Args: + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/user/addresses" query_params = [] @@ -4526,7 +5322,7 @@ async def user_get_addresses_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4540,6 +5336,7 @@ async def user_get_addresses_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4547,7 +5344,7 @@ async def user_get_addresses_async( return json.loads(response.text) - async def listing_get_taxonomy_nodes_async( + def listing_get_taxonomy_nodes( self, *, timeout: Optional[float] = None, @@ -4559,10 +5356,24 @@ async def listing_get_taxonomy_nodes_async( Get seller taxonomy nodes Retrieves the full hierarchy tree of seller taxonomy nodes. + + Swagger operation ID: `ListingGetTaxonomyNodes`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/seller-taxonomy/nodes" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4576,6 +5387,7 @@ async def listing_get_taxonomy_nodes_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4583,7 +5395,7 @@ async def listing_get_taxonomy_nodes_async( return json.loads(response.text) - async def listing_get_properties_by_taxonomy_async( + def listing_get_properties_by_taxonomy( self, taxonomy_id: str, *, @@ -4597,6 +5409,23 @@ async def listing_get_properties_by_taxonomy_async( Retrieves a list of product properties, with applicable scales and values, supported for a specific seller taxonomy ID. + + Swagger operation ID: `ListingGetPropertiesByTaxonomy`. + + Args: + taxonomy_id: The unique numeric ID of an Etsy taxonomy node, which + is a metadata category for listings organized into the seller + taxonomy hierarchy tree. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4606,7 +5435,7 @@ async def listing_get_properties_by_taxonomy_async( f"/properties" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4620,6 +5449,7 @@ async def listing_get_properties_by_taxonomy_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4627,15 +5457,15 @@ async def listing_get_properties_by_taxonomy_async( return json.loads(response.text) - async def listing_get_shop_async( + def listing_get_shop( self, shop_id: int, + *, state: Optional[str] = None, limit: Optional[int] = None, offset: Optional[int] = None, sort_on: Optional[str] = None, sort_order: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4646,6 +5476,28 @@ async def listing_get_shop_async( Returns listings that belong to a Shop. Listings can be filtered using the state parameter. + + Swagger operation ID: `ListingGetShop`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + state: An enumerated string from any of: active or inactive. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + sort_on: The value to sort a search result of listings on. + sort_order: The ascending(up) or descending(down) order to sort + listings by. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4680,7 +5532,7 @@ async def listing_get_shop_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4694,6 +5546,7 @@ async def listing_get_shop_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4701,9 +5554,9 @@ async def listing_get_shop_async( return json.loads(response.text) - async def listing_create_async( + def listing_create( self, - input: ListingCreateInput, + input: ListingCreateInput | Mapping[str, Any], shop_id: int, *, timeout: Optional[float] = None, @@ -4715,13 +5568,30 @@ async def listing_create_async( Create a draft listing Creates a physical draft listing product in a shop on the Etsy channel. + + Swagger operation ID: `ListingCreate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/shops/{quote(str(shop_id), safe='')}/listings" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4735,6 +5605,7 @@ async def listing_create_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4742,11 +5613,11 @@ async def listing_create_async( return json.loads(response.text) - async def listing_get_async( + def listing_get( self, listing_id: int, - includes: Optional[str] = None, *, + includes: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4756,6 +5627,24 @@ async def listing_get_async( Get a listing Retrieves a listing record by listing ID. + + Swagger operation ID: `ListingGet`. + + Args: + listing_id: The numeric ID for the listing associated to this + transaction. + includes: An enumerated string that attaches a valid association. + Acceptable inputs are 'shop', 'images' and 'user'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4770,7 +5659,7 @@ async def listing_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4784,9 +5673,10 @@ async def listing_get_async( request_url, response.status, response.text, + response=response, ) - async def listing_delete_async( + def listing_delete( self, listing_id: int, *, @@ -4802,13 +5692,29 @@ async def listing_delete_async( the state is one of the following: SOLD_OUT, DRAFT, EXPIRED, INACTIVE, ACTIVE and is_available or ACTIVE and has seller flags: SUPRESSED (frozen), VACATION, CUSTOM_SHOPS (pattern), SELL_ON_FACEBOOK + + Swagger operation ID: `ListingDelete`. + + Args: + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/listings/{quote(str(listing_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -4822,10 +5728,12 @@ async def listing_delete_async( request_url, response.status, response.text, + response=response, ) - async def listing_get_active_async( + def listing_get_active( self, + *, limit: Optional[int] = None, offset: Optional[int] = None, keywords: Optional[str] = None, @@ -4835,7 +5743,6 @@ async def listing_get_active_async( max_price: Optional[float] = None, taxonomy_id: Optional[int] = None, shop_location: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4846,6 +5753,38 @@ async def listing_get_active_async( A list of all active listings on Etsy paginated by their creation date. Without sort order listings will be returned newest-first by default. + + Swagger operation ID: `ListingGetActive`. + + Args: + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + keywords: Search term or phrase that must appear in all results. + sort_on: The value to sort a search result of listings on. NOTE: + sort on only works when combined with one of the search options + (keywords, region, etc.). + sort_order: The ascending(up) or descending(down) order to sort + listings by. NOTE: sort_order only works when combined with one + of the search options (keywords, region, etc.). + min_price: The minimum price of listings to be returned by a search + result. + max_price: The maximum price of listings to be returned by a search + result. + taxonomy_id: The numeric taxonomy ID of the listing. The seller + manages listing taxonomy IDs for their shop. + shop_location: Filters by shop location. If location cannot be + parsed, Etsy responds with an error. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/listings/active" query_params = [] @@ -4897,7 +5836,7 @@ async def listing_get_active_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4911,6 +5850,7 @@ async def listing_get_active_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4918,13 +5858,13 @@ async def listing_get_active_async( return json.loads(response.text) - async def listing_get_active_by_shop_async( + def listing_get_active_by_shop( self, shop_id: int, + *, limit: Optional[int] = None, offset: Optional[int] = None, keywords: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4935,6 +5875,25 @@ async def listing_get_active_by_shop_async( Retrieves a list of all active listings on Etsy in a specific shop, paginated by listing creation date. + + Swagger operation ID: `ListingGetActiveByShop`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + keywords: Search term or phrase that must appear in all results. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4959,7 +5918,7 @@ async def listing_get_active_by_shop_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4973,6 +5932,7 @@ async def listing_get_active_by_shop_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4980,11 +5940,11 @@ async def listing_get_active_by_shop_async( return json.loads(response.text) - async def listing_get_by_id_async( + def listing_get_by_id( self, listing_ids: str, - includes: Optional[str] = None, *, + includes: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4995,6 +5955,23 @@ async def listing_get_by_id_async( Allows to query multiple listing IDs at once. Limit 100 IDs maximum per query. + + Swagger operation ID: `ListingGetByID`. + + Args: + listing_ids: The array of numeric IDs for the listings in a + specific Etsy shop. + includes: An enumerated string that attaches a valid association. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/listings/batch" query_params = [] @@ -5010,7 +5987,7 @@ async def listing_get_by_id_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5024,6 +6001,7 @@ async def listing_get_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5031,12 +6009,12 @@ async def listing_get_by_id_async( return json.loads(response.text) - async def listing_get_featured_async( + def listing_get_featured( self, shop_id: int, + *, limit: Optional[int] = None, offset: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5046,6 +6024,24 @@ async def listing_get_featured_async( Get featured listings by shop Retrieves listings associated to a shop that are featured. + + Swagger operation ID: `ListingGetFeatured`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5065,7 +6061,7 @@ async def listing_get_featured_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5079,6 +6075,7 @@ async def listing_get_featured_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5086,7 +6083,7 @@ async def listing_get_featured_async( return json.loads(response.text) - async def listing_delete_property_async( + def listing_delete_property( self, shop_id: int, listing_id: int, @@ -5101,6 +6098,24 @@ async def listing_delete_property_async( Delete a listing property Deletes a property from a listing. + + Swagger operation ID: `ListingDeleteProperty`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + property_id: The unique ID of an Etsy listing property. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5112,7 +6127,7 @@ async def listing_delete_property_async( f"/{quote(str(property_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -5126,11 +6141,12 @@ async def listing_delete_property_async( request_url, response.status, response.text, + response=response, ) - async def listing_update_property_async( + def listing_update_property( self, - input: ListingUpdatePropertyInput, + input: ListingUpdatePropertyInput | Mapping[str, Any], shop_id: int, listing_id: int, property_id: int, @@ -5147,6 +6163,26 @@ async def listing_update_property_async( a listing. Each offering requires both a value and a value ID that are valid for a scale ID assigned to the listing or that you assign to the listing with this request. + + Swagger operation ID: `ListingUpdateProperty`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + property_id: The unique ID of an Etsy listing property. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5158,7 +6194,7 @@ async def listing_update_property_async( f"/{quote(str(property_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -5172,6 +6208,7 @@ async def listing_update_property_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5179,7 +6216,7 @@ async def listing_update_property_async( return json.loads(response.text) - async def listing_get_property_async( + def listing_get_property( self, listing_id: int, property_id: int, @@ -5194,6 +6231,23 @@ async def listing_get_property_async( Retrieves a listing's property. Development for this endpoint is in progress. It will only return a 501 response. + + Swagger operation ID: `ListingGetProperty`. + + Args: + listing_id: The numeric ID for the listing associated to this + transaction. + property_id: The unique ID of an Etsy listing property. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5203,7 +6257,7 @@ async def listing_get_property_async( f"/{quote(str(property_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5217,6 +6271,7 @@ async def listing_get_property_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5224,7 +6279,7 @@ async def listing_get_property_async( return json.loads(response.text) - async def listing_get_properties_async( + def listing_get_properties( self, shop_id: int, listing_id: int, @@ -5238,6 +6293,23 @@ async def listing_get_properties_async( Get a listing's properties Returns a list of a listing's properties. + + Swagger operation ID: `ListingGetProperties`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5248,7 +6320,7 @@ async def listing_get_properties_async( f"/properties" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5262,6 +6334,7 @@ async def listing_get_properties_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5269,9 +6342,9 @@ async def listing_get_properties_async( return json.loads(response.text) - async def listing_update_async( + def listing_update( self, - input: ListingUpdateInput, + input: ListingUpdateInput | Mapping[str, Any], shop_id: int, listing_id: int, *, @@ -5285,6 +6358,25 @@ async def listing_update_async( Updates a listing, identified by a listing ID, for a specific shop identified by a shop ID. + + Swagger operation ID: `ListingUpdate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5294,7 +6386,7 @@ async def listing_update_async( f"/{quote(str(listing_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -5308,6 +6400,7 @@ async def listing_update_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5315,13 +6408,13 @@ async def listing_update_async( return json.loads(response.text) - async def listing_get_by_receipt_async( + def listing_get_by_receipt( self, shop_id: int, receipt_id: int, + *, limit: Optional[int] = None, offset: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5331,6 +6424,27 @@ async def listing_get_by_receipt_async( Get listings by shop receipt Gets all listings associated with a receipt. + + Swagger operation ID: `ListingGetByReceipt`. + + Args: + shop_id: The numeric ID for the receipt associated to this + transaction. + receipt_id: The unique positive non-zero numeric ID for an Etsy + Shop. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5354,7 +6468,7 @@ async def listing_get_by_receipt_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5368,6 +6482,7 @@ async def listing_get_by_receipt_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5375,15 +6490,15 @@ async def listing_get_by_receipt_async( return json.loads(response.text) - async def listing_get_by_section_id_async( + def listing_get_by_section_id( self, shop_id: int, shop_section_ids: str, + *, limit: Optional[int] = None, offset: Optional[int] = None, sort_on: Optional[str] = None, sort_order: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5393,6 +6508,29 @@ async def listing_get_by_section_id_async( Get listings by shop section ID Retrieves all the listings from the section of a specific shop. + + Swagger operation ID: `ListingGetBySectionID`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + shop_section_ids: A array of numeric IDs for all sections in a + specific Etsy shop. + limit: The maximum number of results to return. + offset: The number of records to skip before selecting the first + result. + sort_on: The value to sort a search result of listings on. + sort_order: The ascending(up) or descending(down) order to sort + listings by. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5426,7 +6564,7 @@ async def listing_get_by_section_id_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5440,6 +6578,7 @@ async def listing_get_by_section_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5447,7 +6586,7 @@ async def listing_get_by_section_id_async( return json.loads(response.text) - async def listing_get_file_async( + def listing_get_file( self, shop_id: int, listing_id: int, @@ -5463,6 +6602,25 @@ async def listing_get_file_async( Retrieves a single file associated with the given digital listing. Requesting a file from a physical listing returns an empty result. + + Swagger operation ID: `ListingGetFile`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + listing_file_id: The unique numeric ID of a file associated with a + digital listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5474,7 +6632,7 @@ async def listing_get_file_async( f"/{quote(str(listing_file_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5488,6 +6646,7 @@ async def listing_get_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5495,7 +6654,7 @@ async def listing_get_file_async( return json.loads(response.text) - async def listing_delete_file_async( + def listing_delete_file( self, shop_id: int, listing_id: int, @@ -5513,6 +6672,25 @@ async def listing_delete_file_async( converts into a physical listing. The response to a delete request returns a list of the remaining file records associated with the given listing. + + Swagger operation ID: `ListingDeleteFile`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + listing_file_id: The unique numeric ID of a file associated with a + digital listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5524,7 +6702,7 @@ async def listing_delete_file_async( f"/{quote(str(listing_file_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -5538,9 +6716,10 @@ async def listing_delete_file_async( request_url, response.status, response.text, + response=response, ) - async def listing_get_files_async( + def listing_get_files( self, shop_id: int, listing_id: int, @@ -5555,6 +6734,24 @@ async def listing_get_files_async( Retrieves all the files associated with the given digital listing. Requesting files from a physical listing returns an empty result. + + Swagger operation ID: `ListingGetFiles`. + + Args: + shop_id: The numeric ID for the listing associated to this + transaction. + listing_id: The unique positive non-zero numeric ID for an Etsy + Shop. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5565,7 +6762,7 @@ async def listing_get_files_async( f"/files" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5579,6 +6776,7 @@ async def listing_get_files_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5586,9 +6784,9 @@ async def listing_get_files_async( return json.loads(response.text) - async def listing_upload_async( + def listing_upload( self, - input: ListingUploadInput, + input: ListingUploadInput | Mapping[str, Any], shop_id: int, listing_id: int, *, @@ -5606,6 +6804,25 @@ async def listing_upload_async( upload. Associating an existing file to a physical listing converts the physical listing into a digital listing, which removes all shipping costs and any product and inventory variations. + + Swagger operation ID: `ListingUpload`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5616,7 +6833,7 @@ async def listing_upload_async( f"/files" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5630,6 +6847,7 @@ async def listing_upload_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5637,7 +6855,7 @@ async def listing_upload_async( return json.loads(response.text) - async def listing_get_image_async( + def listing_get_image( self, shop_id: int, listing_id: int, @@ -5653,6 +6871,25 @@ async def listing_get_image_async( Retrieves the references and metadata for a listing image with a specific image ID. + + Swagger operation ID: `ListingGetImage`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + listing_image_id: The numeric ID of the primary listing image for + this transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5664,7 +6901,7 @@ async def listing_get_image_async( f"/{quote(str(listing_image_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5678,6 +6915,7 @@ async def listing_get_image_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5685,7 +6923,7 @@ async def listing_get_image_async( return json.loads(response.text) - async def listing_delete_image_async( + def listing_delete_image( self, shop_id: int, listing_id: int, @@ -5702,6 +6940,25 @@ async def listing_delete_image_async( Deletes a listing image. A copy of the file remains on our servers, and so a deleted image may be re-associated with the listing without re-uploading the original image. + + Swagger operation ID: `ListingDeleteImage`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + listing_image_id: The numeric ID of the primary listing image for + this transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5713,7 +6970,7 @@ async def listing_delete_image_async( f"/{quote(str(listing_image_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -5727,9 +6984,10 @@ async def listing_delete_image_async( request_url, response.status, response.text, + response=response, ) - async def listing_get_images_async( + def listing_get_images( self, shop_id: int, listing_id: int, @@ -5744,6 +7002,23 @@ async def listing_get_images_async( Retrieves all listing image resources for a listing with a specific listing ID. + + Swagger operation ID: `ListingGetImages`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5754,7 +7029,7 @@ async def listing_get_images_async( f"/images" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5768,6 +7043,7 @@ async def listing_get_images_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5775,9 +7051,9 @@ async def listing_get_images_async( return json.loads(response.text) - async def listing_upload_image_async( + def listing_upload_image( self, - input: ListingUploadImageInput, + input: ListingUploadImageInput | Mapping[str, Any], shop_id: int, listing_id: int, *, @@ -5796,6 +7072,25 @@ async def listing_upload_image_async( parameter. When a request contains both image and listing image ID parameter values, the endpoint uploads the image in the image parameter only. + + Swagger operation ID: `ListingUploadImage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5806,7 +7101,7 @@ async def listing_upload_image_async( f"/images" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5820,6 +7115,7 @@ async def listing_upload_image_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5827,11 +7123,11 @@ async def listing_upload_image_async( return json.loads(response.text) - async def listing_get_inventory_async( + def listing_get_inventory( self, listing_id: int, - includes: Optional[str] = None, *, + includes: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5844,6 +7140,23 @@ async def listing_get_inventory_async( using the Etsy.com inventory tools have no inventory records. This endpoint returns SKU data if you are the owner of the inventory records being fetched. + + Swagger operation ID: `ListingGetInventory`. + + Args: + listing_id: The numeric ID for the listing associated to this + transaction. + includes: An enumerated string that attaches an valid association. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5858,7 +7171,7 @@ async def listing_get_inventory_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5872,6 +7185,7 @@ async def listing_get_inventory_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5879,9 +7193,9 @@ async def listing_get_inventory_async( return json.loads(response.text) - async def listing_update_inventory_async( + def listing_update_inventory( self, - input: ListingUpdateInventoryInput, + input: ListingUpdateInventoryInput | Mapping[str, Any], listing_id: str, *, timeout: Optional[float] = None, @@ -5897,13 +7211,31 @@ async def listing_update_inventory_async( and/or price are incompatible with values in on property fields. When setting a price, assign a float equal to amount divided by divisor as specified in the money resource. + + Swagger operation ID: `ListingUpdateInventory`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/listings/{quote(str(listing_id), safe='')}/inventory" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -5917,6 +7249,7 @@ async def listing_update_inventory_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5924,7 +7257,7 @@ async def listing_update_inventory_async( return json.loads(response.text) - async def listing_get_offering_async( + def listing_get_offering( self, listing_id: int, product_id: int, @@ -5939,6 +7272,26 @@ async def listing_get_offering_async( Get a listing's offering Get an offering for a listing. + + Swagger operation ID: `ListingGetOffering`. + + Args: + listing_id: The numeric ID for the listing associated to this + transaction. + product_id: The numeric ID for the product associated to this + transaction. + product_offering_id: The numeric ID for the product offering + associated to this transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5950,7 +7303,7 @@ async def listing_get_offering_async( f"/{quote(str(product_offering_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5964,6 +7317,7 @@ async def listing_get_offering_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5971,7 +7325,7 @@ async def listing_get_offering_async( return json.loads(response.text) - async def listing_get_product_async( + def listing_get_product( self, listing_id: int, product_id: int, @@ -5985,6 +7339,23 @@ async def listing_get_product_async( Get a listing's product Retrieve a listing product by ID. + + Swagger operation ID: `ListingGetProduct`. + + Args: + listing_id: The listing to return a listing product for. + product_id: The numeric ID for a specific product purchased from a + listing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5995,7 +7366,7 @@ async def listing_get_product_async( f"/{quote(str(product_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6009,6 +7380,7 @@ async def listing_get_product_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6016,7 +7388,7 @@ async def listing_get_product_async( return json.loads(response.text) - async def listing_get_translation_async( + def listing_get_translation( self, shop_id: int, listing_id: int, @@ -6031,6 +7403,25 @@ async def listing_get_translation_async( Get a listing's translation Returns the translation for a listing in the given language. + + Swagger operation ID: `ListingGetTranslation`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + language: The IETF language tag for the language of this + translation. Ex: de, en, es, fr, it, ja, nl, pl, pt, ru. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6042,7 +7433,7 @@ async def listing_get_translation_async( f"/{quote(str(language), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6056,6 +7447,7 @@ async def listing_get_translation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6063,9 +7455,9 @@ async def listing_get_translation_async( return json.loads(response.text) - async def listing_create_translation_async( + def listing_create_translation( self, - input: ListingCreateTranslationInput, + input: ListingCreateTranslationInput | Mapping[str, Any], shop_id: int, listing_id: int, language: str, @@ -6079,6 +7471,27 @@ async def listing_create_translation_async( Create a listing translation Creates a listing translation by listing ID and language. + + Swagger operation ID: `ListingCreateTranslation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + language: The IETF language tag for the language of this + translation. Ex: de, en, es, fr, it, ja, nl, pl, pt, ru. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6090,7 +7503,7 @@ async def listing_create_translation_async( f"/{quote(str(language), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6104,6 +7517,7 @@ async def listing_create_translation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6111,9 +7525,9 @@ async def listing_create_translation_async( return json.loads(response.text) - async def listing_update_translation_async( + def listing_update_translation( self, - input: ListingUpdateTranslationInput, + input: ListingUpdateTranslationInput | Mapping[str, Any], shop_id: int, listing_id: int, language: str, @@ -6127,6 +7541,27 @@ async def listing_update_translation_async( Update a listing translation Updates a listing translation by listing ID and language. + + Swagger operation ID: `ListingUpdateTranslation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + language: The IETF language tag for the language of this + translation. Ex: de, en, es, fr, it, ja, nl, pl, pt, ru. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6138,7 +7573,7 @@ async def listing_update_translation_async( f"/{quote(str(language), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -6152,6 +7587,7 @@ async def listing_update_translation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6159,7 +7595,7 @@ async def listing_update_translation_async( return json.loads(response.text) - async def listing_get_variation_async( + def listing_get_variation( self, shop_id: int, listing_id: int, @@ -6173,6 +7609,23 @@ async def listing_get_variation_async( Get listing's variation images Gets all variation images on a listing. + + Swagger operation ID: `ListingGetVariation`. + + Args: + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6183,7 +7636,7 @@ async def listing_get_variation_async( f"/variation-images" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6197,6 +7650,7 @@ async def listing_get_variation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6204,9 +7658,9 @@ async def listing_get_variation_async( return json.loads(response.text) - async def listing_update_variation_async( + def listing_update_variation( self, - input: ListingUpdateVariationInput, + input: ListingUpdateVariationInput | Mapping[str, Any], shop_id: int, listing_id: int, *, @@ -6219,6 +7673,25 @@ async def listing_update_variation_async( Update a listing's variation images Creates variation images on a listing. + + Swagger operation ID: `ListingUpdateVariation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + shop_id: The unique positive non-zero numeric ID for an Etsy Shop. + listing_id: The numeric ID for the listing associated to this + transaction. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6229,7 +7702,7 @@ async def listing_update_variation_async( f"/variation-images" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6243,6 +7716,7 @@ async def listing_update_variation_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/eventbrite.py b/src/azure/connectors/eventbrite.py index 8708f54..44f5129 100644 --- a/src/azure/connectors/eventbrite.py +++ b/src/azure/connectors/eventbrite.py @@ -5,21 +5,36 @@ from __future__ import annotations -from dataclasses import dataclass -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "EventbriteClient", + "CreateEventResponse", + "GetCategoriesResponse", + "GetEventsForOrganizationResponse", + "GetEventsForOrganizerResponse", + "GetMyEventsResponse", + "GetMyVenuesResponse", + "GetOrdersResponse", + "GetOrganizationsResponse", + "GetOrganizersResponse", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,27 +44,27 @@ class CreateEventResponse: Response for Create event """ - name: Optional[Dict[str, Any]] = None - description: Optional[Dict[str, Any]] = None - id: Optional[str] = None + name: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + description: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The id of the event.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The URL of the event.""" - start: Optional[Dict[str, Any]] = None - end: Optional[Dict[str, Any]] = None - created: Optional[str] = None + start: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + end: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + created: Optional[str] = dataclass_field(default=None, kw_only=True) """The date-time the event was created at.""" - changed: Optional[str] = None + changed: Optional[str] = dataclass_field(default=None, kw_only=True) """The date-time the event was changed at.""" - capacity: Optional[int] = None + capacity: Optional[int] = dataclass_field(default=None, kw_only=True) """The capacity of the event.""" - online_event: Optional[bool] = None + online_event: Optional[bool] = dataclass_field(default=None, kw_only=True) """A boolean indicating whether or not the event is online.""" - organizer_id: Optional[str] = None + organizer_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The id of the organizer of the event.""" - venue_id: Optional[str] = None + venue_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The id of the venue of the event.""" - category_id: Optional[str] = None + category_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The id of the category of the event.""" @@ -68,7 +83,7 @@ class GetOrganizersResponse: Response for Get organizers """ - organizers: Optional[List[Dict[str, Any]]] = None + organizers: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -77,7 +92,7 @@ class GetMyVenuesResponse: Response for Get venues """ - venues: Optional[List[Dict[str, Any]]] = None + venues: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -86,7 +101,7 @@ class GetCategoriesResponse: Response for Get categories """ - categories: Optional[List[Dict[str, Any]]] = None + categories: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -95,7 +110,7 @@ class GetMyEventsResponse: Response for Get organization events """ - events: Optional[List[Dict[str, Any]]] = None + events: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) GetEventsForOrganizerResponse = List[Dict[str, Any]] @@ -109,16 +124,16 @@ class EventbriteClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -129,8 +144,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -138,8 +153,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -151,7 +166,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -166,7 +181,46 @@ def __init__( def connector_name(self) -> str: return "eventbrite" - async def create_event_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def create_event( self, organization_id: str, event_name_html: str, @@ -176,6 +230,7 @@ async def create_event_async( event_start_timezone: str, event_end_timezone: str, event_currency: str, + *, event_organizer_id: Optional[str] = None, event_venue_id: Optional[str] = None, event_category_id: Optional[str] = None, @@ -188,7 +243,6 @@ async def create_event_async( event_hide_start_date: Optional[bool] = None, event_hide_end_date: Optional[bool] = None, event_show_remaining: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -198,6 +252,43 @@ async def create_event_async( Create event Create a new Eventbrite event. + + Swagger operation ID: `CreateEventV2`. + + Args: + organization_id: Select the organization. + event_name_html: The name of the event. + event_description_html: The description on the event page. + event_start_utc: Start time (UTC format Ex. 2020-01-12T12:00:00Z). + event_end_utc: End time (UTC format Ex. 2020-01-13T15:00:00Z). + event_start_timezone: Timezone of the event. + event_end_timezone: Timezone of the event. + event_currency: Currency for this Event's transactions. + event_organizer_id: The organizer of the event. + event_venue_id: A previously-created venue to associate with this + event. + event_category_id: The category of the event. + event_password: Password needed to see the event in unlisted mode. + event_capacity: Set specific capacity (if omitted, sums ticket + capacities). + event_shareable: If users can share the event on social media. + event_invite_only: Only invited users can see the event page. + event_online_event: Whether the event is online-only (no venue). + event_listed: If the event is publicly listed and searchable. + event_hide_start_date: Whether the start date should be hidden. + event_hide_end_date: Whether the end date should be hidden. + event_show_remaining: If the remaining number of tickets is + publicly visible on the event page. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -295,7 +386,7 @@ async def create_event_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -309,6 +400,7 @@ async def create_event_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -316,13 +408,14 @@ async def create_event_async( return json.loads(response.text) - async def update_event_async( + def update_event( self, id: str, organization_id: str, event_start_timezone: str, event_end_timezone: str, event_currency: str, + *, event_name_html: Optional[str] = None, event_description_html: Optional[str] = None, event_start_utc: Optional[str] = None, @@ -339,7 +432,6 @@ async def update_event_async( event_hide_start_date: Optional[bool] = None, event_hide_end_date: Optional[bool] = None, event_show_remaining: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -349,6 +441,45 @@ async def update_event_async( Update event Update an existing event. + + Swagger operation ID: `UpdateEventV2`. + + Args: + id: Event to update. + organization_id: Select the organization. + event_start_timezone: Timezone of the event. + event_end_timezone: Timezone of the event. + event_currency: Currency for this Event's transactions. + event_name_html: The name of the event. + event_description_html: The description on the event page. + event_start_utc: Start time (UTC format Ex. 2017-01-12T13:45:30Z). + event_end_utc: End time (UTC format Ex. 2017-01-12T16:45:30Z). + event_organizer_id: The organizer of the event. + event_venue_id: A previously-created venue to associate with this + event. + event_category_id: The category of the event. + event_password: Password needed to see the event in unlisted mode. + event_capacity: Set specific capacity (if omitted, sums ticket + capacities). + event_shareable: Set specific capacity (if omitted, sums ticket + capacities). + event_invite_only: Only invited users can see the event page. + event_online_event: Whether the event is online-only (no venue). + event_listed: If the event is publicly listed and searchable. + event_hide_start_date: Whether the start date should be hidden. + event_hide_end_date: Whether the start date should be hidden. + event_show_remaining: If the remaining number of tickets is + publicly visible on the event page. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -454,7 +585,7 @@ async def update_event_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -468,6 +599,7 @@ async def update_event_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -475,45 +607,84 @@ async def update_event_async( return json.loads(response.text) - async def get_organizations_async( + def list_organizations( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ GetOrganizations Get a list of organizations for your account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetOrganizations`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v3/users/me/organizations/" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def get_organizers_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_organizers( self, organization_id: str, *, @@ -521,11 +692,30 @@ async def get_organizers_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get organizers Get a list of organizers for organization. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetOrganizersV2`. + + Args: + organization_id: Select the organization. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -534,29 +724,50 @@ async def get_organizers_async( f"/{quote(str(organization_id), safe='')}" f"/organizers" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("organizers", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_my_venues_async( + def list_my_venues( self, organization_id: str, *, @@ -564,75 +775,154 @@ async def get_my_venues_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get venues Get venues for organization. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMyVenuesV2`. + + Args: + organization_id: Select the organization. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v3/organizations/{quote(str(organization_id), safe='')}/venues/" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("venues", []): + yield item - async def get_categories_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_categories( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get categories Get the Eventbrite event categories. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetCategories`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v3/categories/" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("categories", []): + yield item - async def get_organization_events_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_organization_events( self, organization_id: str, order_by: str, @@ -642,11 +932,32 @@ async def get_organization_events_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get organization events Get organization events. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetOrganizationEvents`. + + Args: + organization_id: Select the organization. + order_by: Order of the returned events. + status: Status of the returned events. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -663,27 +974,48 @@ async def get_organization_events_async( query_params.append(f"status={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("events", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/eventhubs.py b/src/azure/connectors/eventhubs.py index efa27f8..6c0cfaa 100644 --- a/src/azure/connectors/eventhubs.py +++ b/src/azure/connectors/eventhubs.py @@ -5,21 +5,32 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "EventhubsClient", + "Event", + "ObjectEntity", + "SendEvent", + "SendEventsInput", + "SystemProperties", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,22 +40,25 @@ class Event: Response for When events are available in Event Hub """ - content_data: Optional[ObjectEntity] = field( + content_data: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentData"}, ) - properties: Optional[Dict[str, ObjectEntity]] = field( + properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Key-value pairs for each application property""" - system_properties: Optional[SystemProperties] = field( + system_properties: Optional[SystemProperties | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SystemProperties"}, ) -SendEventsInput = List["SendEvent"] +SendEventsInput = List["SendEvent | Mapping[str, Any]"] @dataclass @@ -53,7 +67,7 @@ class ObjectEntity: Response for Generate event schema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -66,23 +80,27 @@ class SystemProperties: Definition: SystemProperties """ - enqueued_time_utc: Optional[str] = field( + enqueued_time_utc: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnqueuedTimeUtc"}, ) """Enqueued time""" - offset: Optional[str] = field( + offset: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Offset"}, ) """Offset in a partition""" - partition_key: Optional[str] = field( + partition_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PartitionKey"}, ) """Partition Key""" - sequence_number: Optional[int] = field( + sequence_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SequenceNumber"}, ) """Sequence number""" @@ -94,13 +112,15 @@ class SendEvent: Definition: SendEvent """ - content_data: Optional[str] = field( + content_data: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentData"}, ) """Content of the event""" - properties: Optional[Dict[str, ObjectEntity]] = field( + properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Key-value pairs for each application property""" @@ -114,16 +134,16 @@ class EventhubsClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -134,8 +154,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -143,8 +163,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -156,7 +176,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -171,12 +191,51 @@ def __init__( def connector_name(self) -> str: return "eventhubs" - async def send_event_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def send_event( self, - input: SendEvent, + input: SendEvent | Mapping[str, Any], event_hub_name: str, - partition_key: Optional[str] = None, *, + partition_key: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -186,6 +245,24 @@ async def send_event_async( Send event Send event. + + Swagger operation ID: `SendEvent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + event_hub_name: Name of the Event Hub. + partition_key: Partition key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -200,7 +277,7 @@ async def send_event_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -214,9 +291,10 @@ async def send_event_async( request_url, response.status, response.text, + response=response, ) - async def send_events_async( + def send_events( self, input: SendEventsInput, event_hub_name: str, @@ -231,6 +309,23 @@ async def send_events_async( Send one or more events to the Event Hub partition Send one or more events to the Event Hub partition. + + Swagger operation ID: `SendEvents`. + + Args: + input: The request body. + event_hub_name: Name of the Event Hub. + partition_key: Partition key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -244,7 +339,7 @@ async def send_events_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -258,81 +353,160 @@ async def send_events_async( request_url, response.status, response.text, + response=response, ) - async def get_event_hubs_async( + def list_event_hubs( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[str]: """ Get all Event Hubs in a namespace Get all Event Hubs in a namespace. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetEventHubs`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[str]: An Azure Core pager over connector results. Consume + it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/eventhubs" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[str]: + for item in page: + yield item + + return None, items() - async def get_content_types_async( + return ItemPaged(get_next, extract_data) + + def list_content_types( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[str]: """ Get all content types Get all content types. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetContentTypes`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[str]: An Azure Core pager over connector results. Consume + it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/contenttypes" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[str]: + for item in page: + yield item - async def get_consumer_groups_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_consumer_groups( self, event_hub_name: str, *, @@ -340,11 +514,30 @@ async def get_consumer_groups_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[str]: """ Get all the consumer groups for an event hub Get all the consumer groups for an event hub. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetConsumerGroups`. + + Args: + event_hub_name: The Event Hub name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[str]: An Azure Core pager over connector results. Consume + it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/consumergroups" query_params = [] @@ -354,29 +547,50 @@ async def get_consumer_groups_async( query_params.append(f"eventHubName={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[str]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_partition_keys_async( + def list_partition_keys( self, event_hub_name: str, *, @@ -384,11 +598,30 @@ async def get_partition_keys_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[str]: """ Get all partition keys in an Event Hub Get all partition keys in an Event Hub. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetPartitionKeys`. + + Args: + event_hub_name: The Event Hub name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[str]: An Azure Core pager over connector results. Consume + it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/partitions" query_params = [] @@ -398,33 +631,54 @@ async def get_partition_keys_async( query_params.append(f"eventHubName={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[str]: + for item in page: + yield item - async def generate_event_schema_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def generate_event_schema( self, content_type: str, - content_schema: Optional[str] = None, *, + content_schema: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -434,6 +688,22 @@ async def generate_event_schema_async( Generate event schema Generate event schema V2. + + Swagger operation ID: `GenerateEventSchemaV2`. + + Args: + content_type: Content type. + content_schema: content schema of the event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/eventschemaV2" query_params = [] @@ -449,7 +719,7 @@ async def generate_event_schema_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -463,6 +733,7 @@ async def generate_event_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/excelonline.py b/src/azure/connectors/excelonline.py index efcd3f6..983e8b0 100644 --- a/src/azure/connectors/excelonline.py +++ b/src/azure/connectors/excelonline.py @@ -5,21 +5,46 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "ExcelonlineClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "CreateWorksheetInput", + "DataSetsMetadata", + "GetAllWorksheetsResponse", + "GetColumnsResponse", + "GetTablesResponse", + "Item", + "ItemsList", + "ObjectEntity", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TableToCreate", + "TablesList", + "TabularDataSetsMetadata", + "WorksheetMetadata", +] + # Type Definitions @@ -29,26 +54,30 @@ class TableMetadata: Response for Create table """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Table name""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Table title""" - x_ms_permission: Optional[str] = field( + x_ms_permission: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-permission"}, ) """Table permission""" - x_ms_capabilities: Optional[TableCapabilitiesMetadata] = field( + x_ms_capabilities: Optional[TableCapabilitiesMetadata | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-capabilities"}, ) - schema: Optional[ObjectEntity] = None - referenced_entities: Optional[ObjectEntity] = field( + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + referenced_entities: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "referencedEntities"}, ) - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webUrl"}, ) """Url link""" @@ -60,10 +89,16 @@ class ItemsList: Response for List rows present in a table """ - value: Optional[List[Item]] = None + value: Optional[ + List[Item | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Items""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -75,8 +110,9 @@ class Item: Response for Get a row """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) @@ -87,7 +123,12 @@ class GetAllWorksheetsResponse: Response for Get worksheets """ - value: Optional[List[WorksheetMetadata]] = None + value: Optional[ + List[WorksheetMetadata | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -96,7 +137,7 @@ class CreateWorksheetInput: Create worksheet """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Worksheet name.""" @@ -106,13 +147,13 @@ class WorksheetMetadata: Response for Create worksheet """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Worksheet Id.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Worksheet name.""" - position: Optional[int] = None + position: Optional[int] = dataclass_field(default=None, kw_only=True) """Worksheet position.""" - visibility: Optional[str] = None + visibility: Optional[str] = dataclass_field(default=None, kw_only=True) """Worksheet visibility.""" @@ -122,7 +163,7 @@ class GetTablesResponse: Response for Get tables """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -131,7 +172,7 @@ class GetColumnsResponse: Response for Get table columns """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -140,8 +181,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -150,25 +201,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -180,15 +235,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -200,15 +257,17 @@ class TableToCreate: Definition: TableToCreate """ - table_name: Optional[str] = field( + table_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableName"}, ) """Enter the Excel table name.""" - range: Optional[str] = field(default=None, metadata={"wire_name": "Range"}) + range: str = dataclass_field(metadata={"wire_name": "Range"}) """Enter the table address using A1 notation.""" - columns_names: Optional[str] = field( + columns_names: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ColumnsNames"}, ) """Enter the columns names separated by ';' or ','.""" @@ -220,30 +279,42 @@ class TableCapabilitiesMetadata: Definition: TableCapabilitiesMetadata """ - sort_restrictions: Optional[TableSortRestrictionsMetadata] = field( + sort_restrictions: Optional[ + TableSortRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sortRestrictions"}, ) - filter_restrictions: Optional[TableFilterRestrictionsMetadata] = field( + filter_restrictions: Optional[ + TableFilterRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterRestrictions"}, ) - select_restrictions: Optional[TableSelectRestrictionsMetadata] = field( + select_restrictions: Optional[ + TableSelectRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selectRestrictions"}, ) - is_only_server_pagable: Optional[bool] = field( + is_only_server_pagable: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isOnlyServerPagable"}, ) """Server paging restrictions""" - filter_function_support: Optional[List[str]] = field( + filter_function_support: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterFunctionSupport"}, ) """List of supported filter capabilities""" - server_paging_options: Optional[List[str]] = field( + server_paging_options: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "serverPagingOptions"}, ) """List of supported server-driven paging capabilities""" @@ -255,7 +326,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -268,15 +339,17 @@ class TableSortRestrictionsMetadata: Definition: TableSortRestrictionsMetadata """ - sortable: Optional[bool] = None + sortable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has sortable columns""" - unsortable_properties: Optional[List[str]] = field( + unsortable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "unsortableProperties"}, ) """List of unsortable properties""" - ascending_only_properties: Optional[List[str]] = field( + ascending_only_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ascendingOnlyProperties"}, ) """List of properties which support ascending order only""" @@ -288,15 +361,17 @@ class TableFilterRestrictionsMetadata: Definition: TableFilterRestrictionsMetadata """ - filterable: Optional[bool] = None + filterable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has filterable columns""" - non_filterable_properties: Optional[List[str]] = field( + non_filterable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nonFilterableProperties"}, ) """List of non filterable properties""" - required_properties: Optional[List[str]] = field( + required_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredProperties"}, ) """List of required properties""" @@ -308,7 +383,7 @@ class TableSelectRestrictionsMetadata: Definition: TableSelectRestrictionsMetadata """ - selectable: Optional[bool] = None + selectable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has selectable columns""" @@ -318,7 +393,12 @@ class TablesList: Definition: TablesList """ - value: Optional[List[Table]] = None + value: Optional[ + List[Table | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Tables""" @@ -328,15 +408,21 @@ class Table: Definition: Table """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the table. The name is used at runtime.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the table.""" - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DynamicProperties"}, ) """Additional table properties provided by the connector to the clients.""" @@ -348,24 +434,39 @@ class BlobMetadata: Definition: BlobMetadata """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ @@ -382,16 +483,16 @@ class ExcelonlineClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -402,8 +503,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -411,8 +512,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -424,7 +525,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -446,7 +547,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -478,9 +579,9 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def create_table_async( + def create_table( self, - input: TableToCreate, + input: TableToCreate | Mapping[str, Any], drive: str, file: str, *, @@ -493,6 +594,24 @@ async def create_table_async( Create table Create a new table in the Excel workbook. + + Swagger operation ID: `CreateTable`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -507,7 +626,7 @@ async def create_table_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -521,6 +640,7 @@ async def create_table_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -528,13 +648,13 @@ async def create_table_async( return json.loads(response.text) - async def create_id_column_async( + def create_id_column( self, drive: str, file: str, table: str, - id_column: Optional[str] = None, *, + id_column: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -545,6 +665,24 @@ async def create_id_column_async( Add a key column to an Excel table. The new column will be appended to the right. The new key column must be unique in the table. + + Swagger operation ID: `CreateIdColumn`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + id_column: Provide the key column name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -567,7 +705,7 @@ async def create_id_column_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -581,32 +719,59 @@ async def create_id_column_async( request_url, response.status, response.text, + response=response, ) - async def get_items_async( + def list_items( self, drive: str, file: str, table: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, select: Optional[str] = None, date_time_format: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List rows present in a table List rows present in a table. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItems`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + filter: An ODATA filter query to restrict the entries returned. + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Comma-separated list of columns to retrieve (first 500 by + default). + date_time_format: DateTime Format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -652,11 +817,18 @@ async def get_items_async( query_params.append(f"dateTimeFormat={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -669,31 +841,40 @@ async def get_items_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_item_async( + return ItemPaged(get_next, extract_data) + + def get_item( self, drive: str, file: str, table: str, id: str, id_column: str, - date_time_format: Optional[str] = None, *, + date_time_format: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -704,6 +885,26 @@ async def get_item_async( Get a row using a key column. This action will retrieve all the values of the specified row given a column and key column. + + Swagger operation ID: `GetItem`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + id: Enter the key value. + id_column: Select a column from the drop-down. + date_time_format: DateTime Format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -730,7 +931,7 @@ async def get_item_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -744,6 +945,7 @@ async def get_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -751,7 +953,7 @@ async def get_item_async( return json.loads(response.text) - async def delete_item_async( + def delete_item( self, drive: str, file: str, @@ -768,6 +970,25 @@ async def delete_item_async( Delete a row Delete a row using a key column. + + Swagger operation ID: `DeleteItem`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + id: Enter the key value. + id_column: Select a column from the drop-down. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -789,7 +1010,7 @@ async def delete_item_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -803,18 +1024,19 @@ async def delete_item_async( request_url, response.status, response.text, + response=response, ) - async def patch_item_async( + def patch_item( self, - input: Item, + input: Item | Mapping[str, Any], drive: str, file: str, table: str, id: str, id_column: str, - date_time_format: Optional[str] = None, *, + date_time_format: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -827,6 +1049,28 @@ async def patch_item_async( specified cells and columns left blank will not be updated. In order to append (instead of overwrite) a value, use the \"Get a row\" action to retrieve the content first. + + Swagger operation ID: `PatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + id: Enter the key value. + id_column: Select a column from the drop-down. + date_time_format: DateTime Format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -853,7 +1097,7 @@ async def patch_item_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -867,6 +1111,7 @@ async def patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -874,7 +1119,7 @@ async def patch_item_async( return json.loads(response.text) - async def get_all_worksheets_async( + def list_all_worksheets( self, drive: str, file: str, @@ -883,11 +1128,31 @@ async def get_all_worksheets_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get worksheets Get a list of worksheets in the Excel workbook. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAllWorksheets`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -904,31 +1169,52 @@ async def get_all_worksheets_async( query_params.append("source=" + quote("me", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def create_worksheet_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def create_worksheet( self, - input: CreateWorksheetInput, + input: CreateWorksheetInput | Mapping[str, Any], drive: str, file: str, *, @@ -941,6 +1227,24 @@ async def create_worksheet_async( Create worksheet Create a new worksheet in the Excel workbook. + + Swagger operation ID: `CreateWorksheet`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -958,7 +1262,7 @@ async def create_worksheet_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -972,6 +1276,7 @@ async def create_worksheet_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -979,7 +1284,7 @@ async def create_worksheet_async( return json.loads(response.text) - async def get_tables_async( + def list_tables( self, drive: str, file: str, @@ -988,11 +1293,31 @@ async def get_tables_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get tables Get a list of tables in the Excel workbook. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTables`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1009,36 +1334,57 @@ async def get_tables_async( query_params.append("source=" + quote("me", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def add_row_async( + def add_row( self, - input: Item, + input: Item | Mapping[str, Any], drive: str, file: str, table: str, - date_time_format: Optional[str] = None, *, + date_time_format: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1048,6 +1394,26 @@ async def add_row_async( Add a row into a table Add a new row into the Excel table. + + Swagger operation ID: `AddRowV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + date_time_format: DateTime Format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1072,7 +1438,7 @@ async def add_row_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1086,6 +1452,7 @@ async def add_row_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1093,7 +1460,7 @@ async def add_row_async( return json.loads(response.text) - async def get_columns_async( + def list_columns( self, drive: str, file: str, @@ -1103,11 +1470,32 @@ async def get_columns_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get table columns Get table columns. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetColumns`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1126,24 +1514,45 @@ async def get_columns_async( query_params.append("source=" + quote("me", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/excelonlinebusiness.py b/src/azure/connectors/excelonlinebusiness.py index 9c2c186..667a4a8 100644 --- a/src/azure/connectors/excelonlinebusiness.py +++ b/src/azure/connectors/excelonlinebusiness.py @@ -5,21 +5,63 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "ExcelonlinebusinessClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "Comment", + "CommentDetails", + "CommentsList", + "CreateFileMetadata", + "CreateWorksheetInput", + "DataSetsMetadata", + "GetAllWorksheetsResponse", + "GetColumnsResponse", + "GetDrivesResponse", + "GetItemResponse", + "GetSingleScriptResponse", + "GetSourcesResponse", + "GetTablesResponse", + "Item", + "ItemsList", + "ObjectEntity", + "RawAndFormattedTableSchema", + "RunScriptProdInput", + "RunScriptProdResponse", + "ScriptParameters", + "ScriptReturnValues", + "SensitivityLabelMetadata", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TableToCreate", + "TablesList", + "TabularDataSetsMetadata", + "TabularItem", + "TabularItemsList", + "WorkbookRange", + "WorksheetMetadata", +] + # Type Definitions @@ -29,26 +71,30 @@ class TableMetadata: Response for Create table """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Table name""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Table title""" - x_ms_permission: Optional[str] = field( + x_ms_permission: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-permission"}, ) """Table permission""" - x_ms_capabilities: Optional[TableCapabilitiesMetadata] = field( + x_ms_capabilities: Optional[TableCapabilitiesMetadata | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-capabilities"}, ) - schema: Optional[ObjectEntity] = None - referenced_entities: Optional[ObjectEntity] = field( + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + referenced_entities: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "referencedEntities"}, ) - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webUrl"}, ) """Url link""" @@ -60,14 +106,23 @@ class ItemsList: Response for List rows present in a table """ - value: Optional[List[Item]] = None + value: Optional[ + List[Item | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Items""" - sensitivity_label_info: Optional[List[SensitivityLabelMetadata]] = field( + sensitivity_label_info: Optional[ + List[SensitivityLabelMetadata | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelInfo"}, ) - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -79,7 +134,12 @@ class CommentsList: Response for List all comments present in a workbook """ - value: Optional[List[Comment]] = None + value: Optional[ + List[Comment | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Comments""" @@ -89,12 +149,13 @@ class Comment: Response for Get a comment present in a workbook """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique identifier for the comment.""" - content: Optional[str] = None + content: Optional[str] = dataclass_field(default=None, kw_only=True) """The content of the comment.""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentType"}, ) """The content type of the comment.""" @@ -106,12 +167,16 @@ class GetItemResponse: Response for Get a row """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) - sensitivity_label_info: Optional[List[SensitivityLabelMetadata]] = field( + sensitivity_label_info: Optional[ + List[SensitivityLabelMetadata | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelInfo"}, ) @@ -122,8 +187,9 @@ class Item: Response for Update a row """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) @@ -134,9 +200,17 @@ class GetAllWorksheetsResponse: Response for Get worksheets """ - value: Optional[List[WorksheetMetadata]] = None - sensitivity_label_info: Optional[List[SensitivityLabelMetadata]] = field( + value: Optional[ + List[WorksheetMetadata | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, + ) + sensitivity_label_info: Optional[ + List[SensitivityLabelMetadata | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelInfo"}, ) @@ -147,7 +221,7 @@ class CreateWorksheetInput: Create worksheet """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Worksheet name.""" @@ -157,13 +231,13 @@ class WorksheetMetadata: Response for Create worksheet """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Worksheet Id.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Worksheet name.""" - position: Optional[int] = None + position: Optional[int] = dataclass_field(default=None, kw_only=True) """Worksheet position.""" - visibility: Optional[str] = None + visibility: Optional[str] = dataclass_field(default=None, kw_only=True) """Worksheet visibility.""" @@ -173,9 +247,12 @@ class GetTablesResponse: Response for Get tables """ - value: Optional[List[Dict[str, Any]]] = None - sensitivity_label_info: Optional[List[SensitivityLabelMetadata]] = field( + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + sensitivity_label_info: Optional[ + List[SensitivityLabelMetadata | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelInfo"}, ) @@ -186,7 +263,7 @@ class RunScriptProdInput: Run script from SharePoint library """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -199,7 +276,7 @@ class RunScriptProdResponse: Response for Run script from SharePoint library """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -212,7 +289,7 @@ class GetSourcesResponse: Response for Get sources """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -221,7 +298,7 @@ class GetDrivesResponse: Response for Get drives """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -230,7 +307,7 @@ class GetColumnsResponse: Response for Get table columns """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -239,8 +316,9 @@ class GetSingleScriptResponse: Response for Gets one script """ - parameter_info: Optional[Dict[str, Any]] = field( + parameter_info: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parameterInfo"}, ) @@ -251,13 +329,15 @@ class CreateFileMetadata: Definition: CreateFileMetadata """ - file_name: Optional[str] = field( + file_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileName"}, ) """Name of the newly created file""" - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebUrl"}, ) """URL to open the file in the browser on your OneDrive""" @@ -269,8 +349,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -279,25 +369,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -309,15 +403,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -329,7 +425,12 @@ class TablesList: Definition: TablesList """ - value: Optional[List[Table]] = None + value: Optional[ + List[Table | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Tables""" @@ -339,15 +440,21 @@ class Table: Definition: Table """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the table. The name is used at runtime.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the table.""" - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DynamicProperties"}, ) """Additional table properties provided by the connector to the clients.""" @@ -359,15 +466,17 @@ class TableToCreate: Definition: TableToCreate """ - table_name: Optional[str] = field( + table_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableName"}, ) """Enter the Excel table name.""" - range: Optional[str] = field(default=None, metadata={"wire_name": "Range"}) + range: str = dataclass_field(metadata={"wire_name": "Range"}) """Enter the table address using A1 notation.""" - columns_names: Optional[str] = field( + columns_names: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ColumnsNames"}, ) """Enter the columns names separated by ';' or ','.""" @@ -379,30 +488,42 @@ class TableCapabilitiesMetadata: Definition: TableCapabilitiesMetadata """ - sort_restrictions: Optional[TableSortRestrictionsMetadata] = field( + sort_restrictions: Optional[ + TableSortRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sortRestrictions"}, ) - filter_restrictions: Optional[TableFilterRestrictionsMetadata] = field( + filter_restrictions: Optional[ + TableFilterRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterRestrictions"}, ) - select_restrictions: Optional[TableSelectRestrictionsMetadata] = field( + select_restrictions: Optional[ + TableSelectRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selectRestrictions"}, ) - is_only_server_pagable: Optional[bool] = field( + is_only_server_pagable: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isOnlyServerPagable"}, ) """Server paging restrictions""" - filter_function_support: Optional[List[str]] = field( + filter_function_support: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterFunctionSupport"}, ) """List of supported filter capabilities""" - server_paging_options: Optional[List[str]] = field( + server_paging_options: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "serverPagingOptions"}, ) """List of supported server-driven paging capabilities""" @@ -414,7 +535,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -427,15 +548,17 @@ class TableSortRestrictionsMetadata: Definition: TableSortRestrictionsMetadata """ - sortable: Optional[bool] = None + sortable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has sortable columns""" - unsortable_properties: Optional[List[str]] = field( + unsortable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "unsortableProperties"}, ) """List of unsortable properties""" - ascending_only_properties: Optional[List[str]] = field( + ascending_only_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ascendingOnlyProperties"}, ) """List of properties which support ascending order only""" @@ -447,15 +570,17 @@ class TableFilterRestrictionsMetadata: Definition: TableFilterRestrictionsMetadata """ - filterable: Optional[bool] = None + filterable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has filterable columns""" - non_filterable_properties: Optional[List[str]] = field( + non_filterable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nonFilterableProperties"}, ) """List of non filterable properties""" - required_properties: Optional[List[str]] = field( + required_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredProperties"}, ) """List of required properties""" @@ -467,7 +592,7 @@ class TableSelectRestrictionsMetadata: Definition: TableSelectRestrictionsMetadata """ - selectable: Optional[bool] = None + selectable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has selectable columns""" @@ -477,10 +602,11 @@ class CommentDetails: Definition: CommentDetails """ - content: Optional[str] = None + content: Optional[str] = dataclass_field(default=None, kw_only=True) """The content of the comment.""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentType"}, ) """The content type of the comment.""" @@ -492,7 +618,12 @@ class TabularItemsList: Definition: TabularItemsList """ - value: Optional[List[TabularItem]] = None + value: Optional[ + List[TabularItem | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Items""" @@ -502,8 +633,9 @@ class TabularItem: Definition: TabularItem """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) @@ -514,7 +646,7 @@ class ScriptParameters: Definition: ScriptParameters """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -527,7 +659,7 @@ class ScriptReturnValues: Definition: ScriptReturnValues """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -540,8 +672,9 @@ class RawAndFormattedTableSchema: Definition: RawAndFormattedTableSchema """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) @@ -552,24 +685,39 @@ class BlobMetadata: Definition: BlobMetadata """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ @@ -584,41 +732,47 @@ class SensitivityLabelMetadata: Definition: SensitivityLabelMetadata """ - sensitivity_label_id: Optional[str] = field( + sensitivity_label_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelId"}, ) """SensitivityLabel Id.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel name.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """SensitivityLabel displayName info""" - tooltip: Optional[str] = None + tooltip: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel details on tooltip.""" - priority: Optional[int] = None + priority: Optional[int] = dataclass_field(default=None, kw_only=True) """SensitivityLabel priority.""" - color: Optional[str] = None + color: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel color.""" - is_encrypted: Optional[bool] = field( + is_encrypted: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEncrypted"}, ) """ is SensitivityLabel Encrypted.""" - is_enabled: Optional[bool] = field( + is_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEnabled"}, ) """Whether SensitivityLabel is Enabled.""" - is_parent: Optional[bool] = field( + is_parent: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isParent"}, ) """Whether SensitivityLabel is Parent.""" - parent_sensitivity_label_id: Optional[str] = field( + parent_sensitivity_label_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentSensitivityLabelId"}, ) """Parent SensitivityLabel Id.""" @@ -630,44 +784,52 @@ class WorkbookRange: Definition: WorkbookRange """ - address: Optional[str] = None + address: Optional[str] = dataclass_field(default=None, kw_only=True) """Range address including the sheet name, e.g. Sheet1!A1:D10.""" - address_local: Optional[str] = field( + address_local: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "addressLocal"}, ) - cell_count: Optional[int] = field( + cell_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "cellCount"}, ) - column_count: Optional[int] = field( + column_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "columnCount"}, ) - row_count: Optional[int] = field( + row_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "rowCount"}, ) - column_index: Optional[int] = field( + column_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "columnIndex"}, ) - row_index: Optional[int] = field( + row_index: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "rowIndex"}, ) - values: Optional[List[List[Any]]] = None + values: Optional[List[List[Any]]] = dataclass_field(default=None, kw_only=True) """2-D array of cell values.""" - text: Optional[List[List[str]]] = None + text: Optional[List[List[str]]] = dataclass_field(default=None, kw_only=True) """2-D array of display text.""" - formulas: Optional[List[List[str]]] = None + formulas: Optional[List[List[str]]] = dataclass_field(default=None, kw_only=True) """2-D array of formulas.""" - number_format: Optional[List[List[str]]] = field( + number_format: Optional[List[List[str]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "numberFormat"}, ) - value_types: Optional[List[List[str]]] = field( + value_types: Optional[List[List[str]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "valueTypes"}, ) """2-D array of value type names (e.g. String, Double, Empty).""" @@ -681,16 +843,16 @@ class ExcelonlinebusinessClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -701,8 +863,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -710,8 +872,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -723,7 +885,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -745,7 +907,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -777,9 +939,9 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def create_table_async( + def create_table( self, - input: TableToCreate, + input: TableToCreate | Mapping[str, Any], drive: str, file: str, source: str, @@ -793,6 +955,28 @@ async def create_table_async( Create table Create a new table in the Excel workbook. + + Swagger operation ID: `CreateTable`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -810,7 +994,7 @@ async def create_table_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -824,6 +1008,7 @@ async def create_table_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -831,14 +1016,14 @@ async def create_table_async( return json.loads(response.text) - async def create_id_column_async( + def create_id_column( self, drive: str, file: str, table: str, source: str, - id_column: Optional[str] = None, *, + id_column: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -849,6 +1034,28 @@ async def create_id_column_async( Add a key column to an Excel table. The new column will be appended to the right. + + Swagger operation ID: `CreateIdColumn`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + id_column: Provide the key column name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -874,7 +1081,7 @@ async def create_id_column_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -888,14 +1095,16 @@ async def create_id_column_async( request_url, response.status, response.text, + response=response, ) - async def get_items_async( + def list_items( self, drive: str, file: str, table: str, source: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, @@ -904,19 +1113,52 @@ async def get_items_async( date_time_format: Optional[str] = None, extract_sensitivity_label: Optional[bool] = None, fetch_sensitivity_label_metadata: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List rows present in a table List rows present in a table. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItems`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + filter: An ODATA filter query to restrict the entries returned. + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Comma-separated list of columns to retrieve (first 500 by + default). + date_time_format: DateTime Format. + extract_sensitivity_label: A boolean whether to extract sensitivity + label Id for associated artefact. + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -975,11 +1217,18 @@ async def get_items_async( query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -992,37 +1241,70 @@ async def get_items_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_comments_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def list_comments( self, drive: str, file: str, - source: Optional[str] = None, *, + source: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List all comments present in a workbook List all comments present in a workbook. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetComments`. + + Args: + drive: Ask user to select a document library from the drop-down. + file: Ask user to select an Excel file through File Browse. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1041,35 +1323,56 @@ async def get_comments_async( query_params.append(f"source={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_comment_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_comment( self, drive: str, file: str, commentid: str, - source: Optional[str] = None, *, + source: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1079,6 +1382,27 @@ async def get_comment_async( Get a comment present in a workbook Get a comment present in a workbook. + + Swagger operation ID: `GetComment`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + commentid: Provide a comment Id . + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1099,7 +1423,7 @@ async def get_comment_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1113,6 +1437,7 @@ async def get_comment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1120,14 +1445,14 @@ async def get_comment_async( return json.loads(response.text) - async def reply_comment_async( + def reply_comment( self, - input: CommentDetails, + input: CommentDetails | Mapping[str, Any], drive: str, file: str, commentid: str, - source: Optional[str] = None, *, + source: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1137,6 +1462,29 @@ async def reply_comment_async( Reply to a comment present in a workbook Reply to a comment present in a workbook. + + Swagger operation ID: `ReplyComment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Ask user to select a document library from the drop-down. + file: Ask user to select an Excel file through File Browse. + commentid: Provide a comment Id . + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1158,7 +1506,7 @@ async def reply_comment_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1172,6 +1520,7 @@ async def reply_comment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1179,7 +1528,7 @@ async def reply_comment_async( return json.loads(response.text) - async def get_item_async( + def get_item( self, drive: str, file: str, @@ -1187,10 +1536,10 @@ async def get_item_async( id: str, source: str, id_column: str, + *, date_time_format: Optional[str] = None, extract_sensitivity_label: Optional[bool] = None, fetch_sensitivity_label_metadata: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1200,6 +1549,34 @@ async def get_item_async( Get a row Get a row using a key column. + + Swagger operation ID: `GetItem`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + id: Enter the key value. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + id_column: Select a column from the drop-down. + date_time_format: DateTime Format. + extract_sensitivity_label: A boolean whether to extract sensitivity + label Id for associated artefact. + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1239,7 +1616,7 @@ async def get_item_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1253,6 +1630,7 @@ async def get_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1260,7 +1638,7 @@ async def get_item_async( return json.loads(response.text) - async def delete_item_async( + def delete_item( self, drive: str, file: str, @@ -1278,6 +1656,29 @@ async def delete_item_async( Delete a row Delete a row using a key column. + + Swagger operation ID: `DeleteItem`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + id: Enter the key value. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + id_column: Select a column from the drop-down. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1302,7 +1703,7 @@ async def delete_item_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1316,19 +1717,20 @@ async def delete_item_async( request_url, response.status, response.text, + response=response, ) - async def patch_item_async( + def patch_item( self, - input: Item, + input: Item | Mapping[str, Any], drive: str, file: str, table: str, id: str, source: str, id_column: str, - date_time_format: Optional[str] = None, *, + date_time_format: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1341,6 +1743,32 @@ async def patch_item_async( specified cells and columns left blank will not be updated. In order to append (instead of overwrite) a value, use the \"Get a row\" action to retrieve the content first. + + Swagger operation ID: `PatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + id: Enter the key value. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (the colons are required). + id_column: Select a column from the drop-down. + date_time_format: DateTime Format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1370,7 +1798,7 @@ async def patch_item_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -1384,6 +1812,7 @@ async def patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1391,23 +1820,51 @@ async def patch_item_async( return json.loads(response.text) - async def get_all_worksheets_async( + def list_all_worksheets( self, drive: str, file: str, source: str, + *, extract_sensitivity_label: Optional[bool] = None, fetch_sensitivity_label_metadata: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get worksheets Get a list of worksheets in the Excel workbook. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAllWorksheets`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + extract_sensitivity_label: A boolean whether to extract sensitivity + label Id for associated artefact. + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1437,31 +1894,52 @@ async def get_all_worksheets_async( query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def create_worksheet_async( + def create_worksheet( self, - input: CreateWorksheetInput, + input: CreateWorksheetInput | Mapping[str, Any], drive: str, file: str, source: str, @@ -1475,6 +1953,28 @@ async def create_worksheet_async( Create worksheet Create a new worksheet in the Excel workbook. + + Swagger operation ID: `CreateWorksheet`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1495,7 +1995,7 @@ async def create_worksheet_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1509,6 +2009,7 @@ async def create_worksheet_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1516,23 +2017,51 @@ async def create_worksheet_async( return json.loads(response.text) - async def get_tables_async( + def list_tables( self, drive: str, file: str, source: str, + *, extract_sensitivity_label: Optional[bool] = None, fetch_sensitivity_label_metadata: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get tables Get a list of tables in the Excel workbook. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTables`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + extract_sensitivity_label: A boolean whether to extract sensitivity + label Id for associated artefact. + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1562,37 +2091,58 @@ async def get_tables_async( query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - async def add_row_async( + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def add_row( self, - input: Item, + input: Item | Mapping[str, Any], drive: str, file: str, table: str, source: str, - date_time_format: Optional[str] = None, *, + date_time_format: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1602,6 +2152,30 @@ async def add_row_async( Add a row into a table Add a new row into the Excel table. + + Swagger operation ID: `AddRowV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + date_time_format: DateTime Format. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1629,7 +2203,7 @@ async def add_row_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1643,6 +2217,7 @@ async def add_row_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1650,9 +2225,9 @@ async def add_row_async( return json.loads(response.text) - async def run_script_prod_async( + def run_script_prod( self, - input: RunScriptProdInput, + input: RunScriptProdInput | Mapping[str, Any], drive: str, file: str, script_drive: str, @@ -1670,6 +2245,37 @@ async def run_script_prod_async( Runs an Office Script against an Excel workbook. Use this action when the script is saved outside of the default location. + + Swagger operation ID: `RunScriptProdV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + drive: Select a document library from the drop-down. + file: Select an Excel workbook through File Browse. + script_drive: Select the SharePoint library of your Office Script + file (.osts) from the drop-down. + script_id: Select an Office Script file (.osts) in a SharePoint + library from the drop-down. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + script_source: Select from the drop-down or specify one of the + following: - \"me\" - \"SharePoint Site URL\" - + \"users/someone's UPN\" - \"groups/group Id\" - + \"sites/SharePoint Site URL:/teams/team name:\" (the colons are + required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1695,7 +2301,7 @@ async def run_script_prod_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1709,6 +2315,7 @@ async def run_script_prod_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1716,19 +2323,38 @@ async def run_script_prod_async( return json.loads(response.text) - async def get_sources_async( + def list_sources( self, - top: Optional[str] = None, *, + top: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get sources Get a list of sources. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetSources`. + + Args: + top: Top. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/codeless/v1.0/sources" query_params = [] @@ -1739,29 +2365,50 @@ async def get_sources_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def get_drives_async( + return ItemPaged(get_next, extract_data) + + def list_drives( self, source: str, *, @@ -1769,11 +2416,33 @@ async def get_drives_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get drives Get a list of drives. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetDrives`. + + Args: + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/codeless/v1.0/drives" query_params = [] @@ -1783,29 +2452,50 @@ async def get_drives_async( query_params.append(f"source={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def get_columns_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_columns( self, drive: str, file: str, @@ -1816,11 +2506,36 @@ async def get_columns_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get table columns Get table columns. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetColumns`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1842,29 +2557,50 @@ async def get_columns_async( query_params.append(f"source={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - async def get_table_async( + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_table( self, drive: str, file: str, @@ -1880,6 +2616,27 @@ async def get_table_async( Get metadata of a table Get metadata of a table. + + Swagger operation ID: `GetTable`. + + Args: + drive: Select a document library from the drop-down. + file: Select an Excel file through File Browse. + table: Select a table from the drop-down. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1902,7 +2659,7 @@ async def get_table_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1916,6 +2673,7 @@ async def get_table_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1923,7 +2681,7 @@ async def get_table_async( return json.loads(response.text) - async def get_single_script_async( + def get_single_script( self, script_source: str, script_drive: str, @@ -1938,6 +2696,23 @@ async def get_single_script_async( Gets one script Gets one of the scripts. + + Swagger operation ID: `GetSingleScriptV2`. + + Args: + script_source: script source. + script_drive: script drive. + script_id: Script chosen to use. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1959,7 +2734,7 @@ async def get_single_script_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1973,6 +2748,7 @@ async def get_single_script_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/formstackforms.py b/src/azure/connectors/formstackforms.py index a421362..c7a351b 100644 --- a/src/azure/connectors/formstackforms.py +++ b/src/azure/connectors/formstackforms.py @@ -5,14 +5,13 @@ from __future__ import annotations -from dataclasses import dataclass +from dataclasses import dataclass, field as dataclass_field from typing import Optional, Dict, List, Any, Mapping from urllib.parse import quote import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, @@ -20,6 +19,14 @@ ConnectorResponseHook, ) +__all__ = [ + "FormstackformsClient", + "FormstackFormSubmittedInput", + "FormstackFormSubmittedResponse", + "GetAvailableFormsResponse", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,13 +36,13 @@ class FormstackFormSubmittedInput: Triggers when a form is submitted """ - url: Optional[str] = None + url: str """url""" - content_type: Optional[str] = None + content_type: str """content type""" - file_transfer_type: Optional[str] = None + file_transfer_type: str """file transfer type""" - standardize_field_values: Optional[bool] = None + standardize_field_values: bool """standardize field values""" @@ -45,7 +52,7 @@ class FormstackFormSubmittedResponse: Response for Triggers when a form is submitted """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -54,9 +61,9 @@ class GetAvailableFormsResponse: Response for Get Available Forms """ - forms: Optional[List[Dict[str, Any]]] = None + forms: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """forms""" - total: Optional[int] = None + total: Optional[int] = dataclass_field(default=None, kw_only=True) """total""" @@ -68,16 +75,16 @@ class FormstackformsClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -88,8 +95,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -97,8 +104,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -110,7 +117,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -125,7 +132,7 @@ def __init__( def connector_name(self) -> str: return "formstackforms" - async def get_available_forms_async( + def get_available_forms( self, *, timeout: Optional[float] = None, @@ -137,10 +144,24 @@ async def get_available_forms_async( Get Available Forms Returns all available forms + + Swagger operation ID: `GetAvailableForms`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/v2/form/" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -154,6 +175,7 @@ async def get_available_forms_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -161,7 +183,7 @@ async def get_available_forms_async( return json.loads(response.text) - async def get_form_schema_async( + def get_form_schema( self, form_id: int, *, @@ -174,6 +196,21 @@ async def get_form_schema_async( Returns Form Schema from Webhook API Used for the x-ms-dynamic-schema + + Swagger operation ID: `GetFormSchema`. + + Args: + form_id: form_id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -184,7 +221,7 @@ async def get_form_schema_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -198,6 +235,7 @@ async def get_form_schema_async( request_url, response.status, response.text, + response=response, ) diff --git a/src/azure/connectors/freshservice.py b/src/azure/connectors/freshservice.py index 709417d..450867f 100644 --- a/src/azure/connectors/freshservice.py +++ b/src/azure/connectors/freshservice.py @@ -5,14 +5,13 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, Dict, List, Any, Mapping from urllib.parse import quote import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, @@ -20,6 +19,20 @@ ConnectorResponseHook, ) +__all__ = [ + "FreshserviceClient", + "AddNoteRequest", + "AddNoteResponse", + "CreateTicketRequest", + "CreateUpdateTicketResponse", + "ListTicketResponse", + "ListUsersResponse", + "TicketResponse", + "UpdateTicketRequest", + "UpdateTicketResponse", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +42,7 @@ class AddNoteResponse: Response for Add a note to a ticket """ - conversation: Optional[Dict[str, Any]] = None + conversation: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -38,7 +51,7 @@ class CreateUpdateTicketResponse: Response for Create a ticket """ - ticket: Optional[Dict[str, Any]] = None + ticket: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -47,48 +60,52 @@ class ListTicketResponse: Response for When a ticket is created """ - created_at: Optional[str] = None + created_at: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - department_id: Optional[int] = None - due_by: Optional[str] = None + department_id: Optional[int] = dataclass_field(default=None, kw_only=True) + due_by: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - group_id: Optional[int] = None + group_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of Group to which the ticket is assigned.""" - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique Id of the ticket.""" - is_escalated: Optional[bool] = None + is_escalated: Optional[bool] = dataclass_field(default=None, kw_only=True) """Set to true if an escalation was sent.""" - priority: Optional[int] = None + priority: Optional[int] = dataclass_field(default=None, kw_only=True) """A number representing the priority of the ticket.""" - requester_id: Optional[int] = None + requester_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ User-id of the requester. For existing contacts, requester_id can be passed instead of email. """ - responder_id: Optional[int] = None + responder_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the agent to whom the ticket is assigned.""" - source: Optional[int] = None + source: Optional[int] = dataclass_field(default=None, kw_only=True) """ A number representing the channel through which the ticket was created. """ - spam: Optional[bool] = None + spam: Optional[bool] = dataclass_field(default=None, kw_only=True) """Set as true if the ticket is marked as spam.""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """A number representing the status of the ticket.""" - subject: Optional[str] = None + subject: Optional[str] = dataclass_field(default=None, kw_only=True) """Ticket subject.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type property field as defined in ticket fields.""" - updated_at: Optional[str] = None + updated_at: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - description_text: Optional[str] = None + description_text: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the problem.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """ HTML content of the ticket. Description and description_html should not be passed together. """ - to_emails: Optional[List[str]] = None + to_emails: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Email addresses to which the incoming ticket email was sent.""" @@ -98,39 +115,39 @@ class CreateTicketRequest: Definition: CreateTicket_Request """ - requester_id: Optional[int] = None + requester_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ User-id of the requester. One of the Requester ID, Requester Email and Requester Phone is required """ - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """ Email of the requester. One of the Requester ID, Requester Email and Requester Phone is required """ - phone: Optional[str] = None + phone: Optional[str] = dataclass_field(default=None, kw_only=True) """ Phone number of the requester. One of the Requester ID, Requester Email and Requester Phone is required """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the requester. This is a required field only if Requester Phone value is provided """ - subject: Optional[str] = None + subject: str """The subject of the ticket.""" - status: Optional[str] = None + status: str """Status of the ticket.""" - priority: Optional[str] = None + priority: str """The priority of the ticket (such as Low, Medium, or High).""" - description: Optional[str] = None + description: str """The description of the ticket.""" - urgency: Optional[str] = None + urgency: Optional[str] = dataclass_field(default=None, kw_only=True) """Urgency of the problem (such as Low, Medium or High).""" - impact: Optional[str] = None + impact: Optional[str] = dataclass_field(default=None, kw_only=True) """Impact of the problem (such as Low, Medium or High).""" - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """The channel through which the ticket was created.""" @@ -140,22 +157,22 @@ class UpdateTicketRequest: Definition: UpdateTicket_Request """ - requester_id: Optional[int] = None + requester_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ User-id of the requester. For existing contacts, requester_id can be passed instead of email. """ - subject: Optional[str] = None + subject: Optional[str] = dataclass_field(default=None, kw_only=True) """The subject of the ticket.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status of the ticket.""" - priority: Optional[str] = None + priority: Optional[str] = dataclass_field(default=None, kw_only=True) """The priority of the ticket (such as Low, Medium, or High).""" - urgency: Optional[str] = None + urgency: Optional[str] = dataclass_field(default=None, kw_only=True) """Urgency of the problem (such as Low, Medium or High).""" - impact: Optional[str] = None + impact: Optional[str] = dataclass_field(default=None, kw_only=True) """Impact of the problem (such as Low, Medium or High).""" - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """The channel through which the ticket was created.""" @@ -165,9 +182,9 @@ class AddNoteRequest: Definition: AddNote_Request """ - body: Optional[str] = None + body: str """The note to be added to the ticket.""" - private: Optional[bool] = None + private: Optional[bool] = dataclass_field(default=None, kw_only=True) """Set to true if message is private.""" @@ -177,85 +194,85 @@ class TicketResponse: Definition: Ticket_Response """ - created_at: Optional[str] = None + created_at: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - deleted: Optional[bool] = None + deleted: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Set as true if the ticket is deleted/trashed. Deleted tickets will not be considered in any views except 'deleted' filter. """ - department_id_value: Optional[int] = None - display_id: Optional[int] = None + department_id_value: Optional[int] = dataclass_field(default=None, kw_only=True) + display_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Ticket Id specific to your account.""" - due_by: Optional[str] = None + due_by: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - group_id: Optional[int] = None + group_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of Group to which the ticket is assigned.""" - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique Id of the ticket.""" - impact: Optional[int] = None + impact: Optional[int] = dataclass_field(default=None, kw_only=True) """A number representing the impact of the problem.""" - isescalated: Optional[bool] = None + isescalated: Optional[bool] = dataclass_field(default=None, kw_only=True) """Set to true if an escalation was sent.""" - owner_id: Optional[str] = None + owner_id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id of the agent to whom the problem is assigned.""" - priority: Optional[int] = None + priority: Optional[int] = dataclass_field(default=None, kw_only=True) """A number representing the priority of the ticket.""" - requester_id: Optional[int] = None + requester_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ User-id of the requester. For existing contacts, requester_id can be passed instead of email. """ - responder_id: Optional[int] = None + responder_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the agent to whom the ticket is assigned.""" - source: Optional[int] = None + source: Optional[int] = dataclass_field(default=None, kw_only=True) """ A number representing the channel through which the ticket was created. """ - spam: Optional[bool] = None + spam: Optional[bool] = dataclass_field(default=None, kw_only=True) """Set as true if the ticket is marked as spam.""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """A number representing the status of the ticket.""" - subject: Optional[str] = None + subject: Optional[str] = dataclass_field(default=None, kw_only=True) """Ticket subject.""" - ticket_type: Optional[str] = None + ticket_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Type property field as defined in ticket fields.""" - to_email: Optional[str] = None + to_email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address to which the incoming ticket email was sent.""" - updated_at: Optional[str] = None + updated_at: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - urgency: Optional[int] = None + urgency: Optional[int] = dataclass_field(default=None, kw_only=True) """A number representing the urgency of the problem.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the problem.""" - description_html: Optional[str] = None + description_html: Optional[str] = dataclass_field(default=None, kw_only=True) """ HTML content of the ticket. Description and description_html should not be passed together. """ - status_name: Optional[str] = None + status_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Status of the ticket.""" - priority_name: Optional[str] = None + priority_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Priority of the ticket.""" - source_name: Optional[str] = None + source_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The channel through which the ticket was created.""" - responder_name: Optional[str] = None + responder_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the agent to whom the ticket is assigned.""" - to_emails: Optional[List[str]] = None + to_emails: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Email addresses to which the incoming ticket email was sent.""" - department_name: Optional[str] = None + department_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the department.""" - assoc_problem_id: Optional[int] = None + assoc_problem_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the associated problem to the ticket.""" - assoc_change_id: Optional[int] = None + assoc_change_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the associated change to the problem.""" - assoc_change_cause_id: Optional[int] = None + assoc_change_cause_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the change causing the ticket.""" - assoc_asset_id: Optional[int] = None + assoc_asset_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the asset associated to the ticket.""" - urgency_name: Optional[str] = None + urgency_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Urgency of the problem.""" - impact_name: Optional[str] = None + impact_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Impact of the problem.""" @@ -265,7 +282,7 @@ class UpdateTicketResponse: Definition: UpdateTicket_Response """ - ticket: Optional[Dict[str, Any]] = None + ticket: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) ListUsersResponse = List[Dict[str, Any]] @@ -279,16 +296,16 @@ class FreshserviceClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -299,8 +316,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -308,8 +325,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -321,7 +338,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -336,9 +353,9 @@ def __init__( def connector_name(self) -> str: return "freshservice" - async def add_note_async( + def add_note( self, - input: AddNoteRequest, + input: AddNoteRequest | Mapping[str, Any], ticket_id: int, *, timeout: Optional[float] = None, @@ -350,13 +367,30 @@ async def add_note_async( Add a note to a ticket Add a private or public note to a ticket. + + Swagger operation ID: `AddNoteV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + ticket_id: The ticket id to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v2/tickets/{quote(str(ticket_id), safe='')}/notes" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -370,6 +404,7 @@ async def add_note_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -377,9 +412,9 @@ async def add_note_async( return json.loads(response.text) - async def create_ticket_async( + def create_ticket( self, - input: CreateTicketRequest, + input: CreateTicketRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -390,10 +425,26 @@ async def create_ticket_async( Create a ticket Create a ticket. + + Swagger operation ID: `CreateTicketV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/v2/tickets" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -407,6 +458,7 @@ async def create_ticket_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -414,9 +466,9 @@ async def create_ticket_async( return json.loads(response.text) - async def update_ticket_async( + def update_ticket( self, - input: UpdateTicketRequest, + input: UpdateTicketRequest | Mapping[str, Any], ticket_id: int, *, timeout: Optional[float] = None, @@ -428,13 +480,30 @@ async def update_ticket_async( Update a ticket Update a ticket (only specified values will be updated). + + Swagger operation ID: `UpdateTicketV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + ticket_id: The ticket id to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v2/tickets/{quote(str(ticket_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -448,6 +517,7 @@ async def update_ticket_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/ftp.py b/src/azure/connectors/ftp.py index 6347d2d..f054698 100644 --- a/src/azure/connectors/ftp.py +++ b/src/azure/connectors/ftp.py @@ -5,21 +5,34 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "FtpClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "BlobMetadataPage", + "BlobMetadataResponse", + "DataSetsMetadata", + "ObjectEntity", + "TabularDataSetsMetadata", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,41 +42,66 @@ class BlobMetadata: Response for Create file """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The filelocator of the file or folder.""" @@ -75,8 +113,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -85,25 +133,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -115,15 +167,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -135,41 +189,66 @@ class BlobMetadataResponse: Definition: BlobMetadataResponse """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The filelocator of the file or folder.""" @@ -181,7 +260,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -194,7 +273,12 @@ class BlobMetadataPage: Definition: BlobMetadataPage """ - value: Optional[List[BlobMetadata]] = None + value: Optional[ + List[BlobMetadata | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Blob metadata collection.""" @@ -206,16 +290,16 @@ class FtpClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -226,8 +310,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -235,8 +319,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -248,7 +332,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -263,7 +347,46 @@ def __init__( def connector_name(self) -> str: return "ftp" - async def create_file_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def create_file( self, input: bytes, folder_path: str, @@ -281,6 +404,23 @@ async def create_file_async( server right after it was created, connector may return HTTP 404 error by it's design. Please use a delay for 1 minute before deleting or renaming newly created file. + + Swagger operation ID: `CreateFile`. + + Args: + input: The binary request body. + folder_path: Select a folder. + name: Name of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/datasets/default/files" query_params = [] @@ -296,7 +436,7 @@ async def create_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -313,6 +453,7 @@ async def create_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -320,7 +461,7 @@ async def create_file_async( return json.loads(response.text) - async def get_file_metadata_async( + def get_file_metadata( self, id: str, *, @@ -333,6 +474,21 @@ async def get_file_metadata_async( Get file metadata This operation gets the metadata for a file. + + Swagger operation ID: `GetFileMetadata`. + + Args: + id: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -342,7 +498,7 @@ async def get_file_metadata_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -356,6 +512,7 @@ async def get_file_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -363,7 +520,7 @@ async def get_file_metadata_async( return json.loads(response.text) - async def update_file_async( + def update_file( self, input: bytes, id: str, @@ -380,6 +537,22 @@ async def update_file_async( server right after it was updated, connector may return HTTP 404 error by it's design. Please use a delay for 1 minute before deleting or renaming recently updated file. + + Swagger operation ID: `UpdateFile`. + + Args: + input: The binary request body. + id: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -389,7 +562,7 @@ async def update_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, @@ -406,6 +579,7 @@ async def update_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -413,7 +587,7 @@ async def update_file_async( return json.loads(response.text) - async def delete_file_async( + def delete_file( self, id: str, *, @@ -426,6 +600,21 @@ async def delete_file_async( Delete file This operation deletes a file. + + Swagger operation ID: `DeleteFile`. + + Args: + id: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -435,7 +624,7 @@ async def delete_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -449,14 +638,15 @@ async def delete_file_async( request_url, response.status, response.text, + response=response, ) - async def copy_file_async( + def copy_file( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -469,6 +659,23 @@ async def copy_file_async( deleted/renamed on server right after it was copied, connector may return HTTP 404 error by it's design. Please use a delay for 1 minute before deleting or renaming newly created file. + + Swagger operation ID: `CopyFile`. + + Args: + source: Url to source file. + destination: Destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/copyFile" @@ -491,7 +698,7 @@ async def copy_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -505,6 +712,7 @@ async def copy_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -512,7 +720,7 @@ async def copy_file_async( return json.loads(response.text) - async def get_file_metadata_by_path_async( + def get_file_metadata_by_path( self, path: str, *, @@ -525,6 +733,21 @@ async def get_file_metadata_by_path_async( Get file metadata using path This operation gets the metadata of a file using the file path. + + Swagger operation ID: `GetFileMetadataByPath`. + + Args: + path: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/GetFileByPath" @@ -538,7 +761,7 @@ async def get_file_metadata_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -552,6 +775,7 @@ async def get_file_metadata_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -559,11 +783,11 @@ async def get_file_metadata_by_path_async( return json.loads(response.text) - async def get_file_content_by_path_async( + def get_file_content_by_path( self, path: str, - infer_content_type: Optional[bool] = None, *, + infer_content_type: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -573,6 +797,22 @@ async def get_file_content_by_path_async( Get file content using path This operation gets the content of a file using the file path. + + Swagger operation ID: `GetFileContentByPath`. + + Args: + path: Select a file. + infer_content_type: Infer content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -592,7 +832,7 @@ async def get_file_content_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -606,15 +846,16 @@ async def get_file_content_by_path_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_file_content_async( + def get_file_content( self, id: str, - infer_content_type: Optional[bool] = None, *, + infer_content_type: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -624,6 +865,22 @@ async def get_file_content_async( Get file content This operation gets the content of a file. + + Swagger operation ID: `GetFileContent`. + + Args: + id: Select a file. + infer_content_type: Infer content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -642,7 +899,7 @@ async def get_file_content_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -656,11 +913,12 @@ async def get_file_content_async( request_url, response.status, response.text, + response=response, ) return response.content - async def list_folder_async( + def list_folder( self, id: str, *, @@ -668,11 +926,30 @@ async def list_folder_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List files in folder This operation gets the list of files and subfolders in a folder. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListFolder`. + + Args: + id: Select a folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -681,74 +958,134 @@ async def list_folder_async( f"/folders" f"/{quote(quote(str(id), safe=''), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def list_root_folder_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_root_folder( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List files in root folder This operation gets the list of files and subfolders in the root folder. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListRootFolder`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/folders" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def extract_folder_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def extract_folder( self, source: str, destination: str, + *, overwrite: Optional[bool] = None, create_folders: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -758,6 +1095,24 @@ async def extract_folder_async( Extract archive to folder This operation extracts an archive file into a folder (example: .zip). + + Swagger operation ID: `ExtractFolderV2`. + + Args: + source: Path to the archive file. + destination: Path to the destination folder. + overwrite: Overwrites the destination files if set to 'true'. + create_folders: Extracts folders from archive if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/extractFolderV2" @@ -785,7 +1140,7 @@ async def extract_folder_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -799,6 +1154,7 @@ async def extract_folder_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/github.py b/src/azure/connectors/github.py index 4d424cf..ec996f8 100644 --- a/src/azure/connectors/github.py +++ b/src/azure/connectors/github.py @@ -5,21 +5,66 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "GithubClient", + "ActionsPublicKey", + "Commit", + "CommitComparison", + "CreateReferenceRequest", + "CreateRepositorySecretRequest", + "CreateRepositoryUsingTemplateRequest", + "DiffEntry", + "GeneralAPIModel", + "GitReference", + "GitUser", + "GraphQlQuery", + "IssueBasicDetailsModel", + "IssueDetailsModel", + "IssueUpdateModel", + "Label", + "LicenseDetails", + "Link", + "Milestone", + "MilestoneUpdateModel", + "MultipleFetchModel", + "MultipleSearchFetchModel", + "PullRequest", + "PullRequestCreateRequest", + "PullRequestFile", + "PullRequestMergeRequest", + "PullRequestMergeResult", + "PullRequestUpdateRequest", + "QueryRequest", + "RepositoryDetails", + "RepositoryDispatchEvent", + "RepositoryMiniDetails", + "RequestReviewersBody", + "SingleSearchFetchModel", + "TeamDetails", + "UserDetailsModel", + "Verification", + "WebhookCreationResponse", + "WebhookPullRequestResponse", + "WebhookRequestBody", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,22 +74,27 @@ class IssueDetailsModel: Response for Create an issue """ - title: Optional[str] = None + title: str """Summary of the issue.""" - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the issue.""" - assignee: Optional[UserDetailsModel] = None - number: Optional[int] = None + assignee: Optional[ + UserDetailsModel | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + number: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique id of the issue.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """Status of the issue.""" - created_at: Optional[str] = None + created_at: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format).""" - repository_url: Optional[str] = None + repository_url: Optional[str] = dataclass_field(default=None, kw_only=True) """Web link to the repository.""" -MultipleFetchModel = List["GeneralAPIModel"] +MultipleFetchModel = List["GeneralAPIModel | Mapping[str, Any]"] @dataclass @@ -53,17 +103,17 @@ class ActionsPublicKey: Response for Get a repository public key """ - key_id: Optional[str] = None + key_id: str """The identifier for the key.""" - key: Optional[str] = None + key: str """The Base64 encoded public key.""" - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique identifier of the key.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Public key url.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Public key title.""" - created_at: Optional[str] = None + created_at: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time when the key was created.""" @@ -73,182 +123,192 @@ class RepositoryDetails: Response for Create a repository using a template """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique identifier of the repository.""" - node_id: Optional[str] = None + node_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The Node Id of the repository.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the repository.""" - full_name: Optional[str] = None + full_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The full name of the repository.""" - license: Optional[LicenseDetails] = None - forks: Optional[int] = None + license: Optional[ + LicenseDetails | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + forks: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of forks of the repository.""" - permissions: Optional[Dict[str, Any]] = None + permissions: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Permissions on the repository.""" - owner: Optional[UserDetailsModel] = None - private: Optional[bool] = None + owner: Optional[ + UserDetailsModel | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + private: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the repository is private or public.""" - html_url: Optional[str] = None + html_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Html Url of the repository""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the repository""" - fork: Optional[bool] = None + fork: Optional[bool] = dataclass_field(default=None, kw_only=True) """If the repository is a fork?""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The HTTP URL for this repository""" - archive_url: Optional[str] = None + archive_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Archive URL for this repository""" - assignees_url: Optional[str] = None + assignees_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Assignees URL for this repository""" - blobs_url: Optional[str] = None + blobs_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Blobs URL for this repository""" - branches_url: Optional[str] = None + branches_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Branches URL for this repository""" - collaborators_url: Optional[str] = None + collaborators_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Collaborators URL for this repository""" - comments_url: Optional[str] = None + comments_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Comments URL for this repository""" - commits_url: Optional[str] = None + commits_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Commits URL for this repository""" - compare_url: Optional[str] = None + compare_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Compare URL for this repository""" - contents_url: Optional[str] = None + contents_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Contents URL for this repository""" - contributors_url: Optional[str] = None + contributors_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Contributors URL for this repository""" - deployments_url: Optional[str] = None + deployments_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Deployments URL for this repository""" - downloads_url: Optional[str] = None + downloads_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Downloads URL for this repository""" - events_url: Optional[str] = None + events_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Events URL for this repository""" - forks_url: Optional[str] = None + forks_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Forks URL for this repository""" - git_commits_url: Optional[str] = None + git_commits_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Git Commits URL for this repository""" - git_refs_url: Optional[str] = None + git_refs_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Git References URL for this repository""" - git_tags_url: Optional[str] = None + git_tags_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Git Tags URL for this repository""" - git_url: Optional[str] = None + git_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Git URL for this repository""" - issue_comment_url: Optional[str] = None + issue_comment_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The issue comment URL for this repository""" - issue_events_url: Optional[str] = None + issue_events_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The issue events URL for this repository""" - issues_url: Optional[str] = None + issues_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The issues URL for this repository""" - keys_url: Optional[str] = None + keys_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The keys URL for this repository""" - labels_url: Optional[str] = None + labels_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The labels URL for this repository""" - languages_url: Optional[str] = None + languages_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The languages URL for this repository""" - merges_url: Optional[str] = None + merges_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The merges URL for this repository""" - milestones_url: Optional[str] = None + milestones_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The milestones URL for this repository""" - notifications_url: Optional[str] = None + notifications_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The notifications URL for this repository""" - pulls_url: Optional[str] = None + pulls_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The pulls URL for this repository""" - releases_url: Optional[str] = None + releases_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The releases URL for this repository""" - ssh_url: Optional[str] = None + ssh_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The SSH URL to clone this repository""" - stargazers_url: Optional[str] = None + stargazers_url: Optional[str] = dataclass_field(default=None, kw_only=True) """ The stargazers (Stargazers are the people that have bookmarked the GitHub repository) URL for this repository """ - statuses_url: Optional[str] = None + statuses_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The statuses URL for this repository""" - subscribers_url: Optional[str] = None + subscribers_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The subscribers URL for this repository""" - subscription_url: Optional[str] = None + subscription_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The subscription URL for this repository""" - tags_url: Optional[str] = None + tags_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The tags URL for this repository""" - teams_url: Optional[str] = None + teams_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The teams URL for this repository""" - trees_url: Optional[str] = None + trees_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The trees URL for this repository""" - clone_url: Optional[str] = None + clone_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The clone URL for this repository""" - mirror_url: Optional[str] = None + mirror_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The original mirror URL for this repository""" - hooks_url: Optional[str] = None + hooks_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The hooks URL for this repository""" - svn_url: Optional[str] = None + svn_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The SVN URL for this repository""" - homepage: Optional[str] = None + homepage: Optional[str] = dataclass_field(default=None, kw_only=True) """The homepage for this repository""" - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The language for this repository""" - forks_count: Optional[int] = None + forks_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of forks there are of this repository in the whole network.""" - stargazers_count: Optional[int] = None + stargazers_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of users who have starred the repository.""" - watchers_count: Optional[int] = None + watchers_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of users watching the repository.""" - size: Optional[int] = None + size: Optional[int] = dataclass_field(default=None, kw_only=True) """Size of the repository""" - default_branch: Optional[str] = None + default_branch: Optional[str] = dataclass_field(default=None, kw_only=True) """The default branch of the repository.""" - open_issues_count: Optional[int] = None + open_issues_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of open issues in the repository.""" - is_template: Optional[bool] = None + is_template: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether this repository acts as a template that can be used to generate new repositories. """ - topics: Optional[List[str]] = None + topics: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """List of topics in the repository""" - has_issues: Optional[bool] = None + has_issues: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether issues are enabled.""" - has_projects: Optional[bool] = None + has_projects: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether projects are enabled.""" - has_wiki: Optional[bool] = None + has_wiki: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the wiki is enabled.""" - has_pages: Optional[bool] = None + has_pages: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether pages are enabled.""" - has_downloads: Optional[bool] = None + has_downloads: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether downloads are enabled.""" - archived: Optional[bool] = None + archived: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the repository is archived.""" - disabled: Optional[bool] = None + disabled: Optional[bool] = dataclass_field(default=None, kw_only=True) """Returns whether or not this repository disabled.""" - visibility: Optional[str] = None + visibility: Optional[str] = dataclass_field(default=None, kw_only=True) """The repository visibility: public, private, or internal.""" - pushed_at: Optional[str] = None + pushed_at: Optional[str] = dataclass_field(default=None, kw_only=True) """When the repository was last pushed to.""" - created_at: Optional[str] = None + created_at: Optional[str] = dataclass_field(default=None, kw_only=True) """the date and time when the repository was created.""" - updated_at: Optional[str] = None + updated_at: Optional[str] = dataclass_field(default=None, kw_only=True) """the date and time when the repository was last updated.""" - allow_rebase_merge: Optional[bool] = None + allow_rebase_merge: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to allow rebase merges for pull requests.""" - template_repository: Optional[Dict[str, Any]] = None - temp_clone_token: Optional[str] = None + template_repository: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + temp_clone_token: Optional[str] = dataclass_field(default=None, kw_only=True) """Temporary authentication token for cloning this repository.""" - allow_squash_merge: Optional[bool] = None + allow_squash_merge: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to allow squash merges for pull requests.""" - delete_branch_on_merge: Optional[bool] = None + delete_branch_on_merge: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to delete head branches when pull requests are merged""" - allow_merge_commit: Optional[bool] = None + allow_merge_commit: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to allow merge commits for pull requests.""" - subscribers_count: Optional[int] = None + subscribers_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of subscribers for the repository.""" - network_count: Optional[int] = None + network_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Repository Network Count""" - open_issues: Optional[int] = None + open_issues: Optional[int] = dataclass_field(default=None, kw_only=True) """Repository open issues.""" - watchers: Optional[int] = None + watchers: Optional[int] = dataclass_field(default=None, kw_only=True) """Repository Watchers.""" - master_branch: Optional[str] = None + master_branch: Optional[str] = dataclass_field(default=None, kw_only=True) """Repository master branch.""" - starred_at: Optional[str] = None + starred_at: Optional[str] = dataclass_field(default=None, kw_only=True) """Repository Starred At""" @@ -258,13 +318,13 @@ class GitReference: Response for Create a reference """ - ref: Optional[str] = None + ref: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the fully qualified reference.""" - node_id: Optional[str] = None + node_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The Node Id of the reference.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The url of the reference.""" - object: Optional[Dict[str, Any]] = None + object: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -273,11 +333,11 @@ class PullRequestMergeResult: Response for Merge a pull request """ - sha: Optional[str] = None + sha: Optional[str] = dataclass_field(default=None, kw_only=True) """SHA for the merge commit.""" - merged: Optional[bool] = None + merged: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether or not the pull request was merged.""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """Merge response message.""" @@ -287,96 +347,131 @@ class PullRequest: Response for Get a pull request """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The HTTP URL for this pull request.""" - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The Unique Identifier for the pull request.""" - node_id: Optional[str] = None + node_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The Node ID for the pull request.""" - html_url: Optional[str] = None + html_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The HTML URL for the pull request.""" - diff_url: Optional[str] = None + diff_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Diff URL for the pull request.""" - patch_url: Optional[str] = None + patch_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The patch URL for the pull request.""" - issue_url: Optional[str] = None + issue_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The issue URL for the pull request.""" - commits_url: Optional[str] = None + commits_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The commit URL for the pull request.""" - review_comments_url: Optional[str] = None + review_comments_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The review comments URL for the pull request.""" - review_comment_url: Optional[str] = None + review_comment_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The review comment URL for the pull request.""" - comments_url: Optional[str] = None + comments_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Diff URL for the pull request.""" - statuses_url: Optional[str] = None + statuses_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The statuses URL for the pull request.""" - number: Optional[int] = None + number: Optional[int] = dataclass_field(default=None, kw_only=True) """Number uniquely identifying the pull request within its repository.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """State of this Pull Request. Either `open` or `closed`.""" - locked: Optional[bool] = None + locked: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the pull request is locked or not.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the pull request.""" - user: Optional[UserDetailsModel] = None - body: Optional[str] = None + user: Optional[ + UserDetailsModel | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + body: Optional[str] = dataclass_field(default=None, kw_only=True) """The body as Markdown.""" - labels: Optional[List[Label]] = None + labels: Optional[ + List[Label | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of labels associated with the pull request.""" - milestone: Optional[Milestone] = None - active_lock_reason: Optional[str] = None + milestone: Optional[Milestone | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + active_lock_reason: Optional[str] = dataclass_field(default=None, kw_only=True) """Reason that the conversation was locked.""" - created_at: Optional[str] = None + created_at: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time when the pull request was created.""" - updated_at: Optional[str] = None + updated_at: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time when the pull request was last updated.""" - closed_at: Optional[str] = None + closed_at: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time when the pull request was closed.""" - merged_at: Optional[str] = None + merged_at: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time that the pull request was merged.""" - merge_commit_sha: Optional[str] = None + merge_commit_sha: Optional[str] = dataclass_field(default=None, kw_only=True) """The merge commit Sha of the pull request.""" - assignee: Optional[UserDetailsModel] = None - assignees: Optional[List[UserDetailsModel]] = None + assignee: Optional[ + UserDetailsModel | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + assignees: Optional[ + List[UserDetailsModel | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of assignees for the pull request.""" - requested_reviewers: Optional[List[UserDetailsModel]] = None + requested_reviewers: Optional[ + List[UserDetailsModel | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of Users assigned to this pull request.""" - requested_teams: Optional[List[TeamDetails]] = None + requested_teams: Optional[ + List[TeamDetails | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of requested teams to this pull request.""" - head: Optional[Dict[str, Any]] = None + head: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Head""" - base: Optional[Dict[str, Any]] = None + base: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Base""" - author_association: Optional[str] = None + author_association: Optional[str] = dataclass_field(default=None, kw_only=True) """Author's association with the subject of the comment.""" - draft: Optional[bool] = None + draft: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether or not the pull request is a draft.""" - merged: Optional[bool] = None + merged: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether or not the pull request was merged.""" - mergeable: Optional[bool] = None + mergeable: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether or not the pull request can be merged based on the existence of merge conflicts. """ - rebaseable: Optional[bool] = None + rebaseable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether or not the pull request is rebaseable.""" - mergeable_state: Optional[str] = None + mergeable_state: Optional[str] = dataclass_field(default=None, kw_only=True) """The mergeable state of the pull request.""" - merged_by: Optional[UserDetailsModel] = None - comments: Optional[int] = None + merged_by: Optional[ + UserDetailsModel | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + comments: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of comments in this pull request.""" - review_comments: Optional[int] = None + review_comments: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of review comments in this pull request.""" - maintainer_can_modify: Optional[bool] = None + maintainer_can_modify: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether maintainers can modify the pull request.""" - commits: Optional[int] = None + commits: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of commits in this pull request.""" - additions: Optional[int] = None + additions: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of additions in this pull request.""" - deletions: Optional[int] = None + deletions: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of deletions in this pull request.""" - changed_files: Optional[int] = None + changed_files: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of changed files in this pull request.""" @@ -386,25 +481,25 @@ class PullRequestFile: Response for Get the list of files from a pull request """ - sha: Optional[str] = None + sha: Optional[str] = dataclass_field(default=None, kw_only=True) """The sha for the file.""" - filename: Optional[str] = None + filename: Optional[str] = dataclass_field(default=None, kw_only=True) """The file name.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The modification status for the file.""" - additions: Optional[int] = None + additions: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of additions made to the file.""" - deletions: Optional[int] = None + deletions: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of deletions made to the file.""" - changes: Optional[int] = None + changes: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of changes made to the file.""" - blob_url: Optional[str] = None + blob_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The blob Url for the file.""" - raw_url: Optional[str] = None + raw_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The Raw Url for the file.""" - contents_url: Optional[str] = None + contents_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The contents Url for the file.""" - patch: Optional[str] = None + patch: Optional[str] = dataclass_field(default=None, kw_only=True) """The patch content for the file.""" @@ -414,29 +509,44 @@ class CommitComparison: Response for Compare two commits """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Url for the comparison""" - html_url: Optional[str] = None + html_url: Optional[str] = dataclass_field(default=None, kw_only=True) """Html Url for the comparison""" - permalink_url: Optional[str] = None + permalink_url: Optional[str] = dataclass_field(default=None, kw_only=True) """Permanent Url for the comparison """ - diff_url: Optional[str] = None + diff_url: Optional[str] = dataclass_field(default=None, kw_only=True) """Diff Url""" - patch_url: Optional[str] = None + patch_url: Optional[str] = dataclass_field(default=None, kw_only=True) """Patch Url""" - base_commit: Optional[Commit] = None - merge_base_commit: Optional[Commit] = None - status: Optional[str] = None + base_commit: Optional[Commit | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + merge_base_commit: Optional[ + Commit | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status of the comparision eg. diverged etc.,""" - ahead_by: Optional[int] = None + ahead_by: Optional[int] = dataclass_field(default=None, kw_only=True) """ahead by base branch""" - behind_by: Optional[int] = None + behind_by: Optional[int] = dataclass_field(default=None, kw_only=True) """behind_by base branch""" - total_commits: Optional[int] = None + total_commits: Optional[int] = dataclass_field(default=None, kw_only=True) """total commits""" - commits: Optional[List[Commit]] = None + commits: Optional[ + List[Commit | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """commits""" - files: Optional[List[DiffEntry]] = None + files: Optional[ + List[DiffEntry | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """files""" @@ -446,18 +556,22 @@ class WebhookCreationResponse: Response for When a pull request is created or modified """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) - id: Optional[int] = None - name: Optional[str] = None - active: Optional[bool] = None - events: Optional[List[str]] = None - config: Optional[Dict[str, Any]] = None - updated_at: Optional[str] = None - created_at: Optional[str] = None - url: Optional[str] = None - test_url: Optional[str] = None - ping_url: Optional[str] = None - last_response: Optional[Dict[str, Any]] = None + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) + id: Optional[int] = dataclass_field(default=None, kw_only=True) + name: Optional[str] = dataclass_field(default=None, kw_only=True) + active: Optional[bool] = dataclass_field(default=None, kw_only=True) + events: Optional[List[str]] = dataclass_field(default=None, kw_only=True) + config: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + updated_at: Optional[str] = dataclass_field(default=None, kw_only=True) + created_at: Optional[str] = dataclass_field(default=None, kw_only=True) + url: Optional[str] = dataclass_field(default=None, kw_only=True) + test_url: Optional[str] = dataclass_field(default=None, kw_only=True) + ping_url: Optional[str] = dataclass_field(default=None, kw_only=True) + last_response: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -466,36 +580,41 @@ class Milestone: Response for Update a milestone """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The HTTP URL for the milestone.""" - html_url: Optional[str] = None + html_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The HTML URL for the milestone.""" - labels_url: Optional[str] = None + labels_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The labels URL for the milestone.""" - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The Unique Identifier for the milestone.""" - node_id: Optional[str] = None + node_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The Node ID for the milestone.""" - number: Optional[int] = None + number: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of the milestone.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """The state of the milestone.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the milestone.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the milestone.""" - creator: Optional[UserDetailsModel] = None - open_issues: Optional[int] = None + creator: Optional[ + UserDetailsModel | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + open_issues: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of open issues for the repository.""" - closed_issues: Optional[int] = None + closed_issues: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of closed issues for the repository.""" - created_at: Optional[str] = None + created_at: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time when the milestone was created.""" - updated_at: Optional[str] = None + updated_at: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time when the milestone was last updated.""" - closed_at: Optional[str] = None + closed_at: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time when the milestone was closed.""" - due_on: Optional[str] = None + due_on: Optional[str] = dataclass_field(default=None, kw_only=True) """The due date of the milestone.""" @@ -505,67 +624,71 @@ class UserDetailsModel: Response for Get the authenticated user """ - login: Optional[str] = None + login: Optional[str] = dataclass_field(default=None, kw_only=True) """User Login.""" - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """User Id.""" - node_id: Optional[str] = None + node_id: Optional[str] = dataclass_field(default=None, kw_only=True) """User Node Id.""" - avatar_url: Optional[str] = None + avatar_url: Optional[str] = dataclass_field(default=None, kw_only=True) """User Avatar Url.""" - gravatar_id: Optional[str] = None + gravatar_id: Optional[str] = dataclass_field(default=None, kw_only=True) """User Gravatar Id.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """User Url.""" - html_url: Optional[str] = None + html_url: Optional[str] = dataclass_field(default=None, kw_only=True) """User Html Url.""" - followers_url: Optional[str] = None + followers_url: Optional[str] = dataclass_field(default=None, kw_only=True) """User FollowersUrl""" - following_url: Optional[str] = None + following_url: Optional[str] = dataclass_field(default=None, kw_only=True) """User Following Url.""" - gists_url: Optional[str] = None + gists_url: Optional[str] = dataclass_field(default=None, kw_only=True) """User Gists Url.""" - starred_url: Optional[str] = None + starred_url: Optional[str] = dataclass_field(default=None, kw_only=True) """User Starred Url.""" - subscriptions_url: Optional[str] = None + subscriptions_url: Optional[str] = dataclass_field(default=None, kw_only=True) """User Subscriptions Url.""" - organizations_url: Optional[str] = None + organizations_url: Optional[str] = dataclass_field(default=None, kw_only=True) """User Organizations Url.""" - repos_url: Optional[str] = None + repos_url: Optional[str] = dataclass_field(default=None, kw_only=True) """User Repos Url.""" - events_url: Optional[str] = None + events_url: Optional[str] = dataclass_field(default=None, kw_only=True) """User Events Url.""" - received_events_url: Optional[str] = None + received_events_url: Optional[str] = dataclass_field(default=None, kw_only=True) """User Received Events Url.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """User Type.""" - site_admin: Optional[bool] = None + site_admin: Optional[bool] = dataclass_field(default=None, kw_only=True) """Is User Site Admin?""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """User Name.""" - company: Optional[str] = None + company: Optional[str] = dataclass_field(default=None, kw_only=True) """User Company.""" - blog: Optional[str] = None + blog: Optional[str] = dataclass_field(default=None, kw_only=True) """User Blog.""" - location: Optional[str] = None + location: Optional[str] = dataclass_field(default=None, kw_only=True) """User Location.""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """User Email.""" - hireable: Optional[bool] = None + hireable: Optional[bool] = dataclass_field(default=None, kw_only=True) """User Hireable?""" - bio: Optional[str] = None + bio: Optional[str] = dataclass_field(default=None, kw_only=True) """User Bio.""" - public_repos: Optional[int] = None + public_repos: Optional[int] = dataclass_field(default=None, kw_only=True) """User Public Repos.""" - public_gists: Optional[int] = None + public_gists: Optional[int] = dataclass_field(default=None, kw_only=True) """User Public Gists.""" - followers: Optional[int] = None + followers: Optional[int] = dataclass_field(default=None, kw_only=True) """User Followers.""" - following: Optional[int] = None + following: Optional[int] = dataclass_field(default=None, kw_only=True) """User Following.""" - created_at: Optional[str] = None + created_at: Optional[str] = dataclass_field(default=None, kw_only=True) """User Created At.""" - updated_at: Optional[str] = None + updated_at: Optional[str] = dataclass_field(default=None, kw_only=True) """User Updated At.""" @@ -575,7 +698,7 @@ class GeneralAPIModel: Response for Check if a user is a repository collaborator """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -588,7 +711,12 @@ class MultipleSearchFetchModel: Response for Find issues by state and keyword """ - body: Optional[List[GeneralAPIModel]] = None + body: Optional[ + List[GeneralAPIModel | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """body of result""" @@ -598,9 +726,9 @@ class IssueBasicDetailsModel: Definition: IssueBasicDetailsModel """ - title: Optional[str] = None + title: str """Summary of the issue.""" - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the issue.""" @@ -610,7 +738,12 @@ class SingleSearchFetchModel: Definition: SingleSearchFetchModel """ - body: Optional[List[GeneralAPIModel]] = None + body: Optional[ + List[GeneralAPIModel | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """body of result""" @@ -620,21 +753,21 @@ class IssueUpdateModel: Definition: IssueUpdateModel """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Summary of the issue.""" - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the issue.""" - assignee: Optional[str] = None + assignee: Optional[str] = dataclass_field(default=None, kw_only=True) """Assignee of the issue.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """The open or close state of an issue. Can be one of open or closed.""" - state_reason: Optional[str] = None + state_reason: Optional[str] = dataclass_field(default=None, kw_only=True) """The reason for change of state.""" - milestone: Optional[str] = None + milestone: Optional[str] = dataclass_field(default=None, kw_only=True) """Number of milestones to associate with issue.""" - labels: Optional[List[str]] = None + labels: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """labels associated with the issue.""" - assignees: Optional[List[str]] = None + assignees: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """UserSnames to assign to the issue.""" @@ -644,13 +777,13 @@ class MilestoneUpdateModel: Definition: MilestoneUpdateModel """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Summary of the milestone.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """The open or close state of the milestone.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """A description of the milestone.""" - due_on: Optional[str] = None + due_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Due date of the milestone.""" @@ -660,16 +793,16 @@ class Verification: Definition: Verification """ - verified: Optional[bool] = None + verified: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Indicates whether GitHub considers the signature in this commit to be verified. """ - reason: Optional[str] = None + reason: Optional[str] = dataclass_field(default=None, kw_only=True) """The reason for verified value.""" - payload: Optional[str] = None + payload: Optional[str] = dataclass_field(default=None, kw_only=True) """The value that was signed.""" - signature: Optional[str] = None + signature: Optional[str] = dataclass_field(default=None, kw_only=True) """The signature that was extracted from the commit.""" @@ -679,11 +812,11 @@ class GitUser: Definition: GitUser """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """User Name""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email""" - date: Optional[str] = None + date: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of Commit.""" @@ -693,7 +826,7 @@ class GraphQlQuery: Definition: GraphQlQuery """ - query: Optional[str] = None + query: Optional[str] = dataclass_field(default=None, kw_only=True) """query""" @@ -703,27 +836,27 @@ class DiffEntry: Definition: DiffEntry """ - filename: Optional[str] = None + filename: Optional[str] = dataclass_field(default=None, kw_only=True) """Changed File Name.""" - additions: Optional[int] = None + additions: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of additions in the file""" - deletions: Optional[int] = None + deletions: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of Deletions in the file""" - changes: Optional[int] = None + changes: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of Changes in the file""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status of the change modified, renamed etc.,""" - raw_url: Optional[str] = None + raw_url: Optional[str] = dataclass_field(default=None, kw_only=True) """Raw Url link to the file""" - blob_url: Optional[str] = None + blob_url: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob Url link to the file""" - patch: Optional[str] = None + patch: Optional[str] = dataclass_field(default=None, kw_only=True) """Actual changes made to the file.""" - sha: Optional[str] = None + sha: Optional[str] = dataclass_field(default=None, kw_only=True) """SHA of the change.""" - contents_url: Optional[str] = None + contents_url: Optional[str] = dataclass_field(default=None, kw_only=True) """File Contents Url.""" - previous_filename: Optional[str] = None + previous_filename: Optional[str] = dataclass_field(default=None, kw_only=True) """Previous FileName if the FileName is changed""" @@ -733,22 +866,37 @@ class Commit: Definition: Commit """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The HTTP URL for the commit.""" - sha: Optional[str] = None + sha: Optional[str] = dataclass_field(default=None, kw_only=True) """SHA of the commit""" - node_id: Optional[str] = None + node_id: Optional[str] = dataclass_field(default=None, kw_only=True) """Node Id of the commit.""" - html_url: Optional[str] = None + html_url: Optional[str] = dataclass_field(default=None, kw_only=True) """HTML Url of the commit""" - comments_url: Optional[str] = None + comments_url: Optional[str] = dataclass_field(default=None, kw_only=True) """Comments Url of the commit""" - commit: Optional[Dict[str, Any]] = None - author: Optional[UserDetailsModel] = None - committer: Optional[UserDetailsModel] = None - parents: Optional[List[Dict[str, Any]]] = None - stats: Optional[Dict[str, Any]] = None - files: Optional[List[DiffEntry]] = None + commit: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + author: Optional[ + UserDetailsModel | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + committer: Optional[ + UserDetailsModel | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + parents: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + stats: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + files: Optional[ + List[DiffEntry | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -757,9 +905,9 @@ class RepositoryDispatchEvent: Definition: RepositoryDispatchEvent """ - event_type: Optional[str] = None + event_type: Optional[str] = dataclass_field(default=None, kw_only=True) """A custom webhook event name.""" - client_payload: Optional[Dict[str, Any]] = None + client_payload: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """ JSON payload with extra information about the webhook event that your action or worklow may use. @@ -772,12 +920,12 @@ class CreateRepositorySecretRequest: Definition: CreateRepositorySecretRequest """ - encrypted_value: Optional[str] = None + encrypted_value: Optional[str] = dataclass_field(default=None, kw_only=True) """ Value for your secret, encrypted with LibSodium using the public key retrieved from the Get an Repository public key action. """ - key_id: Optional[str] = None + key_id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID of the key you used to encrypt the secret.""" @@ -787,16 +935,16 @@ class CreateRepositoryUsingTemplateRequest: Definition: CreateRepositoryUsingTemplateRequest """ - owner: Optional[str] = None + owner: Optional[str] = dataclass_field(default=None, kw_only=True) """ The organization or person who will own the new repository. If left blank, the authenticated user will be the owner. """ - name: Optional[str] = None + name: str """The name of the new repository.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """A short description of the new repository.""" - private: Optional[bool] = None + private: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Either `true` to create a new private repository or `false` to create a new public one. @@ -809,17 +957,17 @@ class LicenseDetails: Definition: LicenseDetails """ - key: Optional[str] = None + key: Optional[str] = dataclass_field(default=None, kw_only=True) """The lowercased SPDX Id of the license.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The license full name specified by https://spdx.org/licenses.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """URL to the license on https://choosealicense.com.""" - spdx_id: Optional[str] = None + spdx_id: Optional[str] = dataclass_field(default=None, kw_only=True) """Short identifier specified by https://spdx.org/licenses.""" - node_id: Optional[str] = None + node_id: Optional[str] = dataclass_field(default=None, kw_only=True) """License Node Id.""" - html_url: Optional[str] = None + html_url: Optional[str] = dataclass_field(default=None, kw_only=True) """License HTML URL.""" @@ -829,44 +977,49 @@ class RepositoryMiniDetails: Definition: RepositoryMiniDetails """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique identifier of the repository.""" - node_id: Optional[str] = None + node_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The Node Id of the repository.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the repository.""" - full_name: Optional[str] = None + full_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The full name of the repository.""" - permissions: Optional[Dict[str, Any]] = None + permissions: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Permissions on the repository.""" - owner: Optional[UserDetailsModel] = None - private: Optional[bool] = None + owner: Optional[ + UserDetailsModel | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + private: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the repository is private or public.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the repository""" - homepage: Optional[str] = None + homepage: Optional[str] = dataclass_field(default=None, kw_only=True) """The homepage for this repository""" - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The language for this repository""" - archived: Optional[bool] = None + archived: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the repository is archived.""" - disabled: Optional[bool] = None + disabled: Optional[bool] = dataclass_field(default=None, kw_only=True) """Returns whether or not this repository disabled.""" - visibility: Optional[str] = None + visibility: Optional[str] = dataclass_field(default=None, kw_only=True) """The repository visibility: public, private, or internal.""" - created_at: Optional[str] = None + created_at: Optional[str] = dataclass_field(default=None, kw_only=True) """the date and time when the repository was created.""" - updated_at: Optional[str] = None + updated_at: Optional[str] = dataclass_field(default=None, kw_only=True) """the date and time when the repository was last updated.""" - allow_rebase_merge: Optional[bool] = None + allow_rebase_merge: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to allow rebase merges for pull requests.""" - allow_squash_merge: Optional[bool] = None + allow_squash_merge: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to allow squash merges for pull requests.""" - delete_branch_on_merge: Optional[bool] = None + delete_branch_on_merge: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to delete head branches when pull requests are merged""" - allow_merge_commit: Optional[bool] = None + allow_merge_commit: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to allow merge commits for pull requests.""" - master_branch: Optional[str] = None + master_branch: Optional[str] = dataclass_field(default=None, kw_only=True) """Repository master branch.""" @@ -876,13 +1029,13 @@ class CreateReferenceRequest: Definition: CreateReferenceRequest """ - ref: Optional[str] = None + ref: str """ The name of the fully qualified reference (ie: `refs/heads/master`). If it doesn't start with 'refs' and have at least two slashes, it will be rejected. """ - sha: Optional[str] = None + sha: str """The SHA1 value for this reference.""" @@ -892,25 +1045,25 @@ class PullRequestCreateRequest: Definition: PullRequestCreateRequest """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the new pull request.""" - head: Optional[str] = None + head: str """ The name of the branch where your changes are implemented. For cross-repository pull requests in the same network, namespace `head` with a user like this: `username:branch`. """ - base: Optional[str] = None + base: str """ The name of the branch you want the changes pulled into. This should be an existing branch on the current repository. You cannot submit a pull request to one repository that requests a merge to a base of another repository. """ - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """The contents of the pull request.""" - maintainer_can_modify: Optional[bool] = None + maintainer_can_modify: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether maintainers can modify the pull request.""" - draft: Optional[bool] = None + draft: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether the pull request is a draft.""" @@ -920,20 +1073,23 @@ class PullRequestMergeRequest: Definition: PullRequestMergeRequest """ - commit_title: Optional[str] = field( + commit_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "commitTitle"}, ) """Title for the automatic commit message.""" - commit_message: Optional[str] = field( + commit_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "commitMessage"}, ) """Extra detail to append to automatic commit message.""" - sha: Optional[str] = None + sha: Optional[str] = dataclass_field(default=None, kw_only=True) """SHA that pull request head must match to allow merge.""" - merge_method: Optional[str] = field( + merge_method: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mergeMethod"}, ) """ @@ -948,19 +1104,19 @@ class PullRequestUpdateRequest: Definition: PullRequestUpdateRequest """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the pull request.""" - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """The contents of the pull request.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """State of this Pull Request. Either `open` or `closed`.""" - base: Optional[str] = None + base: Optional[str] = dataclass_field(default=None, kw_only=True) """ The name of the branch you want your changes pulled into. This should be an existing branch on the current repository. You cannot update the base branch on a pull request to point to another repository. """ - maintainer_can_modify: Optional[bool] = None + maintainer_can_modify: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether maintainers can modify the pull request.""" @@ -970,19 +1126,19 @@ class Label: Definition: Label """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The Unique Identifier for the label.""" - node_id: Optional[str] = None + node_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The Node ID for the label.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """URL for the label""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the label.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """A brief description of this label.""" - color: Optional[str] = None + color: Optional[str] = dataclass_field(default=None, kw_only=True) """6-character hex code, without the leading #, identifying the color""" - default: Optional[bool] = None + default: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether or not this is a default label.""" @@ -992,29 +1148,29 @@ class TeamDetails: Definition: TeamDetails """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique identifier of the team.""" - node_id: Optional[str] = None + node_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The Node ID for the team.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """URL for the team.""" - members_url: Optional[str] = None + members_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The HTTP URL for the team members.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the team""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the team""" - permission: Optional[str] = None + permission: Optional[str] = dataclass_field(default=None, kw_only=True) """Permission that the team will have for its repositories""" - privacy: Optional[str] = None + privacy: Optional[str] = dataclass_field(default=None, kw_only=True) """The level of privacy this team should have""" - html_url: Optional[str] = None + html_url: Optional[str] = dataclass_field(default=None, kw_only=True) """HTML Url of the team.""" - repositories_url: Optional[str] = None + repositories_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The HTTP URL for this team's repositories.""" - slug: Optional[str] = None + slug: Optional[str] = dataclass_field(default=None, kw_only=True) """The slug corresponding to the team.""" - ldap_dn: Optional[str] = None + ldap_dn: Optional[str] = dataclass_field(default=None, kw_only=True) """Distinguished Name (DN) that team maps to within LDAP environment""" @@ -1024,7 +1180,7 @@ class Link: Definition: Link """ - href: Optional[str] = None + href: str @dataclass @@ -1033,11 +1189,16 @@ class WebhookPullRequestResponse: Definition: WebhookPullRequestResponse """ - action: Optional[str] = None + action: Optional[str] = dataclass_field(default=None, kw_only=True) """The action that was performed.""" - number: Optional[int] = None + number: Optional[int] = dataclass_field(default=None, kw_only=True) """The pull request number.""" - pull_request: Optional[PullRequest] = None + pull_request: Optional[ + PullRequest | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1046,13 +1207,13 @@ class WebhookRequestBody: Definition: WebhookRequestBody """ - active: Optional[bool] = None + active: bool """State of the Trigger, always set to true""" - name: Optional[str] = None + name: str """Name of the trigger""" - config: Optional[Dict[str, Any]] = None + config: Dict[str, Any] """Configuration of the Trigger""" - events: Optional[List[str]] = None + events: List[str] """Webhook events to listen on""" @@ -1062,8 +1223,8 @@ class RequestReviewersBody: Definition: RequestReviewersBody """ - reviewers: Optional[List[str]] = None - team_reviewers: Optional[List[str]] = None + reviewers: Optional[List[str]] = dataclass_field(default=None, kw_only=True) + team_reviewers: Optional[List[str]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1072,12 +1233,12 @@ class QueryRequest: Definition: QueryRequest """ - jsonrpc: Optional[str] = None - id: Optional[str] = None - method: Optional[str] = None - params: Optional[Dict[str, Any]] = None - result: Optional[Dict[str, Any]] = None - error: Optional[Dict[str, Any]] = None + jsonrpc: Optional[str] = dataclass_field(default=None, kw_only=True) + id: Optional[str] = dataclass_field(default=None, kw_only=True) + method: Optional[str] = dataclass_field(default=None, kw_only=True) + params: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + result: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + error: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) # Client Class @@ -1088,16 +1249,16 @@ class GithubClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -1108,8 +1269,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -1117,8 +1278,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -1130,7 +1291,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -1145,9 +1306,48 @@ def __init__( def connector_name(self) -> str: return "github" - async def create_issue_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def create_issue( self, - input: IssueBasicDetailsModel, + input: IssueBasicDetailsModel | Mapping[str, Any], repository_owner: str, repository_name: str, *, @@ -1160,6 +1360,24 @@ async def create_issue_async( Create an issue This operation is used to create a new issue for a specific repository. + + Swagger operation ID: `CreateIssue`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1169,7 +1387,7 @@ async def create_issue_async( f"/issues" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1183,6 +1401,7 @@ async def create_issue_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1190,10 +1409,11 @@ async def create_issue_async( return json.loads(response.text) - async def get_issues_async( + def list_issues( self, repository_owner: str, repository_name: str, + *, milestone: Optional[str] = None, state: Optional[str] = None, assignee: Optional[str] = None, @@ -1205,16 +1425,46 @@ async def get_issues_async( since: Optional[str] = None, per_page: Optional[int] = None, page: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get all issues of a repository Get all issues of a repository. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetIssues`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + milestone: Filter by milestone. + state: Filter by state. + assignee: Filter by assignee. + creator: Filter by creator. + mentioned: Filter by mentions. + labels: Filter by label names. + sort: Field to sort results by. + direction: Direction of sort. + since: Filter by issues after given date. + per_page: Number of results per page. + page: Page number to display. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1281,29 +1531,50 @@ async def get_issues_async( query_params.append(f"page={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_repository_public_key_async( + def get_repository_public_key( self, repository_owner: str, repository_name: str, @@ -1318,6 +1589,22 @@ async def get_repository_public_key_async( Gets your public key, which you need to encrypt secrets. You need to encrypt a secret before you can create or update secrets. + + Swagger operation ID: `GetRepositoryPublicKey`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1329,7 +1616,7 @@ async def get_repository_public_key_async( f"/public-key" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1343,6 +1630,7 @@ async def get_repository_public_key_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1350,9 +1638,9 @@ async def get_repository_public_key_async( return json.loads(response.text) - async def create_update_repository_secret_async( + def create_update_repository_secret( self, - input: CreateRepositorySecretRequest, + input: CreateRepositorySecretRequest | Mapping[str, Any], repository_owner: str, repository_name: str, secret_name: str, @@ -1367,6 +1655,25 @@ async def create_update_repository_secret_async( Creates or updates a repository secret with an encrypted value. Encrypt your secret using LibSodium. + + Swagger operation ID: `CreateUpdateRepositorySecret`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + secret_name: Name of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1378,7 +1685,7 @@ async def create_update_repository_secret_async( f"/{quote(str(secret_name), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1392,11 +1699,12 @@ async def create_update_repository_secret_async( request_url, response.status, response.text, + response=response, ) - async def create_repository_using_template_async( + def create_repository_using_template( self, - input: CreateRepositoryUsingTemplateRequest, + input: CreateRepositoryUsingTemplateRequest | Mapping[str, Any], template_owner: str, template_repository: str, *, @@ -1411,6 +1719,24 @@ async def create_repository_using_template_async( Creates a new repository using a repository template. The authenticated user must own or be a member of an organization that owns the repository. + + Swagger operation ID: `CreateRepositoryUsingTemplate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + template_owner: Name of the template repository owner. + template_repository: Name of the template repository. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1420,7 +1746,7 @@ async def create_repository_using_template_async( f"/generate" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1434,6 +1760,7 @@ async def create_repository_using_template_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1441,7 +1768,7 @@ async def create_repository_using_template_async( return json.loads(response.text) - async def get_repository_by_id_async( + def get_repository_by_id( self, repository_id: int, *, @@ -1454,13 +1781,28 @@ async def get_repository_by_id_async( Get a repository by Id Gets a repository by Id. + + Swagger operation ID: `GetRepositoryById`. + + Args: + repository_id: Unique Identifier of the repository. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/repositories/{quote(str(repository_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1474,6 +1816,7 @@ async def get_repository_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1481,9 +1824,9 @@ async def get_repository_by_id_async( return json.loads(response.text) - async def create_reference_async( + def create_reference( self, - input: CreateReferenceRequest, + input: CreateReferenceRequest | Mapping[str, Any], repository_owner: str, repository_name: str, *, @@ -1498,6 +1841,24 @@ async def create_reference_async( Creates a reference for your repository. You are unable to create new references for empty repositories, even if the commit SHA-1 hash used exists. Empty repositories are repositories without branches. + + Swagger operation ID: `CreateReference`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1508,7 +1869,7 @@ async def create_reference_async( f"/refs" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1522,6 +1883,7 @@ async def create_reference_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1529,7 +1891,7 @@ async def create_reference_async( return json.loads(response.text) - async def get_reference_async( + def get_reference( self, repository_owner: str, repository_name: str, @@ -1547,6 +1909,24 @@ async def get_reference_async( parameter must be formatted as `heads/` for branches and `tags/` for tags. If the `reference` doesn't match an existing ref, a `404` is returned. + + Swagger operation ID: `GetReference`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + reference: The ref in the URL must be formatted as heads/ for branches and tags/ for tags. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1558,7 +1938,7 @@ async def get_reference_async( f"/{quote(str(reference), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1572,6 +1952,7 @@ async def get_reference_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1579,9 +1960,9 @@ async def get_reference_async( return json.loads(response.text) - async def merge_pull_request_async( + def merge_pull_request( self, - input: PullRequestMergeRequest, + input: PullRequestMergeRequest | Mapping[str, Any], repository_owner: str, repository_name: str, pull_number: int, @@ -1595,6 +1976,25 @@ async def merge_pull_request_async( Merge a pull request This operation is used to merge a pull request for the repository. + + Swagger operation ID: `MergePullRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + pull_number: Pull Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1606,7 +2006,7 @@ async def merge_pull_request_async( f"/merge" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1620,6 +2020,7 @@ async def merge_pull_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1627,7 +2028,7 @@ async def merge_pull_request_async( return json.loads(response.text) - async def get_pull_request_async( + def get_pull_request( self, repository_owner: str, repository_name: str, @@ -1642,6 +2043,23 @@ async def get_pull_request_async( Get a pull request This operation is used to get a pull request for the repository. + + Swagger operation ID: `GetPullRequest`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + pull_number: Pull Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1652,7 +2070,7 @@ async def get_pull_request_async( f"/{quote(str(pull_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1666,6 +2084,7 @@ async def get_pull_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1673,9 +2092,9 @@ async def get_pull_request_async( return json.loads(response.text) - async def update_pull_request_async( + def update_pull_request( self, - input: PullRequestUpdateRequest, + input: PullRequestUpdateRequest | Mapping[str, Any], repository_owner: str, repository_name: str, pull_number: int, @@ -1693,6 +2112,25 @@ async def update_pull_request_async( access to the head or the source branch. For organization-owned repositories, you must be a member of the organization that owns the repository to open or update a pull request. + + Swagger operation ID: `UpdatePullRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + pull_number: Pull Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1703,7 +2141,7 @@ async def update_pull_request_async( f"/{quote(str(pull_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -1717,6 +2155,7 @@ async def update_pull_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1724,7 +2163,7 @@ async def update_pull_request_async( return json.loads(response.text) - async def get_pull_request_files_async( + def list_pull_request_files( self, repository_owner: str, repository_name: str, @@ -1734,12 +2173,33 @@ async def get_pull_request_files_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get the list of files from a pull request This operation is used to get the list of files from a pull request for the repository. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetPullRequestFiles`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + pull_number: Pull Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1750,31 +2210,52 @@ async def get_pull_request_files_async( f"/{quote(str(pull_number), safe='')}" f"/files" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def request_reviewers_pull_request_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def request_reviewers_pull_request( self, - input: RequestReviewersBody, + input: RequestReviewersBody | Mapping[str, Any], repository_owner: str, repository_name: str, pull_number: int, @@ -1789,6 +2270,25 @@ async def request_reviewers_pull_request_async( Requests reviews for a pull request from a given set of users and/or teams. + + Swagger operation ID: `RequestReviewersPullRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + pull_number: Pull Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1800,7 +2300,7 @@ async def request_reviewers_pull_request_async( f"/requested_reviewers" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1814,11 +2314,12 @@ async def request_reviewers_pull_request_async( request_url, response.status, response.text, + response=response, ) - async def remove_reviewers_pull_request_async( + def remove_reviewers_pull_request( self, - input: RequestReviewersBody, + input: RequestReviewersBody | Mapping[str, Any], repository_owner: str, repository_name: str, pull_number: int, @@ -1833,6 +2334,25 @@ async def remove_reviewers_pull_request_async( Remove requested reviewers from a pull request from a given set of users and/or teams. + + Swagger operation ID: `RemoveReviewersPullRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + pull_number: Pull Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1844,7 +2364,7 @@ async def remove_reviewers_pull_request_async( f"/requested_reviewers" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=input, timeout=timeout, headers=headers, @@ -1858,11 +2378,12 @@ async def remove_reviewers_pull_request_async( request_url, response.status, response.text, + response=response, ) - async def create_pull_request_async( + def create_pull_request( self, - input: PullRequestCreateRequest, + input: PullRequestCreateRequest | Mapping[str, Any], repository_owner: str, repository_name: str, *, @@ -1879,6 +2400,24 @@ async def create_pull_request_async( access to the head or the source branch. For organization-owned repositories, you must be a member of the organization that owns the repository to create a pull request. + + Swagger operation ID: `CreatePullRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1888,7 +2427,7 @@ async def create_pull_request_async( f"/pulls" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1902,6 +2441,7 @@ async def create_pull_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1909,10 +2449,11 @@ async def create_pull_request_async( return json.loads(response.text) - async def get_pull_requests_async( + def list_pull_requests( self, repository_owner: str, repository_name: str, + *, state: Optional[str] = None, head: Optional[str] = None, base: Optional[str] = None, @@ -1920,16 +2461,42 @@ async def get_pull_requests_async( direction: Optional[str] = None, per_page: Optional[int] = None, page: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get all Pull Requests of A Repository Get all Pull Requests of A Repository. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetPullRequests`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + state: Filter by state. + head: Filter by head user or organization. + base: Filter by base branch name. + sort: What to sort the results by. + direction: Direction of sort. + per_page: Number of results per page. + page: Page number to display. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1976,31 +2543,52 @@ async def get_pull_requests_async( query_params.append(f"page={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def create_repository_dispatch_event_async( + return ItemPaged(get_next, extract_data) + + def create_repository_dispatch_event( self, - input: RepositoryDispatchEvent, + input: RepositoryDispatchEvent | Mapping[str, Any], repository_owner: str, repository_name: str, *, @@ -2017,6 +2605,24 @@ async def create_repository_dispatch_event_async( GitHub to trigger a GitHub Actions workflow or GitHub App webhook. You must configure your GitHub Actions workflow or GitHub App to run when the `repository_dispatch` event occurs. + + Swagger operation ID: `CreateRepositoryDispatchEvent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2026,7 +2632,7 @@ async def create_repository_dispatch_event_async( f"/dispatches" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2040,9 +2646,10 @@ async def create_repository_dispatch_event_async( request_url, response.status, response.text, + response=response, ) - async def compare_repository_commits_async( + def compare_repository_commits( self, repository_owner: str, repository_name: str, @@ -2062,6 +2669,24 @@ async def compare_repository_commits_async( `repositoryName`, use the format `:branch`. The response is equivalent to running the `git log base..head` command; however, commits are returned in chronological order. + + Swagger operation ID: `CompareRepositoryCommits`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + base: base parameter. + head: head parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2072,7 +2697,7 @@ async def compare_repository_commits_async( f"/{quote(str(base), safe='')}...{quote(str(head), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2086,6 +2711,7 @@ async def compare_repository_commits_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2093,7 +2719,7 @@ async def compare_repository_commits_async( return json.loads(response.text) - async def add_selected_repo_to_org_secret_async( + def add_selected_repo_to_org_secret( self, repository_owner: str, repository_id: int, @@ -2114,6 +2740,23 @@ async def add_selected_repo_to_org_secret_async( You must authenticate using an access token with the `admin:org` scope to use this endpoint. GitHub Apps must have the `secrets` organization permission to use this endpoint. + + Swagger operation ID: `AddSelectedRepoToOrgSecret`. + + Args: + repository_owner: Name of the repository owner. + repository_id: Unique Identifier of the repository. + secret_name: Name of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2126,7 +2769,7 @@ async def add_selected_repo_to_org_secret_async( f"/{quote(str(repository_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -2140,9 +2783,10 @@ async def add_selected_repo_to_org_secret_async( request_url, response.status, response.text, + response=response, ) - async def remove_selected_repo_from_org_secret_async( + def remove_selected_repo_from_org_secret( self, repository_owner: str, repository_id: int, @@ -2163,6 +2807,23 @@ async def remove_selected_repo_from_org_secret_async( You must authenticate using an access token with the `admin:org` scope to use this endpoint. GitHub Apps must have the `secrets` organization permission to use this endpoint. + + Swagger operation ID: `RemoveSelectedRepoFromOrgSecret`. + + Args: + repository_owner: Name of the repository owner. + repository_id: Unique Identifier of the repository. + secret_name: Name of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2175,7 +2836,7 @@ async def remove_selected_repo_from_org_secret_async( f"/{quote(str(repository_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2189,9 +2850,10 @@ async def remove_selected_repo_from_org_secret_async( request_url, response.status, response.text, + response=response, ) - async def delete_webhook_trigger_async( + def delete_webhook_trigger( self, repository_owner: str, repository_name: str, @@ -2206,6 +2868,23 @@ async def delete_webhook_trigger_async( Deletes a GitHub Webhook Deletes a GitHub Webhook + + Swagger operation ID: `DeleteWebhookTrigger`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + webhook_id: ID of the GitHub Webhook. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2216,7 +2895,7 @@ async def delete_webhook_trigger_async( f"/{quote(str(webhook_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2230,9 +2909,10 @@ async def delete_webhook_trigger_async( request_url, response.status, response.text, + response=response, ) - async def get_issue_num_async( + def get_issue_num( self, repository_owner: str, repository_name: str, @@ -2247,6 +2927,23 @@ async def get_issue_num_async( Get a particular issue of a repository Get a particular issue of a repository. + + Swagger operation ID: `GetIssueNum`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + issue_number: Issue Number for a given issue. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2257,7 +2954,7 @@ async def get_issue_num_async( f"/{quote(str(issue_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2271,6 +2968,7 @@ async def get_issue_num_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2278,9 +2976,9 @@ async def get_issue_num_async( return json.loads(response.text) - async def update_issue_num_async( + def update_issue_num( self, - input: IssueUpdateModel, + input: IssueUpdateModel | Mapping[str, Any], repository_owner: str, repository_name: str, issue_number: int, @@ -2294,6 +2992,25 @@ async def update_issue_num_async( Update an Issue Update an existing issue given the issue number. + + Swagger operation ID: `UpdateIssueNum`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + issue_number: Issue Number for a given issue. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2304,7 +3021,7 @@ async def update_issue_num_async( f"/{quote(str(issue_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -2318,6 +3035,7 @@ async def update_issue_num_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2325,9 +3043,9 @@ async def update_issue_num_async( return json.loads(response.text) - async def update_milestone_async( + def update_milestone( self, - input: MilestoneUpdateModel, + input: MilestoneUpdateModel | Mapping[str, Any], repository_owner: str, repository_name: str, milestone_number: int, @@ -2341,6 +3059,25 @@ async def update_milestone_async( Update a milestone Update an existing milestone. + + Swagger operation ID: `UpdateMilestone`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + milestone_number: Milestone number for a given milestone. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2351,7 +3088,7 @@ async def update_milestone_async( f"/{quote(str(milestone_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -2365,6 +3102,7 @@ async def update_milestone_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2372,7 +3110,7 @@ async def update_milestone_async( return json.loads(response.text) - async def get_user_async( + def get_user( self, *, timeout: Optional[float] = None, @@ -2384,10 +3122,24 @@ async def get_user_async( Get the authenticated user Get the authenticated user. + + Swagger operation ID: `GetUser`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/user" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2401,6 +3153,7 @@ async def get_user_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2408,9 +3161,9 @@ async def get_user_async( return json.loads(response.text) - async def search_github_with_query_async( + def search_github_with_query( self, - input: GraphQlQuery, + input: GraphQlQuery | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -2421,10 +3174,26 @@ async def search_github_with_query_async( Search Github using Query Search Github using Query + + Swagger operation ID: `SearchGithubWithQuery`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/graphql" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2438,24 +3207,47 @@ async def search_github_with_query_async( request_url, response.status, response.text, + response=response, ) - async def get_assignees_async( + def list_assignees( self, repository_owner: str, repository_name: str, + *, per_page: Optional[int] = None, page: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Lists the available assignees for issues in a repository Lists the available assignees for issues in a repository. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAssignees`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + per_page: Number of results per page. + page: Page number to display. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2477,44 +3269,87 @@ async def get_assignees_async( query_params.append(f"page={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def list_collaborators_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_collaborators( self, repository_owner: str, repository_name: str, + *, per_page: Optional[int] = None, page: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List repository collaborators List repository collaborators. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListCollaborators`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + per_page: Number of results per page. + page: Page number to display. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2536,29 +3371,50 @@ async def list_collaborators_async( query_params.append(f"page={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def check_collaborator_async( + def check_collaborator( self, repository_owner: str, repository_name: str, @@ -2573,6 +3429,23 @@ async def check_collaborator_async( Check if a user is a repository collaborator Check if a user is a repository collaborator. + + Swagger operation ID: `checkCollaborator`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + user_name: The handle for the GitHub user account. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2583,7 +3456,7 @@ async def check_collaborator_async( f"/{quote(str(user_name), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2597,6 +3470,7 @@ async def check_collaborator_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2604,25 +3478,50 @@ async def check_collaborator_async( return json.loads(response.text) - async def get_milestones_async( + def list_milestones( self, repository_owner: str, repository_name: str, + *, state: Optional[str] = None, sort: Optional[str] = None, direction: Optional[str] = None, per_page: Optional[int] = None, page: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Lists all milestones of a repository Lists all milestones of a repository. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMilestones`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + state: State of the milestone. + sort: What to sort the results by. + direction: Direction of sort. + per_page: Number of results per page. + page: Page number to display. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2659,44 +3558,87 @@ async def get_milestones_async( query_params.append(f"page={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def get_labels_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_labels( self, repository_owner: str, repository_name: str, + *, per_page: Optional[int] = None, page: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Lists all labels for a repository Lists all labels for a repository. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetLabels`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + per_page: Number of results per page. + page: Page number to display. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2718,45 +3660,89 @@ async def get_labels_async( query_params.append(f"page={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_issue_labels_async( + def list_issue_labels( self, repository_owner: str, repository_name: str, issue_number: int, + *, per_page: Optional[int] = None, page: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Lists all labels for an issue Lists all labels for an issue. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetIssueLabels`. + + Args: + repository_owner: Name of the repository owner. + repository_name: Name of the repository. + issue_number: Issue Number for a given issue. + per_page: Number of results per page. + page: Page number to display. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2780,46 +3766,91 @@ async def get_issue_labels_async( query_params.append(f"page={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def get_repos_async( + return ItemPaged(get_next, extract_data) + + def list_repos( self, repository_owner: str, + *, type_: Optional[str] = None, sort: Optional[str] = None, direction: Optional[str] = None, per_page: Optional[int] = None, page: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Lists all public repositories for a user Lists all public repositories for a user. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetRepos`. + + Args: + repository_owner: Name of the repository owner. + type_: Limit results to repositories of the specified type. + sort: The property to sort the results by. + direction: Direction of sort. + per_page: Number of results per page. + page: Page number to fetch. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2853,46 +3884,91 @@ async def get_repos_async( query_params.append(f"page={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def get_org_repos_async( + return ItemPaged(get_next, extract_data) + + def list_org_repos( self, repository_owner: str, + *, type_: Optional[str] = None, sort: Optional[str] = None, direction: Optional[str] = None, per_page: Optional[int] = None, page: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Lists all public repositories for an organization Lists all public repositories for an organization. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetOrgRepos`. + + Args: + repository_owner: Name of the repository owner. + type_: Limit results to repositories of the specified type. + sort: The property to sort the results by. + direction: Direction of sort. + per_page: Number of results per page. + page: Page number to fetch. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2926,30 +4002,52 @@ async def get_org_repos_async( query_params.append(f"page={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_user_repos_async( + def list_user_repos( self, + *, visibility: Optional[str] = None, affiliation: Optional[str] = None, since: Optional[str] = None, @@ -2959,17 +4057,44 @@ async def get_user_repos_async( direction: Optional[str] = None, per_page: Optional[int] = None, page: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Lists all repositories for the authenticated user Lists all repositories (both public and private) for the authenticated user. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetUserRepos`. + + Args: + visibility: Limit results to repositories of the specified + visibility(public/private/all). + affiliation: Limit results based on affiliation. + since: Limit results to repositories updated after a given time. + before: Limit results to repositories updated before a given time. + type_: Limit results to repositories of the specified type. + sort: The property to sort the results by. + direction: Direction of sort. + per_page: Number of results per page. + page: Page number to fetch. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/user/repos" query_params = [] @@ -3020,45 +4145,89 @@ async def get_user_repos_async( query_params.append(f"page={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def search_issues_async( + return ItemPaged(get_next, extract_data) + + def list_search_issues( self, q: str, + *, sort: Optional[str] = None, order: Optional[str] = None, per_page: Optional[int] = None, page: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Find issues by state and keyword Find issues by state and keyword. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SearchIssues`. + + Args: + q: Search keywords and qualifiers. + sort: The property to sort the results by. + order: Direction of sort. + per_page: Number of results per page. + page: Page number to fetch. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/search/issues" query_params = [] @@ -3088,31 +4257,52 @@ async def search_issues_async( query_params.append(f"page={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("body", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def invoke_mcp_server_async( + def invoke_mcp_server( self, - input: QueryRequest, + input: QueryRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -3123,10 +4313,26 @@ async def invoke_mcp_server_async( Github MCP Server Github MCP Server + + Swagger operation ID: `InvokeMCPServer`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/mcp" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3140,6 +4346,7 @@ async def invoke_mcp_server_async( request_url, response.status, response.text, + response=response, ) diff --git a/src/azure/connectors/googlecalendar.py b/src/azure/connectors/googlecalendar.py index 424473d..c68b32d 100644 --- a/src/azure/connectors/googlecalendar.py +++ b/src/azure/connectors/googlecalendar.py @@ -5,21 +5,36 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "GooglecalendarClient", + "CalendarEventChangedList", + "CalendarEventList", + "CalendarList", + "CalendarListEntry", + "ObjectEntity", + "PatchEvent", + "RequestEvent", + "ResponseEvent", + "ResponseEventWithActionType", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +44,12 @@ class CalendarList: Response for List calendars """ - items: Optional[List[CalendarListEntry]] = None + items: Optional[ + List[CalendarListEntry | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Calendars in the list.""" @@ -39,7 +59,12 @@ class CalendarEventList: Response for List the events on a calendar """ - items: Optional[List[ResponseEvent]] = None + items: Optional[ + List[ResponseEvent | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Events in the calendar.""" @@ -49,40 +74,42 @@ class ResponseEvent: Response for Create an event """ - summary: Optional[str] = None + summary: Optional[str] = dataclass_field(default=None, kw_only=True) """A summary of the event.""" - start: Optional[str] = None + start: Optional[str] = dataclass_field(default=None, kw_only=True) """The (inclusive) start time of the event.""" - end: Optional[str] = None + end: Optional[str] = dataclass_field(default=None, kw_only=True) """The (exclusive) end time of the event.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the event.""" - location: Optional[str] = None + location: Optional[str] = dataclass_field(default=None, kw_only=True) """Geographic location of the event as free-form text.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Status of the event. Possible values are \"confirmed\", \"tentative\", or \"cancelled\". """ - html_link: Optional[str] = field( + html_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "htmlLink"}, ) """Unique ID of the list.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Opaque identifier of the event.""" - attendees: Optional[str] = None + attendees: Optional[str] = dataclass_field(default=None, kw_only=True) """The event's attendees.""" - creator: Optional[str] = None + creator: Optional[str] = dataclass_field(default=None, kw_only=True) """The creator of the event.""" - organizer: Optional[str] = None + organizer: Optional[str] = dataclass_field(default=None, kw_only=True) """The organizer of the event.""" - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """Creation time of the event.""" - updated: Optional[str] = None + updated: Optional[str] = dataclass_field(default=None, kw_only=True) """Last modification time of the event.""" - end_time_unspecified: Optional[bool] = field( + end_time_unspecified: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endTimeUnspecified"}, ) """ @@ -97,7 +124,7 @@ class ObjectEntity: Response for Delete an event """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -110,7 +137,12 @@ class CalendarEventChangedList: Response for When an event is added, updated or deleted from a calendar """ - items: Optional[List[ResponseEventWithActionType]] = None + items: Optional[ + List[ResponseEventWithActionType | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Changed events in the calendar.""" @@ -120,16 +152,17 @@ class CalendarListEntry: Definition: CalendarListEntry """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Identifier of the calendar.""" - summary: Optional[str] = None + summary: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of the calendar.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the calendar.""" - location: Optional[str] = None + location: Optional[str] = dataclass_field(default=None, kw_only=True) """Geographic location of the calendar as free-form text.""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "timeZone"}, ) """The time zone of the calendar.""" @@ -141,25 +174,26 @@ class RequestEvent: Definition: RequestEvent """ - summary: Optional[str] = None + summary: Optional[str] = dataclass_field(default=None, kw_only=True) """A summary of the event.""" - start: Optional[str] = None + start: str """The (inclusive) start time of the event.""" - end: Optional[str] = None + end: str """The (exclusive) end time of the event.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the event.""" - location: Optional[str] = None + location: Optional[str] = dataclass_field(default=None, kw_only=True) """Geographic location of the event as free-form text.""" - attendees: Optional[str] = None + attendees: Optional[str] = dataclass_field(default=None, kw_only=True) """Enter a comma-separated list of attendee emails.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Status of the event. Possible values are \"confirmed\", \"tentative\", or \"cancelled\". """ - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAllDay"}, ) """Is all-day event?""" @@ -171,25 +205,26 @@ class PatchEvent: Definition: PatchEvent """ - summary: Optional[str] = None + summary: Optional[str] = dataclass_field(default=None, kw_only=True) """A summary of the event.""" - start: Optional[str] = None + start: Optional[str] = dataclass_field(default=None, kw_only=True) """The (inclusive) start time of the event.""" - end: Optional[str] = None + end: Optional[str] = dataclass_field(default=None, kw_only=True) """The (exclusive) end time of the event.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the event.""" - location: Optional[str] = None + location: Optional[str] = dataclass_field(default=None, kw_only=True) """Geographic location of the event as free-form text.""" - attendees: Optional[str] = None + attendees: Optional[str] = dataclass_field(default=None, kw_only=True) """Enter a comma-separated list of attendee emails.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Status of the event. Possible values are \"confirmed\", \"tentative\", or \"cancelled. """ - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAllDay"}, ) """Is all-day event?""" @@ -201,45 +236,48 @@ class ResponseEventWithActionType: Definition: ResponseEventWithActionType """ - action_type: Optional[str] = field( + action_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "actionType"}, ) """Type of action which changed the event in change trigger.""" - summary: Optional[str] = None + summary: Optional[str] = dataclass_field(default=None, kw_only=True) """A summary of the event.""" - start: Optional[str] = None + start: Optional[str] = dataclass_field(default=None, kw_only=True) """The (inclusive) start time of the event.""" - end: Optional[str] = None + end: Optional[str] = dataclass_field(default=None, kw_only=True) """The (exclusive) end time of the event.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the event.""" - location: Optional[str] = None + location: Optional[str] = dataclass_field(default=None, kw_only=True) """Geographic location of the event as free-form text.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Status of the event. Possible values are \"confirmed\", \"tentative\", or \"cancelled\". """ - html_link: Optional[str] = field( + html_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "htmlLink"}, ) """Unique ID of the list.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Opaque identifier of the event.""" - attendees: Optional[str] = None + attendees: Optional[str] = dataclass_field(default=None, kw_only=True) """The event's attendees.""" - creator: Optional[str] = None + creator: Optional[str] = dataclass_field(default=None, kw_only=True) """The creator of the event.""" - organizer: Optional[str] = None + organizer: Optional[str] = dataclass_field(default=None, kw_only=True) """The organizer of the event.""" - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """Creation time of the event.""" - updated: Optional[str] = None + updated: Optional[str] = dataclass_field(default=None, kw_only=True) """Last modification time of the event.""" - end_time_unspecified: Optional[bool] = field( + end_time_unspecified: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endTimeUnspecified"}, ) """ @@ -256,16 +294,16 @@ class GooglecalendarClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -276,8 +314,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -285,8 +323,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -298,7 +336,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -313,19 +351,78 @@ def __init__( def connector_name(self) -> str: return "googlecalendar" - async def list_calendars_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_calendars( self, - min_access_role: Optional[str] = None, *, + min_access_role: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List calendars This operation is used to list all calendars in your Google account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListCalendars`. + + Args: + min_access_role: The minimum access role users must have to view + calendars. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/users/me/calendarList" query_params = [] @@ -336,45 +433,91 @@ async def list_calendars_async( query_params.append(f"minAccessRole={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() - async def list_events_async( + return ItemPaged(get_next, extract_data) + + def list_events( self, calendar_id: str, + *, time_min: Optional[str] = None, time_max: Optional[str] = None, q: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List the events on a calendar This operation is used to return the first page of arbitrarily ordered events on the selected calendar. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListEvents`. + + Args: + calendar_id: Unique ID of the calendar to fetch events from. + time_min: Time format: yyyy-MM-ddTHH:mm:ss.fffZ + (2016-07-20T08:00:00.000Z). + time_max: Time format: yyyy-MM-ddTHH:mm:ss.fffZ + (2016-07-20T09:00:59.000Z). + q: Text search terms to find events that match these terms in any + fields. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -398,31 +541,52 @@ async def list_events_async( query_params.append(f"q={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item - async def create_event_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def create_event( self, - input: RequestEvent, + input: RequestEvent | Mapping[str, Any], calendar_id: str, *, timeout: Optional[float] = None, @@ -434,13 +598,30 @@ async def create_event_async( Create an event This operation is used to create an event on a specific calendar. + + Swagger operation ID: `CreateEvent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + calendar_id: Unique ID of the calendar to fetch events from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/calendars/{quote(str(calendar_id), safe='')}/events" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -454,6 +635,7 @@ async def create_event_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -461,7 +643,7 @@ async def create_event_async( return json.loads(response.text) - async def get_event_async( + def get_event( self, calendar_id: str, event_id: str, @@ -476,6 +658,22 @@ async def get_event_async( This operation is used to get the details of a specific event from a calendar. + + Swagger operation ID: `GetEvent`. + + Args: + calendar_id: Unique ID of the calendar to fetch events from. + event_id: Unique ID of the event to get. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -485,7 +683,7 @@ async def get_event_async( f"/{quote(str(event_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -499,6 +697,7 @@ async def get_event_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -506,7 +705,7 @@ async def get_event_async( return json.loads(response.text) - async def delete_event_async( + def delete_event( self, calendar_id: str, event_id: str, @@ -520,6 +719,22 @@ async def delete_event_async( Delete an event This operation is used to delete an event from a calendar. + + Swagger operation ID: `DeleteEvent`. + + Args: + calendar_id: Unique ID of the calendar to fetch events from. + event_id: Unique ID of the event to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -529,7 +744,7 @@ async def delete_event_async( f"/{quote(str(event_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -543,6 +758,7 @@ async def delete_event_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -550,9 +766,9 @@ async def delete_event_async( return json.loads(response.text) - async def update_event_async( + def update_event( self, - input: PatchEvent, + input: PatchEvent | Mapping[str, Any], calendar_id: str, event_id: str, *, @@ -565,6 +781,24 @@ async def update_event_async( Update an event This operation is used to update an existing event on a calendar. + + Swagger operation ID: `UpdateEvent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + calendar_id: Unique ID of the calendar to fetch events from. + event_id: Unique ID of the event to get. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -574,7 +808,7 @@ async def update_event_async( f"/{quote(str(event_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -588,6 +822,7 @@ async def update_event_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -595,46 +830,85 @@ async def update_event_async( return json.loads(response.text) - async def list_writable_calendars_async( + def list_writable_calendars( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List writable calendars This operation is used to list all calendars in your Google account that you can write to. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListWritableCalendars`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/users/me/calendarList/1" query_params = [] query_params.append("minAccessRole=" + quote("writer", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/googledrive.py b/src/azure/connectors/googledrive.py index 37a99df..794386c 100644 --- a/src/azure/connectors/googledrive.py +++ b/src/azure/connectors/googledrive.py @@ -5,21 +5,44 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "GoogledriveClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "Item", + "ItemsList", + "ObjectEntity", + "PassThroughNativeQuery", + "Procedure", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TablesList", + "TabularDataSetsMetadata", +] + # Type Definitions @@ -29,56 +52,84 @@ class BlobMetadata: Response for Get file metadata using id """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - folder_id: Optional[str] = field( + folder_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FolderId"}, ) """The unique id of the parent folder of the file or folder.""" - folder_path: Optional[str] = field( + folder_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FolderPath"}, ) """The current path of the parent folder of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The filelocator of the file or folder.""" - last_modified_by: Optional[str] = field( + last_modified_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModifiedBy"}, ) """The user who last modified the file or folder.""" @@ -90,8 +141,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -100,25 +161,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -130,15 +195,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -150,7 +217,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -163,26 +230,30 @@ class TableMetadata: Definition: TableMetadata """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Table name""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Table title""" - x_ms_permission: Optional[str] = field( + x_ms_permission: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-permission"}, ) """Table permission""" - x_ms_capabilities: Optional[TableCapabilitiesMetadata] = field( + x_ms_capabilities: Optional[TableCapabilitiesMetadata | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-capabilities"}, ) - schema: Optional[ObjectEntity] = None - referenced_entities: Optional[ObjectEntity] = field( + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + referenced_entities: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "referencedEntities"}, ) - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webUrl"}, ) """Url link""" @@ -194,30 +265,42 @@ class TableCapabilitiesMetadata: Definition: TableCapabilitiesMetadata """ - sort_restrictions: Optional[TableSortRestrictionsMetadata] = field( + sort_restrictions: Optional[ + TableSortRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sortRestrictions"}, ) - filter_restrictions: Optional[TableFilterRestrictionsMetadata] = field( + filter_restrictions: Optional[ + TableFilterRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterRestrictions"}, ) - select_restrictions: Optional[TableSelectRestrictionsMetadata] = field( + select_restrictions: Optional[ + TableSelectRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selectRestrictions"}, ) - is_only_server_pagable: Optional[bool] = field( + is_only_server_pagable: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isOnlyServerPagable"}, ) """Server paging restrictions""" - filter_function_support: Optional[List[str]] = field( + filter_function_support: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterFunctionSupport"}, ) """List of supported filter capabilities""" - server_paging_options: Optional[List[str]] = field( + server_paging_options: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "serverPagingOptions"}, ) """List of supported server-driven paging capabilities""" @@ -229,15 +312,17 @@ class TableSortRestrictionsMetadata: Definition: TableSortRestrictionsMetadata """ - sortable: Optional[bool] = None + sortable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has sortable columns""" - unsortable_properties: Optional[List[str]] = field( + unsortable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "unsortableProperties"}, ) """List of unsortable properties""" - ascending_only_properties: Optional[List[str]] = field( + ascending_only_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ascendingOnlyProperties"}, ) """List of properties which support ascending order only""" @@ -249,15 +334,17 @@ class TableFilterRestrictionsMetadata: Definition: TableFilterRestrictionsMetadata """ - filterable: Optional[bool] = None + filterable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has filterable columns""" - non_filterable_properties: Optional[List[str]] = field( + non_filterable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nonFilterableProperties"}, ) """List of non filterable properties""" - required_properties: Optional[List[str]] = field( + required_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredProperties"}, ) """List of required properties""" @@ -269,7 +356,7 @@ class TableSelectRestrictionsMetadata: Definition: TableSelectRestrictionsMetadata """ - selectable: Optional[bool] = None + selectable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has selectable columns""" @@ -279,7 +366,12 @@ class TablesList: Definition: TablesList """ - value: Optional[List[Table]] = None + value: Optional[ + List[Table | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Tables""" @@ -289,15 +381,21 @@ class Table: Definition: Table """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the table. The name is used at runtime.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the table.""" - dynamic_properties: Optional[Dict[str, str]] = field( + dynamic_properties: Optional[Dict[str, str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DynamicProperties"}, ) """Additional table properties provided by the connector to the clients.""" @@ -309,8 +407,9 @@ class Item: Definition: Item """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) @@ -321,7 +420,12 @@ class ItemsList: Definition: ItemsList """ - value: Optional[List[Item]] = None + value: Optional[ + List[Item | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Items""" @@ -331,7 +435,12 @@ class DataSetsList: Definition: DataSetsList """ - value: Optional[List[DataSet]] = None + value: Optional[ + List[DataSet | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of datasets""" @@ -341,14 +450,24 @@ class DataSet: Definition: DataSet """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Dataset name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Dataset display name""" - query: Optional[List[PassThroughNativeQuery]] = None + query: Optional[ + List[PassThroughNativeQuery | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Pass-through Native Queries""" @@ -358,10 +477,15 @@ class Procedure: Definition: Procedure """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Procedure name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Procedure display name""" @@ -373,8 +497,9 @@ class PassThroughNativeQuery: Definition: PassThroughNativeQuery """ - language: Optional[str] = field( + language: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Language"}, ) """Query language""" @@ -388,16 +513,16 @@ class GoogledriveClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -408,8 +533,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -417,8 +542,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -430,7 +555,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -445,7 +570,46 @@ def __init__( def connector_name(self) -> str: return "googledrive" - async def get_file_metadata_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def get_file_metadata( self, id: str, *, @@ -458,6 +622,21 @@ async def get_file_metadata_async( Get file metadata using id Retrieves file metadata from Google Drive using id + + Swagger operation ID: `GetFileMetadata`. + + Args: + id: Specify the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -467,7 +646,7 @@ async def get_file_metadata_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -481,6 +660,7 @@ async def get_file_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -488,7 +668,7 @@ async def get_file_metadata_async( return json.loads(response.text) - async def update_file_async( + def update_file( self, input: bytes, id: str, @@ -502,6 +682,22 @@ async def update_file_async( Update file Updates a file in Google Drive + + Swagger operation ID: `UpdateFile`. + + Args: + input: The binary request body. + id: Specify the file to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -511,7 +707,7 @@ async def update_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, @@ -528,6 +724,7 @@ async def update_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -535,7 +732,7 @@ async def update_file_async( return json.loads(response.text) - async def delete_file_async( + def delete_file( self, id: str, *, @@ -548,6 +745,21 @@ async def delete_file_async( Delete file Deletes a file from Google Drive + + Swagger operation ID: `DeleteFile`. + + Args: + id: Specify the file to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -557,7 +769,7 @@ async def delete_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -571,9 +783,10 @@ async def delete_file_async( request_url, response.status, response.text, + response=response, ) - async def get_file_metadata_by_path_async( + def get_file_metadata_by_path( self, path: str, *, @@ -586,6 +799,21 @@ async def get_file_metadata_by_path_async( Get file metadata using path Retrieves file metadata from Google Drive using path + + Swagger operation ID: `GetFileMetadataByPath`. + + Args: + path: Path of the file in Google Drive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/GetFileByPath" @@ -599,7 +827,7 @@ async def get_file_metadata_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -613,6 +841,7 @@ async def get_file_metadata_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -620,11 +849,11 @@ async def get_file_metadata_by_path_async( return json.loads(response.text) - async def get_file_content_by_path_async( + def get_file_content_by_path( self, path: str, - infer_content_type: Optional[bool] = None, *, + infer_content_type: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -634,6 +863,22 @@ async def get_file_content_by_path_async( Get file content using path Retrieves file content from Google Drive using path + + Swagger operation ID: `GetFileContentByPath`. + + Args: + path: Path of the file in Google Drive. + infer_content_type: Infer content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -653,7 +898,7 @@ async def get_file_content_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -667,15 +912,16 @@ async def get_file_content_by_path_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_file_content_async( + def get_file_content( self, id: str, - infer_content_type: Optional[bool] = None, *, + infer_content_type: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -685,6 +931,22 @@ async def get_file_content_async( Get file content using id Retrieves file content from Google Drive using id + + Swagger operation ID: `GetFileContent`. + + Args: + id: Unique identifier of the file to retrieve in Google Drive. + infer_content_type: Infer content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -703,7 +965,7 @@ async def get_file_content_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -717,16 +979,17 @@ async def get_file_content_async( request_url, response.status, response.text, + response=response, ) return response.content - async def copy_file_async( + def copy_file( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -736,6 +999,24 @@ async def copy_file_async( Copy file Copies a file on Google Drive + + Swagger operation ID: `CopyFile`. + + Args: + source: Url to source file. + destination: Destination file path in Google Drive, including + target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/copyFile" @@ -758,7 +1039,7 @@ async def copy_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -772,6 +1053,7 @@ async def copy_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -779,7 +1061,7 @@ async def copy_file_async( return json.loads(response.text) - async def list_folder_async( + def list_folder( self, id: str, *, @@ -787,11 +1069,30 @@ async def list_folder_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List files in folder List files in a Google Drive folder + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListFolder`. + + Args: + id: Specify the folder in Google Drive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -800,67 +1101,127 @@ async def list_folder_async( f"/folders" f"/{quote(quote(str(id), safe=''), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def list_root_folder_async( + def list_root_folder( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List files in root folder Lists files in the Google Drive root folder + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListRootFolder`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/folders" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def create_file_async( + return ItemPaged(get_next, extract_data) + + def create_file( self, input: bytes, folder_id: str, @@ -875,6 +1236,23 @@ async def create_file_async( Create file Uploads a file to a Google Drive folder selected by its identifier + + Swagger operation ID: `CreateFileV2`. + + Args: + input: The binary request body. + folder_id: Folder to upload the file to Google Drive. + name: Name of the file to create in Google Drive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/v2/files" @@ -892,7 +1270,7 @@ async def create_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -909,6 +1287,7 @@ async def create_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -916,12 +1295,12 @@ async def create_file_async( return json.loads(response.text) - async def extract_folder_async( + def extract_folder( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -931,6 +1310,23 @@ async def extract_folder_async( Extract archive to folder Extracts an archive file into a folder in Google Drive (example: .zip) + + Swagger operation ID: `ExtractFolderV2`. + + Args: + source: Path to the archive file. + destination: Path in Google Drive to extract the archive contents. + overwrite: Overwrites the destination files if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/extractFolderV2" @@ -953,7 +1349,7 @@ async def extract_folder_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -967,6 +1363,7 @@ async def extract_folder_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/googletasks.py b/src/azure/connectors/googletasks.py index 9037a95..7bf2313 100644 --- a/src/azure/connectors/googletasks.py +++ b/src/azure/connectors/googletasks.py @@ -5,21 +5,33 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "GoogletasksClient", + "TaskCreate", + "TaskList", + "TaskListCreate", + "TaskListEntry", + "TaskListList", + "TaskObject", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +41,12 @@ class TaskListList: Response for List task lists """ - items: Optional[List[TaskListEntry]] = None + items: Optional[ + List[TaskListEntry | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Task lists in the lists.""" @@ -39,16 +56,17 @@ class TaskListEntry: Response for Create a task list """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier of the task list.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the task list.""" - self_link: Optional[str] = field( + self_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selfLink"}, ) """A link to this task list.""" - updated: Optional[str] = None + updated: Optional[str] = dataclass_field(default=None, kw_only=True) """The time the task list was last updated.""" @@ -58,7 +76,12 @@ class TaskList: Response for Lists the tasks for a task list """ - items: Optional[List[TaskObject]] = None + items: Optional[ + List[TaskObject | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The tasks in the list.""" @@ -68,28 +91,29 @@ class TaskObject: Response for Create a task in a task list """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier of the task.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the task.""" - updated: Optional[str] = None + updated: Optional[str] = dataclass_field(default=None, kw_only=True) """The last time the task was updated.""" - self_link: Optional[str] = field( + self_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selfLink"}, ) """A link to the task.""" - parent: Optional[str] = None + parent: Optional[str] = dataclass_field(default=None, kw_only=True) """The parent of the task.""" - position: Optional[str] = None + position: Optional[str] = dataclass_field(default=None, kw_only=True) """The position of the task.""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """The notes for the task.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status of the task.""" - due: Optional[str] = None + due: Optional[str] = dataclass_field(default=None, kw_only=True) """The datetime the task is due.""" - completed: Optional[str] = None + completed: Optional[str] = dataclass_field(default=None, kw_only=True) """The datetime the task was completed.""" @@ -99,7 +123,7 @@ class TaskListCreate: Definition: TaskListCreate """ - title: Optional[str] = None + title: str """The title of the task list.""" @@ -109,11 +133,11 @@ class TaskCreate: Definition: TaskCreate """ - title: Optional[str] = None + title: str """The title of the task.""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """The notes for the task.""" - due: Optional[str] = None + due: Optional[str] = dataclass_field(default=None, kw_only=True) """The datetime the task is due.""" @@ -125,16 +149,16 @@ class GoogletasksClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -145,8 +169,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -154,8 +178,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -167,7 +191,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -182,45 +206,123 @@ def __init__( def connector_name(self) -> str: return "googletasks" - async def list_task_lists_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_task_lists( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List task lists List all task lists. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTaskLists`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/users/@me/lists" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() - async def create_task_list_async( + return ItemPaged(get_next, extract_data) + + def create_task_list( self, - input: TaskListCreate, + input: TaskListCreate | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -231,10 +333,26 @@ async def create_task_list_async( Create a task list Creates a new task list. + + Swagger operation ID: `CreateTaskList`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/users/@me/lists" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -248,6 +366,7 @@ async def create_task_list_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -255,7 +374,7 @@ async def create_task_list_async( return json.loads(response.text) - async def list_tasks_async( + def list_tasks( self, task_list_id: str, *, @@ -263,41 +382,81 @@ async def list_tasks_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Lists the tasks for a task list Lists the tasks for a specific task list. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTasks`. + + Args: + task_list_id: The id of the task list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/lists/{quote(str(task_list_id), safe='')}/tasks" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item - async def create_task_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def create_task( self, - input: TaskCreate, + input: TaskCreate | Mapping[str, Any], task_list_id: str, *, timeout: Optional[float] = None, @@ -309,13 +468,30 @@ async def create_task_async( Create a task in a task list Create a task in a specific task list. + + Swagger operation ID: `CreateTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + task_list_id: The id of the task list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/lists/{quote(str(task_list_id), safe='')}/tasks" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -329,6 +505,7 @@ async def create_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -336,7 +513,7 @@ async def create_task_async( return json.loads(response.text) - async def list_task_async( + def list_task( self, task_list_id: str, task_id: str, @@ -350,6 +527,22 @@ async def list_task_async( Get a task from a task list Get specific task from the specified task list. + + Swagger operation ID: `ListTask`. + + Args: + task_list_id: The id of the task list. + task_id: The id of the task. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -359,7 +552,7 @@ async def list_task_async( f"/{quote(str(task_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -373,6 +566,7 @@ async def list_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/impexium.py b/src/azure/connectors/impexium.py index c0fafca..75425a8 100644 --- a/src/azure/connectors/impexium.py +++ b/src/azure/connectors/impexium.py @@ -5,21 +5,180 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "ImpexiumClient", + "AbandonedCheckoutData", + "ActivityData", + "AddActivityInput", + "AddCategoriesForAnIndividualInput", + "AddCategoriesForAnOrganizationInput", + "AddEmailToIndividualInput", + "AddExamScoresInput", + "AddIndividualInput", + "AddOrUpdateAListOfCustomFieldsPerIndividualInput", + "AddOrUpdateAListOfCustomFieldsPerOrganizationInput", + "AddOrganizationInput", + "AddRelationshipToIndividualInput", + "AddToCommitteeResponse", + "AddWebLinkForIndividualInput", + "AddWebLinkForOrganizationInput", + "AddressSaveData", + "AwardData", + "AwardNominationData", + "AwardRecipientIndividualData", + "AwardRecipientOrganizationData", + "AwardsGetIndividualAwardRecipientsResponse", + "AwardsGetOrganizationAwardRecipientsResponse", + "BaseNoteData", + "CertificationData", + "CommitteeData", + "CommitteeMemberCreateData", + "CommitteeMemberData", + "CommitteeMemberPayload", + "CommitteeMemberUpdateData", + "CommitteeNomineeData", + "CommitteeNomineeSaveData", + "CommitteePositionData", + "ContactData", + "CountryData", + "CourseAttendeeData", + "CustomFieldData", + "CustomFieldResultData", + "CustomFieldValueData", + "CustomerAddressUpdatedPayload", + "CustomerCustomFieldValuePayload", + "CustomerMergedPayload", + "CustomerPhoneUpdatedPayload", + "CustomerRelationshipUpdatedPayload", + "CustomerRequestPayload", + "DeleteAnIndividualWebLinkInput", + "DeleteAnOrganizationWebLinkInput", + "EducationCreditData", + "EmailData", + "EmailPayload", + "EventData", + "EventRegistrationSubstitutedPayload", + "ExamData", + "ExamScoreData", + "ExamScoreResultData", + "ExhibitData", + "ExhibitorData", + "FindCustomerPhoneResponse", + "FindIndividualIdOrEmailResponse", + "FindMembersByNameResponse", + "FindMembersOrIndividualsByFirstAndLastNameResponse", + "FindMembersOrIndividualsByNameResponse", + "GetAListOfAllServicesOfAnOrganizationResponse", + "GetAListOfLicensesResponse", + "GetAbandonedCheckoutsResponse", + "GetAllCommitteesResponse", + "GetAllEventRegistrationsInformationForAnIndividualResponse", + "GetAllEventsResponse", + "GetAllOpenOrdersForAnIndividualResponse", + "GetAllStatesByCountryResponse", + "GetCommitteeInformationForAnIndividualResponse", + "GetCourseAttendeesResponse", + "GetIndividualsActiveSubscriptionsResponse", + "GetIndividualsRelationshipsResponse", + "GetListOfActiveCertificationsForAnIndividualResponse", + "GetListOfActiveCertificationsForAnOrganizationResponse", + "GetNomineesByCommitteeResponse", + "GetOrganizationsActiveSubscriptionsResponse", + "GetOrganizationsRelationshipsResponse", + "GetPositionsByCommitteeResponse", + "GetPurchasesForAnIndividualResponse", + "GetSubCommitteesResponse", + "GetUpcomingEventsResponse", + "IndividualData", + "IndividualLookupBasicData", + "IndividualPayload", + "IndividualRequestToBeForgottenPayload", + "IndividualsLookupByNameResponse", + "LicenseData", + "ListAllAwardsResponse", + "ListAllCountriesResponse", + "ListAllEventCancellationsByEventResponse", + "ListAllExhibitorsResponse", + "ListAllExhibitsResponse", + "ListAllIndividualsResponse", + "ListAllOpenCustomerRequestResponse", + "ListCompletedUserTasksByUserIdOrEmailResponse", + "ListOfAllIndividualMembersResponse", + "ListOfAllOrganizationMembersResponse", + "ListOfCustomerRelationshipsResponse", + "ListOfExamsResponse", + "ListPendingUserTasksByUserIdOrEmailResponse", + "ListRegistrantsResponse", + "MarkRegistrantAttendedInput", + "MembershipData", + "MembershipTypeTerminatedPayload", + "NoteData", + "NotificationData", + "OrganizationData", + "OrganizationLookupBasicData", + "OrganizationLookupByNameResponse", + "PayableOrderData", + "PhoneDataSet", + "PhoneSaveData", + "ProductPurchasePayload", + "PurchaseCancelledPayload", + "PurchasedItemData", + "RegisterAnIndividualForAFreeSessionInput", + "RegistrantCancellationData", + "RegistrantData", + "RegistrationData", + "RelationshipData", + "RelationshipTypeData", + "RequestData", + "RequestSaveData", + "RequestUpdateData", + "SaveCategoryBasicData", + "SaveRelationshipForOrganizationInput", + "ServiceData", + "SessionRegistrationData", + "StateProvinceData", + "SubscriptionData", + "TaskData", + "TaskSaveData", + "UpdateAnIndividualEmailInput", + "UpdateAwardNominationData", + "UpdateOrganizationInput", + "UserTaskData", + "WhenCommitteeMemberUpdatedInput", + "WhenCustomerAddressUpdatedInput", + "WhenCustomerCustomFieldValueUpdatedInput", + "WhenCustomerIsMergedInput", + "WhenCustomerPhoneUpdatedInput", + "WhenCustomerRelationshipUpdatedInput", + "WhenEmailUpdatedInput", + "WhenEventRegistrationSubstitutedInput", + "WhenIndividualCreatedInput", + "WhenIndividualDeletedInput", + "WhenIndividualRequestForgottenInput", + "WhenMembershipTerminatedInput", + "WhenProductPurchasedInput", + "WhenPurchaseCancelledInput", + "WhenPurchasePaidInput", + "WhenRequestUpdatedInput", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,13 +188,15 @@ class GetAbandonedCheckoutsResponse: Response for Get Abandoned Checkouts """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number""" - data_list: Optional[List[AbandonedCheckoutData]] = field( + data_list: Optional[List[AbandonedCheckoutData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -47,13 +208,15 @@ class ListAllExhibitorsResponse: Response for List All Exhibitors """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number""" - data_list: Optional[List[ExhibitorData]] = field( + data_list: Optional[List[ExhibitorData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -65,13 +228,15 @@ class ListOfExamsResponse: Response for List of Exams """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number""" - data_list: Optional[List[ExamData]] = field( + data_list: Optional[List[ExamData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -83,13 +248,15 @@ class ListRegistrantsResponse: Response for List Registrants """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[RegistrantData]] = field( + data_list: Optional[List[RegistrantData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -101,19 +268,21 @@ class GetCourseAttendeesResponse: Response for Get Course Attendees """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[CourseAttendeeData]] = field( + data_list: Optional[List[CourseAttendeeData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" -AddExamScoresInput = List["ExamScoreData"] +AddExamScoresInput = List["ExamScoreData | Mapping[str, Any]"] @dataclass @@ -122,14 +291,15 @@ class ExamScoreResultData: Response for Add Exam Scores """ - individual_record_number: Optional[str] = field( + individual_record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "individualRecordNumber"}, ) """Individual Record Number.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status.""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """Message.""" @@ -139,13 +309,15 @@ class FindMembersByNameResponse: Response for Find Members by Name """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[ContactData]] = field( + data_list: Optional[List[ContactData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -157,19 +329,23 @@ class GetPurchasesForAnIndividualResponse: Response for Get Purchases for an Individual """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[PurchasedItemData]] = field( + data_list: Optional[List[PurchasedItemData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" -AddOrUpdateAListOfCustomFieldsPerOrganizationInput = List["CustomFieldValueData"] +AddOrUpdateAListOfCustomFieldsPerOrganizationInput = List[ + "CustomFieldValueData | Mapping[str, Any]" +] @dataclass @@ -178,12 +354,13 @@ class CustomFieldResultData: Response for Add or Update a List of Custom Fields Per Organization """ - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status.""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """Message.""" - custom_field_name: Optional[str] = field( + custom_field_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customFieldName"}, ) """Custom Field Name.""" @@ -195,11 +372,11 @@ class CustomFieldData: Response for Get Individual Custom Field Values """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - caption: Optional[str] = None + caption: Optional[str] = dataclass_field(default=None, kw_only=True) """Caption.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Custom Field Value. For multi-selects, use \"|\" as delimiter.""" @@ -209,13 +386,17 @@ class ListAllEventCancellationsByEventResponse: Response for List All Event Cancellations by Event """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[RegistrantCancellationData]] = field( + data_list: Optional[ + List[RegistrantCancellationData | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -227,13 +408,15 @@ class GetAllOpenOrdersForAnIndividualResponse: Response for Get All Open Orders for an Individual """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number""" - data_list: Optional[List[PayableOrderData]] = field( + data_list: Optional[List[PayableOrderData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -245,13 +428,15 @@ class ListCompletedUserTasksByUserIdOrEmailResponse: Response for List Completed User Tasks by User ID or Email """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[UserTaskData]] = field( + data_list: Optional[List[UserTaskData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -263,13 +448,15 @@ class ListPendingUserTasksByUserIdOrEmailResponse: Response for List Pending User Tasks by User ID or Email """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[UserTaskData]] = field( + data_list: Optional[List[UserTaskData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -281,24 +468,27 @@ class TaskData: Response for Update Task by Task Number """ - task_number: Optional[str] = field( + task_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "taskNumber"}, ) """Task Number.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" - category: Optional[str] = None + category: Optional[str] = dataclass_field(default=None, kw_only=True) """Category.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """Start Date.""" - due_date: Optional[str] = field( + due_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dueDate"}, ) """Due Date.""" @@ -310,13 +500,15 @@ class ListAllCountriesResponse: Response for List All Countries """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number""" - data_list: Optional[List[CountryData]] = field( + data_list: Optional[List[CountryData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -328,13 +520,15 @@ class GetAllStatesByCountryResponse: Response for Get All States by Country """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number""" - data_list: Optional[List[StateProvinceData]] = field( + data_list: Optional[List[StateProvinceData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -346,13 +540,15 @@ class ListAllExhibitsResponse: Response for List All Exhibits """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number""" - data_list: Optional[List[ExhibitData]] = field( + data_list: Optional[List[ExhibitData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -364,19 +560,21 @@ class RequestUpdateData: Response for Update Customer Request """ - request_number: Optional[str] = field( + request_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requestNumber"}, ) """Request Number.""" - closed_date: Optional[str] = field( + closed_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "closedDate"}, ) """Closed Date.""" -AddCategoriesForAnOrganizationInput = List["SaveCategoryBasicData"] +AddCategoriesForAnOrganizationInput = List["SaveCategoryBasicData | Mapping[str, Any]"] @dataclass @@ -385,13 +583,15 @@ class ListOfCustomerRelationshipsResponse: Response for List of Customer Relationships """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[RelationshipTypeData]] = field( + data_list: Optional[List[RelationshipTypeData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -403,13 +603,15 @@ class ListAllOpenCustomerRequestResponse: Response for List All Open Customer Request """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[RequestData]] = field( + data_list: Optional[List[RequestData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -421,60 +623,71 @@ class MembershipData: Response for Get Organization Inactive Memberships """ - membership_type: Optional[str] = field( + membership_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "membershipType"}, ) """Membership Type.""" - membership_type_id: Optional[str] = field( + membership_type_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "membershipTypeId"}, ) """Membership Type ID.""" - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Code.""" - expire_date: Optional[str] = field( + expire_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "expireDate"}, ) """Expire Date.""" - grace_expire_date: Optional[str] = field( + grace_expire_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "graceExpireDate"}, ) """Grace Expire Date.""" - inherited_membership_benefits: Optional[bool] = field( + inherited_membership_benefits: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "inheritedMembershipBenefits"}, ) """Inherited Membership Benefits.""" - renewal_url: Optional[str] = field( + renewal_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "renewalUrl"}, ) """Renewal URL.""" - join_date: Optional[str] = field( + join_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "joinDate"}, ) """Join Date.""" - terminate_date: Optional[str] = field( + terminate_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "terminateDate"}, ) """Terminate Date.""" - effective_date: Optional[str] = field( + effective_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "effectiveDate"}, ) """Effective Date.""" - membership_unique_id: Optional[str] = field( + membership_unique_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "membershipUniqueId"}, ) """Membership Unique ID.""" - terms_list: Optional[List[Dict[str, Any]]] = field( + terms_list: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "termsList"}, ) """Terms List""" @@ -486,36 +699,41 @@ class UserTaskData: Response for Update User Task Progress or Mark as Completed """ - task_number: Optional[str] = field( + task_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "taskNumber"}, ) """Task Number.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" - category: Optional[str] = None + category: Optional[str] = dataclass_field(default=None, kw_only=True) """Category.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description.""" - assigned_by: Optional[str] = field( + assigned_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignedBy"}, ) """Assigned By.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """Start Date.""" - due_date: Optional[str] = field( + due_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dueDate"}, ) """Due Date.""" - progress: Optional[str] = None + progress: Optional[str] = dataclass_field(default=None, kw_only=True) """Progress.""" - completed_date: Optional[str] = field( + completed_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "completedDate"}, ) """Completed Date.""" @@ -527,135 +745,158 @@ class IndividualData: Response for Find Members (Individuals) by First Name """ - first_name: Optional[str] = field( + first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "firstName"}, ) """First Name.""" - last_name: Optional[str] = field( + last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastName"}, ) """Last Name.""" - middle_name: Optional[str] = field( + middle_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "middleName"}, ) """Middle Name.""" - preferred_first_name: Optional[str] = field( + preferred_first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "preferredFirstName"}, ) """Preferred First Name.""" - second_last_name: Optional[str] = field( + second_last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "secondLastName"}, ) """Second Last Name.""" - prefix: Optional[str] = None + prefix: Optional[str] = dataclass_field(default=None, kw_only=True) """Prefix.""" - suffix: Optional[str] = None + suffix: Optional[str] = dataclass_field(default=None, kw_only=True) """Suffix.""" - gender: Optional[str] = None + gender: Optional[str] = dataclass_field(default=None, kw_only=True) """Gender.""" - primary_organization: Optional[Dict[str, Any]] = field( + primary_organization: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "primaryOrganization"}, ) - committees: Optional[List[Dict[str, Any]]] = None + committees: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Committees.""" - security_roles: Optional[List[Dict[str, Any]]] = field( + security_roles: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "securityRoles"}, ) """Security Roles.""" - user: Optional[Dict[str, Any]] = None - designation_data: Optional[List[Dict[str, Any]]] = field( + user: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + designation_data: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "designationData"}, ) """Designations.""" - relationships: Optional[List[Dict[str, Any]]] = None + relationships: Optional[ + List[Dict[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Relationships.""" - job_roles: Optional[List[Dict[str, Any]]] = field( + job_roles: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobRoles"}, ) """Job Roles.""" - tags: Optional[List[str]] = None + tags: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Tags.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Individual Id.""" - customer_type: Optional[str] = field( + customer_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customerType"}, ) """Customer Type.""" - record_number: Optional[str] = field( + record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordNumber"}, ) """Record Number.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - addresses: Optional[List[Dict[str, Any]]] = None + addresses: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Addresses.""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email.""" - image_uri: Optional[str] = field( + image_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "imageUri"}, ) """Image URI.""" - twitter: Optional[str] = None + twitter: Optional[str] = dataclass_field(default=None, kw_only=True) """Twitter.""" - linked_in: Optional[str] = field( + linked_in: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "linkedIn"}, ) """LinkedIn.""" - emails: Optional[List[Dict[str, Any]]] = None + emails: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Emails.""" - phones: Optional[List[Dict[str, Any]]] = None + phones: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Phones.""" - web_site: Optional[str] = field( + web_site: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webSite"}, ) """Website.""" - memberships: Optional[List[Dict[str, Any]]] = None + memberships: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Memberships.""" - category: Optional[str] = None + category: Optional[str] = dataclass_field(default=None, kw_only=True) """Category.""" - categories: Optional[List[Dict[str, Any]]] = None + categories: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Categories.""" - custom_fields: Optional[List[Dict[str, Any]]] = field( + custom_fields: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customFields"}, ) """Custom Fields.""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory.""" - links: Optional[List[Dict[str, Any]]] = None + links: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Links.""" - old_id: Optional[str] = field( + old_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldId"}, ) """Old Id.""" - is_deceased: Optional[bool] = field( + is_deceased: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isDeceased"}, ) """Is Deceased.""" -AddCategoriesForAnIndividualInput = List["SaveCategoryBasicData"] +AddCategoriesForAnIndividualInput = List["SaveCategoryBasicData | Mapping[str, Any]"] @dataclass @@ -664,13 +905,15 @@ class ListOfAllOrganizationMembersResponse: Response for List of All Organization Members """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[OrganizationData]] = field( + data_list: Optional[List[OrganizationData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -682,13 +925,15 @@ class ListOfAllIndividualMembersResponse: Response for List of All Individual Members """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[IndividualData]] = field( + data_list: Optional[List[IndividualData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -700,13 +945,15 @@ class GetListOfActiveCertificationsForAnOrganizationResponse: Response for Get List of Active Certifications for an Organization """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[CertificationData]] = field( + data_list: Optional[List[CertificationData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -718,19 +965,21 @@ class GetListOfActiveCertificationsForAnIndividualResponse: Response for Get List of Active Certifications for an Individual """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[CertificationData]] = field( + data_list: Optional[List[CertificationData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" -RegisterAnIndividualForAFreeSessionInput = List["SessionRegistrationData"] +RegisterAnIndividualForAFreeSessionInput = List["SessionRegistrationData | Mapping[str, Any]"] @dataclass @@ -739,13 +988,15 @@ class GetAListOfLicensesResponse: Response for Get a List of Licenses """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[LicenseData]] = field( + data_list: Optional[List[LicenseData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -757,13 +1008,15 @@ class ListAllAwardsResponse: Response for List All Awards """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[AwardData]] = field( + data_list: Optional[List[AwardData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -775,13 +1028,15 @@ class FindMembersOrIndividualsByNameResponse: Response for Find Members (Individuals) by Name """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[IndividualData]] = field( + data_list: Optional[List[IndividualData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -793,13 +1048,15 @@ class GetAListOfAllServicesOfAnOrganizationResponse: Response for Get a List of All Services of an Organization """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[ServiceData]] = field( + data_list: Optional[List[ServiceData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -811,9 +1068,9 @@ class ServiceData: Response for Add a Service to an Organization """ - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Code.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" @@ -823,24 +1080,30 @@ class PhoneDataSet: Response for Update Phone for an Individual """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID.""" - primary: Optional[bool] = None + primary: Optional[bool] = dataclass_field(default=None, kw_only=True) """Is Primary.""" - type_: Optional[int] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type.""" - country: Optional[Dict[str, Any]] = None - show_in_directory: Optional[bool] = field( + country: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory.""" - number: Optional[str] = None + number: Optional[str] = dataclass_field(default=None, kw_only=True) """Number.""" - extension: Optional[str] = None + extension: Optional[str] = dataclass_field(default=None, kw_only=True) """Extension.""" - type_name: Optional[str] = field( + type_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "typeName"}, ) """Type Name.""" @@ -852,9 +1115,13 @@ class DeleteAnIndividualWebLinkInput: Delete an Individual Web Link """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Url.""" @@ -864,9 +1131,13 @@ class AddWebLinkForIndividualInput: Add Web Link for Individual """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Url.""" @@ -876,13 +1147,15 @@ class GetNomineesByCommitteeResponse: Response for Get Nominees by Committee """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[CommitteeNomineeData]] = field( + data_list: Optional[List[CommitteeNomineeData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """Data List""" @@ -894,13 +1167,15 @@ class GetOrganizationsActiveSubscriptionsResponse: Response for Get Organization's Active Subscriptions """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[SubscriptionData]] = field( + data_list: Optional[List[SubscriptionData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -912,9 +1187,9 @@ class DeleteAnOrganizationWebLinkInput: Delete an Organization Web Link """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """Type.""" - url: Optional[str] = None + url: str """Url.""" @@ -924,9 +1199,9 @@ class AddWebLinkForOrganizationInput: Add Web Link for Organization """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """Type.""" - url: Optional[str] = None + url: str """Url.""" @@ -936,13 +1211,15 @@ class GetOrganizationsRelationshipsResponse: Response for Get Organization's Relationships """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[RelationshipData]] = field( + data_list: Optional[List[RelationshipData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """DataList""" @@ -954,43 +1231,51 @@ class AddressSaveData: Response for Add or Update Address to Organization """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID.""" - primary: Optional[bool] = None + primary: Optional[bool] = dataclass_field(default=None, kw_only=True) """Primary.""" - line1: Optional[str] = None + line1: Optional[str] = dataclass_field(default=None, kw_only=True) """Line 1.""" - line2: Optional[str] = None + line2: Optional[str] = dataclass_field(default=None, kw_only=True) """Line 2.""" - line3: Optional[str] = None + line3: Optional[str] = dataclass_field(default=None, kw_only=True) """Line 3.""" - city: Optional[str] = None + city: Optional[str] = dataclass_field(default=None, kw_only=True) """City.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """State.""" - zipcode: Optional[str] = None + zipcode: Optional[str] = dataclass_field(default=None, kw_only=True) """Zipcode.""" - country: Optional[str] = None + country: Optional[str] = dataclass_field(default=None, kw_only=True) """Country.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type.""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory.""" - is_preferred_shipping: Optional[bool] = field( + is_preferred_shipping: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isPreferredShipping"}, ) """Is Preferred Shipping.""" - is_preferred_billing: Optional[bool] = field( + is_preferred_billing: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isPreferredBilling"}, ) """Is Preferred Billing.""" - is_bad_address: Optional[bool] = field( + is_bad_address: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isBadAddress"}, ) """Is Bad Address.""" @@ -1005,13 +1290,15 @@ class GetUpcomingEventsResponse: Response for Get Upcoming Events """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[EventData]] = field( + data_list: Optional[List[EventData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """DataList""" @@ -1023,13 +1310,15 @@ class GetCommitteeInformationForAnIndividualResponse: Response for Get Committee Information for an Individual """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number""" - data_list: Optional[List[CommitteeMemberData]] = field( + data_list: Optional[List[CommitteeMemberData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """Data List.""" @@ -1041,13 +1330,15 @@ class GetAllEventsResponse: Response for Get All Events """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[EventData]] = field( + data_list: Optional[List[EventData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """DataList""" @@ -1059,13 +1350,15 @@ class GetAllEventRegistrationsInformationForAnIndividualResponse: Response for Get All Event Registrations Information for an Individual """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[RegistrationData]] = field( + data_list: Optional[List[RegistrationData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -1077,13 +1370,15 @@ class GetIndividualsRelationshipsResponse: Response for Get Individual's Relationships """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[RelationshipData]] = field( + data_list: Optional[List[RelationshipData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """Data List.""" @@ -1095,14 +1390,19 @@ class UpdateAnIndividualEmailInput: Update an Individual Email """ - primary: Optional[bool] = None + primary: Optional[bool] = dataclass_field(default=None, kw_only=True) """Primary.""" - address: Optional[str] = None + address: Optional[str] = dataclass_field(default=None, kw_only=True) """Address.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type.""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory""" @@ -1114,42 +1414,43 @@ class SaveRelationshipForOrganizationInput: Save Relationship for Organization """ - relationship_name: Optional[str] = field( - default=None, + relationship_name: str = dataclass_field( metadata={"wire_name": "relationshipName"}, ) """Relationship Name.""" - related_to_customer_record_number: Optional[str] = field( - default=None, + related_to_customer_record_number: str = dataclass_field( metadata={"wire_name": "relatedToCustomerRecordNumber"}, ) """Related To Customer Record Number.""" - reciprocal_relationship_name: Optional[str] = field( - default=None, + reciprocal_relationship_name: str = dataclass_field( metadata={"wire_name": "reciprocalRelationshipName"}, ) """Reciprocal Relationship Name.""" - is_primary: Optional[bool] = field( + is_primary: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isPrimary"}, ) """Is Primary.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """Start Date.""" - end_date: Optional[str] = field( + end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDate"}, ) """End Date.""" - is_reciprocal_primary: Optional[bool] = field( + is_reciprocal_primary: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isReciprocalPrimary"}, ) """Is Reciprocal Primary.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" @@ -1159,20 +1460,15 @@ class AddIndividualInput: Add Individual """ - first_name: Optional[str] = field( - default=None, - metadata={"wire_name": "firstName"}, - ) + first_name: str = dataclass_field(metadata={"wire_name": "firstName"}) """First Name.""" - last_name: Optional[str] = field( - default=None, - metadata={"wire_name": "lastName"}, - ) + last_name: str = dataclass_field(metadata={"wire_name": "lastName"}) """Last Name.""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email Address.""" - record_number: Optional[str] = field( + record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordNumber"}, ) """Record Number.""" @@ -1184,14 +1480,19 @@ class AddEmailToIndividualInput: Add Email to Individual """ - primary: Optional[bool] = None + primary: Optional[bool] = dataclass_field(default=None, kw_only=True) """Primary""" - address: Optional[str] = None + address: Optional[str] = dataclass_field(default=None, kw_only=True) """Address.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type.""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory""" @@ -1203,14 +1504,19 @@ class EmailData: Response for Add Email to Individual """ - primary: Optional[bool] = None + primary: Optional[bool] = dataclass_field(default=None, kw_only=True) """Is Primary Email.""" - address: Optional[str] = None + address: Optional[str] = dataclass_field(default=None, kw_only=True) """Address.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type.""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory.""" @@ -1222,13 +1528,15 @@ class FindMembersOrIndividualsByFirstAndLastNameResponse: Response for Find Members (Individuals) by First Name and Last Name """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[IndividualData]] = field( + data_list: Optional[List[IndividualData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -1240,14 +1548,15 @@ class AddActivityInput: Add Activity """ - category: Optional[str] = None + category: str """Category.""" - text: Optional[str] = None + text: str """Text.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """URL.""" - activity_date: Optional[str] = field( + activity_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "activityDate"}, ) """Activity Date.""" @@ -1259,13 +1568,15 @@ class FindIndividualIdOrEmailResponse: Response for Find Individual by Id or Email or Record Number """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[IndividualData]] = field( + data_list: Optional[List[IndividualData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """Data List.""" @@ -1277,38 +1588,39 @@ class AddRelationshipToIndividualInput: Add Relationship to Individual """ - relationship_name: Optional[str] = field( - default=None, + relationship_name: str = dataclass_field( metadata={"wire_name": "relationshipName"}, ) """Relationship Name.""" - related_to_customer_record_number: Optional[str] = field( - default=None, + related_to_customer_record_number: str = dataclass_field( metadata={"wire_name": "relatedToCustomerRecordNumber"}, ) """Related To Customer Record Number.""" - reciprocal_relationship_name: Optional[str] = field( - default=None, + reciprocal_relationship_name: str = dataclass_field( metadata={"wire_name": "reciprocalRelationshipName"}, ) """Reciprocal Relationship Name.""" - is_primary: Optional[bool] = field( + is_primary: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isPrimary"}, ) """Is Primary.""" - is_reciprocal_primary: Optional[bool] = field( + is_reciprocal_primary: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isReciprocalPrimary"}, ) """Is Reciprocal Primary.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """Start Date.""" - end_date: Optional[str] = field( + end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDate"}, ) """End Date.""" @@ -1320,13 +1632,17 @@ class IndividualsLookupByNameResponse: Response for Lookup Individuals """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[IndividualLookupBasicData]] = field( + data_list: Optional[ + List[IndividualLookupBasicData | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """Data List.""" @@ -1338,58 +1654,67 @@ class AddToCommitteeResponse: Response for Add Individual to Committee """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Member Id.""" - first_name: Optional[str] = field( + first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "firstName"}, ) """First Name.""" - last_name: Optional[str] = field( + last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastName"}, ) """Last Name.""" - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Code.""" - record_number: Optional[str] = field( + record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordNumber"}, ) """Record Number.""" - position: Optional[str] = None + position: Optional[str] = dataclass_field(default=None, kw_only=True) """Position.""" - position_code: Optional[str] = field( + position_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "positionCode"}, ) """Position Code.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """Start Date.""" - end_date: Optional[str] = field( + end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDate"}, ) """End Date.""" - primary_organization: Optional[Dict[str, Any]] = field( + primary_organization: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "primaryOrganization"}, ) - organization_representing: Optional[Dict[str, Any]] = field( + organization_representing: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "organizationRepresenting"}, ) - nominated_by_customer: Optional[Dict[str, Any]] = field( + nominated_by_customer: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nominatedByCustomer"}, ) - addresses: Optional[List[Dict[str, Any]]] = None - phones: Optional[List[Dict[str, Any]]] = None - emails: Optional[List[Dict[str, Any]]] = None - rank: Optional[int] = None + addresses: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + phones: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + emails: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + rank: Optional[int] = dataclass_field(default=None, kw_only=True) """Rank.""" @@ -1399,21 +1724,21 @@ class AddOrganizationInput: Add Organization """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id.""" - name: Optional[str] = None + name: str """Name.""" - show_in_directory: Optional[bool] = field( - default=None, + show_in_directory: bool = dataclass_field( metadata={"wire_name": "showInDirectory"}, ) """Show In Directory.""" - branch_name: Optional[str] = field( + branch_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "branchName"}, ) """Branch Name.""" - website: Optional[str] = None + website: Optional[str] = dataclass_field(default=None, kw_only=True) """Website.""" @@ -1423,86 +1748,97 @@ class OrganizationData: Response for Add Organization """ - contact_ids: Optional[List[str]] = field( + contact_ids: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contactIds"}, ) """Contact Ids.""" - parent_company_id: Optional[str] = field( + parent_company_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentCompanyId"}, ) """Parent Company Id.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description.""" - branch_name: Optional[str] = field( + branch_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "branchName"}, ) """Branch Name.""" - tags: Optional[List[str]] = None + tags: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Tags.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Organization Id.""" - customer_type: Optional[str] = field( + customer_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customerType"}, ) """Customer Type.""" - record_number: Optional[str] = field( + record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordNumber"}, ) """Record Number.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Organization Name.""" - addresses: Optional[List[Dict[str, Any]]] = None + addresses: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Addresses.""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email.""" - image_uri: Optional[str] = field( + image_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "imageUri"}, ) """Image URI.""" - twitter: Optional[str] = None + twitter: Optional[str] = dataclass_field(default=None, kw_only=True) """Twitter.""" - linked_in: Optional[str] = field( + linked_in: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "linkedIn"}, ) """LinkedIn.""" - emails: Optional[List[Dict[str, Any]]] = None + emails: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Emails.""" - phones: Optional[List[Dict[str, Any]]] = None + phones: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Phones.""" - web_site: Optional[str] = field( + web_site: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webSite"}, ) """Website.""" - memberships: Optional[List[Dict[str, Any]]] = None + memberships: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Memberships.""" - category: Optional[str] = None + category: Optional[str] = dataclass_field(default=None, kw_only=True) """Category.""" - categories: Optional[List[Dict[str, Any]]] = None + categories: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Categories.""" - custom_fields: Optional[List[Dict[str, Any]]] = field( + custom_fields: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customFields"}, ) """Custom Fields.""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory.""" - links: Optional[List[Dict[str, Any]]] = None + links: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Links.""" - old_id: Optional[str] = field( + old_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldId"}, ) """Old Id.""" @@ -1514,21 +1850,23 @@ class UpdateOrganizationInput: Update Organization """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description.""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory.""" - branch_name: Optional[str] = field( + branch_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "branchName"}, ) """Branch Name.""" - website: Optional[str] = None + website: Optional[str] = dataclass_field(default=None, kw_only=True) """Website.""" @@ -1538,13 +1876,17 @@ class OrganizationLookupByNameResponse: Response for Lookup Organizations """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[OrganizationLookupBasicData]] = field( + data_list: Optional[ + List[OrganizationLookupBasicData | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """Data List.""" @@ -1556,13 +1898,15 @@ class GetAllCommitteesResponse: Response for Get All Committees """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[CommitteeData]] = field( + data_list: Optional[List[CommitteeData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -1574,13 +1918,15 @@ class GetPositionsByCommitteeResponse: Response for Get Positions by Committee """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[CommitteePositionData]] = field( + data_list: Optional[List[CommitteePositionData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -1592,13 +1938,15 @@ class GetSubCommitteesResponse: Response for Get Sub-Committees """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """pageNumber""" - data_list: Optional[List[CommitteeData]] = field( + data_list: Optional[List[CommitteeData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -1610,13 +1958,15 @@ class GetIndividualsActiveSubscriptionsResponse: Response for Get Individual's Active Subscriptions """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[SubscriptionData]] = field( + data_list: Optional[List[SubscriptionData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """dataList""" @@ -1628,13 +1978,15 @@ class ListAllIndividualsResponse: Response for List all Individuals """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[IndividualData]] = field( + data_list: Optional[List[IndividualData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) @@ -1645,13 +1997,15 @@ class FindCustomerPhoneResponse: Response for Find Customer by Phone Number """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[Dict[str, Any]]] = field( + data_list: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) @@ -1665,13 +2019,17 @@ class AwardsGetIndividualAwardRecipientsResponse: Response for List Award Individual Recipients """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[AwardRecipientIndividualData]] = field( + data_list: Optional[ + List[AwardRecipientIndividualData | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """Data List.""" @@ -1683,13 +2041,17 @@ class AwardsGetOrganizationAwardRecipientsResponse: Response for List Award Organization Recipients """ - page_number: Optional[int] = field( + page_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageNumber"}, ) """Page Number.""" - data_list: Optional[List[AwardRecipientOrganizationData]] = field( + data_list: Optional[ + List[AwardRecipientOrganizationData | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dataList"}, ) """Data List.""" @@ -1701,19 +2063,13 @@ class WhenIndividualCreatedInput: When an individual is created """ - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -1723,19 +2079,13 @@ class WhenIndividualDeletedInput: When an individual is deleted """ - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -1745,19 +2095,13 @@ class WhenIndividualRequestForgottenInput: When an individual requests to be forgotten """ - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -1767,23 +2111,17 @@ class WhenProductPurchasedInput: When a product is purchased """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id.""" - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - filters: Optional[List[str]] = None + filters: List[str] """Filters.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -1793,19 +2131,13 @@ class WhenCommitteeMemberUpdatedInput: When a committee member is updated """ - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -1815,23 +2147,17 @@ class WhenPurchaseCancelledInput: When a purchase is canceled """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id.""" - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - filters: Optional[List[str]] = None + filters: List[str] """Filters.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -1841,19 +2167,13 @@ class WhenRequestUpdatedInput: When a customer request is updated """ - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -1863,19 +2183,13 @@ class WhenEmailUpdatedInput: When a customer email is updated """ - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -1885,21 +2199,15 @@ class WhenCustomerCustomFieldValueUpdatedInput: When a customer custom field value is updated """ - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - filters: Optional[List[str]] = None + filters: List[str] """Filters.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -1909,19 +2217,13 @@ class WhenCustomerIsMergedInput: When a customer is merged """ - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -1931,19 +2233,13 @@ class WhenCustomerRelationshipUpdatedInput: When a customer relationship is updated """ - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -1953,19 +2249,13 @@ class WhenCustomerPhoneUpdatedInput: When a customer phone is updated """ - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -1975,19 +2265,13 @@ class WhenCustomerAddressUpdatedInput: When a customer address is updated """ - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -1997,21 +2281,15 @@ class WhenEventRegistrationSubstitutedInput: When an event registration is substituted """ - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - filters: Optional[List[str]] = None + filters: List[str] """Filters.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -2021,21 +2299,15 @@ class WhenPurchasePaidInput: When a purchase is paid """ - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - filters: Optional[List[str]] = None + filters: List[str] """Filters.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -2045,21 +2317,15 @@ class WhenMembershipTerminatedInput: When a membership is terminated """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id.""" - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" - secret: Optional[str] = None + secret: str """Secret.""" - call_back_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callBackUrl"}, - ) + call_back_url: str = dataclass_field(metadata={"wire_name": "callBackUrl"}) """Callback URL.""" - description: Optional[str] = None + description: str """Description.""" @@ -2069,21 +2335,24 @@ class AbandonedCheckoutData: Definition: AbandonedCheckoutData """ - created_on: Optional[str] = field( + created_on: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdOn"}, ) """Created On""" - created_by_email_address: Optional[str] = field( + created_by_email_address: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdByEmailAddress"}, ) """Created By Email Address""" - currency: Optional[str] = None + currency: Optional[str] = dataclass_field(default=None, kw_only=True) """Currency""" - customer: Optional[Dict[str, Any]] = None - line_items: Optional[List[Dict[str, Any]]] = field( + customer: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + line_items: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lineItems"}, ) """Line Items""" @@ -2095,9 +2364,9 @@ class ExhibitorData: Definition: ExhibitorData """ - organization: Optional[Dict[str, Any]] = None + organization: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Organization""" - booths: Optional[List[Dict[str, Any]]] = None + booths: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Booths""" @@ -2107,77 +2376,93 @@ class ExamData: Definition: ExamData """ - exam_start_date: Optional[str] = field( + exam_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "examStartDate"}, ) """Exam Start Date""" - exam_end_date: Optional[str] = field( + exam_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "examEndDate"}, ) """Exam End Date""" - exam_number: Optional[str] = field( + exam_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "examNumber"}, ) """Exam Number""" - education_credits: Optional[List[Dict[str, Any]]] = field( + education_credits: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "educationCredits"}, ) """Education Credits""" - categories: Optional[List[Dict[str, Any]]] = None + categories: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """categories""" - active_prices: Optional[List[Dict[str, Any]]] = field( + active_prices: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "activePrices"}, ) """Active Prices""" - related_products: Optional[List[Dict[str, Any]]] = field( + related_products: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "relatedProducts"}, ) """Related Products""" - tags: Optional[List[str]] = None + tags: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Tags.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID.""" - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Code.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - short_description: Optional[str] = field( + short_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shortDescription"}, ) """Short Description.""" - long_description: Optional[str] = field( + long_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "longDescription"}, ) """Long Description.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Url.""" - image_url: Optional[List[str]] = field( + image_url: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "imageUrl"}, ) """Image Url.""" - is_public: Optional[bool] = field( + is_public: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isPublic"}, ) """Is Public.""" - available_from: Optional[str] = field( + available_from: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "availableFrom"}, ) """Available From.""" - available_until: Optional[str] = field( + available_until: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "availableUntil"}, ) """Available Until.""" @@ -2189,118 +2474,138 @@ class RegistrantData: Definition: RegistrantData """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" - badge_name: Optional[str] = field( + badge_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "badgeName"}, ) """Badge Name""" - badge_organization: Optional[str] = field( + badge_organization: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "badgeOrganization"}, ) """Badge Organization.""" - badge_city: Optional[str] = field( + badge_city: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "badgeCity"}, ) """Badge City.""" - badge_state: Optional[str] = field( + badge_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "badgeState"}, ) """Badge State.""" - attended_date: Optional[str] = field( + attended_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "attendedDate"}, ) """Attended Date.""" - sessions: Optional[List[Dict[str, Any]]] = None - itemized_custom_fields: Optional[List[Dict[str, Any]]] = field( + sessions: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + itemized_custom_fields: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "itemizedCustomFields"}, ) """Itemized Custom Fields""" - guest_of_record_number: Optional[str] = field( + guest_of_record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "guestOfRecordNumber"}, ) """Guest Of Record Number.""" - registrant_type_code: Optional[str] = field( + registrant_type_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "registrantTypeCode"}, ) """Registrant Type Code.""" - registrant_type_name: Optional[str] = field( + registrant_type_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "registrantTypeName"}, ) """Registrant Type Name.""" - registration_number: Optional[str] = field( + registration_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "registrationNumber"}, ) """Registration Number.""" - bought_together_with: Optional[List[Dict[str, Any]]] = field( + bought_together_with: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "boughtTogetherWith"}, ) - first_name: Optional[str] = field( + first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "firstName"}, ) """First Name.""" - last_name: Optional[str] = field( + last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastName"}, ) """Last Name.""" - middle_name: Optional[str] = field( + middle_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "middleName"}, ) """Middle Name.""" - preferred_first_name: Optional[str] = field( + preferred_first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "preferredFirstName"}, ) """Preferred First Name.""" - second_last_name: Optional[str] = field( + second_last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "secondLastName"}, ) """Second Last Name.""" - prefix: Optional[str] = None + prefix: Optional[str] = dataclass_field(default=None, kw_only=True) """Prefix.""" - suffix: Optional[str] = None + suffix: Optional[str] = dataclass_field(default=None, kw_only=True) """Suffix.""" - gender: Optional[str] = None + gender: Optional[str] = dataclass_field(default=None, kw_only=True) """Gender.""" - primary_organization: Optional[Dict[str, Any]] = field( + primary_organization: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "primaryOrganization"}, ) - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID.""" - customer_type: Optional[str] = field( + customer_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customerType"}, ) """Customer Type""" - record_number: Optional[str] = field( + record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordNumber"}, ) """Record Number.""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory.""" - addresses: Optional[List[Dict[str, Any]]] = None - phones: Optional[List[Dict[str, Any]]] = None - emails: Optional[List[Dict[str, Any]]] = None + addresses: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + phones: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + emails: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -2309,80 +2614,92 @@ class CourseAttendeeData: Definition: CourseAttendeeData """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" - registered_date: Optional[str] = field( + registered_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "registeredDate"}, ) """Registered Date.""" - attended_date: Optional[str] = field( + attended_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "attendedDate"}, ) """Attended Date.""" - itemized_custom_fields: Optional[List[Dict[str, Any]]] = field( + itemized_custom_fields: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "itemizedCustomFields"}, ) """Itemized Custom Fields""" - first_name: Optional[str] = field( + first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "firstName"}, ) """First Name.""" - last_name: Optional[str] = field( + last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastName"}, ) """Last Name.""" - middle_name: Optional[str] = field( + middle_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "middleName"}, ) """Middle Name.""" - preferred_first_name: Optional[str] = field( + preferred_first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "preferredFirstName"}, ) """Preferred First Name.""" - second_last_name: Optional[str] = field( + second_last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "secondLastName"}, ) """Second Last Name.""" - prefix: Optional[str] = None + prefix: Optional[str] = dataclass_field(default=None, kw_only=True) """Prefix.""" - suffix: Optional[str] = None + suffix: Optional[str] = dataclass_field(default=None, kw_only=True) """Suffix""" - gender: Optional[str] = None + gender: Optional[str] = dataclass_field(default=None, kw_only=True) """Gender.""" - primary_organization: Optional[Dict[str, Any]] = field( + primary_organization: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "primaryOrganization"}, ) - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID.""" - customer_type: Optional[str] = field( + customer_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customerType"}, ) """Customer Type.""" - record_number: Optional[str] = field( + record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordNumber"}, ) """Record Number.""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory.""" - addresses: Optional[List[Dict[str, Any]]] = None + addresses: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Addresses.""" - emails: Optional[List[Dict[str, Any]]] = None + emails: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Emails.""" - phones: Optional[List[Dict[str, Any]]] = None + phones: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Phones.""" @@ -2392,12 +2709,13 @@ class ExamScoreData: Definition: ExamScoreData """ - individual_record_number: Optional[str] = field( + individual_record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "individualRecordNumber"}, ) """Individual Record Number.""" - score: Optional[str] = None + score: Optional[str] = dataclass_field(default=None, kw_only=True) """Score.""" @@ -2407,63 +2725,71 @@ class ContactData: Definition: ContactData """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID.""" - customer_type: Optional[str] = field( + customer_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customerType"}, ) """Customer Type.""" - record_number: Optional[str] = field( + record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordNumber"}, ) """Record Number.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - addresses: Optional[List[Dict[str, Any]]] = None - image_uri: Optional[str] = field( + addresses: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + image_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "imageUri"}, ) """Image Uri.""" - twitter: Optional[str] = None + twitter: Optional[str] = dataclass_field(default=None, kw_only=True) """Twitter.""" - linked_in: Optional[str] = field( + linked_in: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "linkedIn"}, ) """LinkedIn.""" - emails: Optional[List[Dict[str, Any]]] = None + emails: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """emails""" - phones: Optional[List[Dict[str, Any]]] = None - web_site: Optional[str] = field( + phones: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + web_site: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webSite"}, ) """Website.""" - memberships: Optional[List[Dict[str, Any]]] = None + memberships: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Memberships.""" - category: Optional[str] = None + category: Optional[str] = dataclass_field(default=None, kw_only=True) """Category.""" - categories: Optional[List[Dict[str, Any]]] = None + categories: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Categories""" - custom_fields: Optional[List[Dict[str, Any]]] = field( + custom_fields: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customFields"}, ) """Custom Fields""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory.""" - links: Optional[List[Dict[str, Any]]] = None + links: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Links""" - old_id: Optional[str] = field( + old_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldId"}, ) """Old ID.""" @@ -2475,45 +2801,53 @@ class PurchasedItemData: Definition: PurchasedItemData """ - order_number: Optional[str] = field( + order_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "orderNumber"}, ) """Order Number.""" - product_code: Optional[str] = field( + product_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "productCode"}, ) """Product Code.""" - product_name: Optional[str] = field( + product_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "productName"}, ) """Product Name.""" - product_type: Optional[str] = field( + product_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "productType"}, ) """Product Type.""" - purchase_date: Optional[str] = field( + purchase_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "purchaseDate"}, ) """Purchase Date.""" - additional_info: Optional[str] = field( + additional_info: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "additionalInfo"}, ) """Additional Info.""" - quantity: Optional[int] = None + quantity: Optional[int] = dataclass_field(default=None, kw_only=True) """Quantity.""" - itemized_custom_fields: Optional[List[Dict[str, Any]]] = field( + itemized_custom_fields: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "itemizedCustomFields"}, ) """Itemized Custom Fields""" - product_categories: Optional[List[Dict[str, Any]]] = field( + product_categories: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "productCategories"}, ) """Product Categories""" @@ -2525,9 +2859,9 @@ class CustomFieldValueData: Definition: CustomFieldValueData """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Value.""" @@ -2537,41 +2871,47 @@ class CommitteeNomineeSaveData: Definition: CommitteeNomineeSaveData """ - nominee_record_number: Optional[str] = field( + nominee_record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nomineeRecordNumber"}, ) """Nominee Record Number.""" - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Code.""" - position_code: Optional[str] = field( + position_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "positionCode"}, ) """Position Code.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status.""" - representing_organization_record_number: Optional[str] = field( + representing_organization_record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "representingOrganizationRecordNumber"}, ) """Representing Organization Record Number.""" - representing_organization_relationship_name: Optional[str] = field( + representing_organization_relationship_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "representingOrganizationRelationshipName"}, ) """Representing Organization Relationship Name.""" - nominated_by_customer_record_number: Optional[str] = field( + nominated_by_customer_record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nominatedByCustomerRecordNumber"}, ) """Nominated By Customer Record Number.""" - committee_term: Optional[int] = field( + committee_term: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "committeeTerm"}, ) """Committee Term.""" - rank: Optional[int] = None + rank: Optional[int] = dataclass_field(default=None, kw_only=True) """Rank.""" @@ -2581,86 +2921,99 @@ class RegistrantCancellationData: Definition: RegistrantCancellationData """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" - registration_number: Optional[str] = field( + registration_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "registrationNumber"}, ) """Registration Number.""" - event_cancellation_date: Optional[str] = field( + event_cancellation_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventCancellationDate"}, ) """Event Cancellation Date.""" - guest_of_record_number: Optional[str] = field( + guest_of_record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "guestOfRecordNumber"}, ) """Guest Of Record Number.""" - cancelled_sessions: Optional[List[Dict[str, Any]]] = field( + cancelled_sessions: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "cancelledSessions"}, ) """Cancelled Sessions.""" - first_name: Optional[str] = field( + first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "firstName"}, ) """First Name.""" - last_name: Optional[str] = field( + last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastName"}, ) """Last Name.""" - middle_name: Optional[str] = field( + middle_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "middleName"}, ) """Middle Name.""" - preferred_first_name: Optional[str] = field( + preferred_first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "preferredFirstName"}, ) """Preferred First Name.""" - second_last_name: Optional[str] = field( + second_last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "secondLastName"}, ) """Second Last Name.""" - prefix: Optional[str] = None + prefix: Optional[str] = dataclass_field(default=None, kw_only=True) """Prefix.""" - suffix: Optional[str] = None + suffix: Optional[str] = dataclass_field(default=None, kw_only=True) """Suffix.""" - gender: Optional[str] = None + gender: Optional[str] = dataclass_field(default=None, kw_only=True) """Gender.""" - primary_organization: Optional[Dict[str, Any]] = field( + primary_organization: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "primaryOrganization"}, ) """primaryOrganization""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID.""" - customer_type: Optional[str] = field( + customer_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customerType"}, ) """Customer Type.""" - record_number: Optional[str] = field( + record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordNumber"}, ) """Record Number.""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory.""" - addresses: Optional[List[Dict[str, Any]]] = None + addresses: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Addresses.""" - emails: Optional[List[Dict[str, Any]]] = None + emails: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Emails""" - phones: Optional[List[Dict[str, Any]]] = None + phones: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Phones.""" @@ -2670,32 +3023,39 @@ class PayableOrderData: Definition: PayableOrderData """ - number: Optional[str] = None + number: Optional[str] = dataclass_field(default=None, kw_only=True) """Number.""" - date: Optional[str] = None + date: Optional[str] = dataclass_field(default=None, kw_only=True) """Date.""" - balance: Optional[float] = None + balance: Optional[float] = dataclass_field(default=None, kw_only=True) """Balance.""" - line_items: Optional[List[Dict[str, Any]]] = field( + line_items: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lineItems"}, ) """lineItems""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID.""" - customer_id: Optional[str] = field( + customer_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customerId"}, ) """Customer Id.""" - total_amount: Optional[float] = field( + total_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "totalAmount"}, ) """Total Amount.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" @@ -2705,18 +3065,21 @@ class BaseNoteData: Definition: BaseNoteData """ - content: Optional[str] = field( + content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Content"}, ) """Content.""" - category: Optional[str] = field( + category: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Category"}, ) """Category.""" - is_internal: Optional[bool] = field( + is_internal: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isInternal"}, ) """Is Internal.""" @@ -2728,19 +3091,21 @@ class TaskSaveData: Definition: TaskSaveData """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" - category: Optional[str] = None + category: Optional[str] = dataclass_field(default=None, kw_only=True) """Category.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """Start Date.""" - due_date: Optional[str] = field( + due_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dueDate"}, ) """Due Date.""" @@ -2752,21 +3117,23 @@ class CountryData: Definition: CountryData """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - two_letter_iso_code: Optional[str] = field( + two_letter_iso_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "twoLetterIsoCode"}, ) """Two Letter Iso Code.""" - three_letter_iso_code: Optional[str] = field( + three_letter_iso_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "threeLetterIsoCode"}, ) """Three Letter Iso Code.""" - code: Optional[int] = None + code: Optional[int] = dataclass_field(default=None, kw_only=True) """Code.""" @@ -2776,14 +3143,15 @@ class StateProvinceData: Definition: StateProvinceData """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - abbreviation: Optional[str] = None + abbreviation: Optional[str] = dataclass_field(default=None, kw_only=True) """Abbreviation.""" - iso_code: Optional[str] = field( + iso_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isoCode"}, ) """Iso Code.""" @@ -2795,44 +3163,51 @@ class ExhibitData: Definition: ExhibitData """ - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Code.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """Start Date.""" - start_time: Optional[str] = field( + start_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startTime"}, ) """Start Time.""" - end_date: Optional[str] = field( + end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDate"}, ) """End Date.""" - end_time: Optional[str] = field( + end_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endTime"}, ) """End Time.""" - categories: Optional[List[Dict[str, Any]]] = None + categories: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Categories""" - short_description: Optional[str] = field( + short_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shortDescription"}, ) """Short Description.""" - long_description: Optional[str] = field( + long_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "longDescription"}, ) """Long Description.""" - featured_listing: Optional[Dict[str, Any]] = field( + featured_listing: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "featuredListing"}, ) @@ -2843,19 +3218,21 @@ class RequestSaveData: Definition: RequestSaveData """ - requested_by_customer_record_number: Optional[str] = field( + requested_by_customer_record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requestedByCustomerRecordNumber"}, ) """Requested By Customer Record Number.""" - request_type: Optional[str] = field( + request_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requestType"}, ) """Request Type.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description.""" - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Source.""" @@ -2865,35 +3242,41 @@ class RelationshipTypeData: Definition: RelationshipTypeData """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - reciprocal_relationship_name: Optional[str] = field( + reciprocal_relationship_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reciprocalRelationshipName"}, ) """Reciprocal Relationship Name.""" - relationship_type: Optional[str] = field( + relationship_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "relationshipType"}, ) """Relationship Type.""" - allow_primary: Optional[bool] = field( + allow_primary: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowPrimary"}, ) """Allow Primary.""" - can_purchase_for_organization: Optional[bool] = field( + can_purchase_for_organization: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "canPurchaseForOrganization"}, ) """Can Purchase For Organization.""" - can_manage_p_a_c: Optional[bool] = field( + can_manage_p_a_c: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "canManagePAC"}, ) """Can Manage PAC.""" - can_manage_organization: Optional[bool] = field( + can_manage_organization: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "canManageOrganization"}, ) """Can Manage Organization.""" @@ -2905,32 +3288,37 @@ class RequestData: Definition: RequestData """ - request_number: Optional[str] = field( + request_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requestNumber"}, ) """Request Number.""" - request_date: Optional[str] = field( + request_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requestDate"}, ) """Request Date.""" - requested_by_customer_record_number: Optional[str] = field( + requested_by_customer_record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requestedByCustomerRecordNumber"}, ) """Requested By Customer Record Number.""" - request_type: Optional[str] = field( + request_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requestType"}, ) """Request Type.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description.""" - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Source.""" - closed_date: Optional[str] = field( + closed_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "closedDate"}, ) """Closed Date.""" @@ -2942,16 +3330,17 @@ class NotificationData: Definition: NotificationData """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """Message.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Url.""" - date: Optional[str] = None + date: Optional[str] = dataclass_field(default=None, kw_only=True) """Date.""" - is_read: Optional[bool] = field( + is_read: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isRead"}, ) """Is Read.""" @@ -2963,10 +3352,11 @@ class SaveCategoryBasicData: Definition: SaveCategoryBasicData """ - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Code.""" - is_primary: Optional[bool] = field( + is_primary: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isPrimary"}, ) """Is Primary.""" @@ -2978,12 +3368,13 @@ class CertificationData: Definition: CertificationData """ - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Code.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - expire_date: Optional[str] = field( + expire_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "expireDate"}, ) """Expire Date.""" @@ -2995,14 +3386,15 @@ class ActivityData: Definition: ActivityData """ - category: Optional[str] = None + category: Optional[str] = dataclass_field(default=None, kw_only=True) """Category.""" - text: Optional[str] = None + text: Optional[str] = dataclass_field(default=None, kw_only=True) """Text.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Url.""" - activity_date: Optional[str] = field( + activity_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "activityDate"}, ) """Activity Date.""" @@ -3014,8 +3406,9 @@ class SessionRegistrationData: Definition: SessionRegistrationData """ - session_code: Optional[str] = field( + session_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sessionCode"}, ) """Session Code.""" @@ -3027,31 +3420,35 @@ class AwardData: Definition: AwardData """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description.""" - year: Optional[int] = None + year: Optional[int] = dataclass_field(default=None, kw_only=True) """Year.""" - customer_type: Optional[str] = field( + customer_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customerType"}, ) """Customer Type.""" - allow_public_nomination: Optional[bool] = field( + allow_public_nomination: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowPublicNomination"}, ) """Allow Public Nomination.""" - nomination_start_date: Optional[str] = field( + nomination_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nominationStartDate"}, ) """Nomination Start Date.""" - nomination_end_date: Optional[str] = field( + nomination_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nominationEndDate"}, ) """Nomination End Date.""" @@ -3063,26 +3460,29 @@ class LicenseData: Definition: LicenseData """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID.""" - license_type: Optional[str] = field( + license_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "licenseType"}, ) """License Type.""" - number: Optional[str] = None + number: Optional[str] = dataclass_field(default=None, kw_only=True) """Number.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """State.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """Start Date.""" - expiration_date: Optional[str] = field( + expiration_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "expirationDate"}, ) """Experation Date.""" @@ -3094,53 +3494,61 @@ class CommitteeNomineeData: Definition: CommitteeNomineeData """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID.""" - first_name: Optional[str] = field( + first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "firstName"}, ) """First Name.""" - last_name: Optional[str] = field( + last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastName"}, ) """Last Name.""" - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Code.""" - position: Optional[str] = None + position: Optional[str] = dataclass_field(default=None, kw_only=True) """Position.""" - position_code: Optional[str] = field( + position_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "positionCode"}, ) """Position Code.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """Start Date.""" - end_date: Optional[str] = field( + end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDate"}, ) """End Date.""" - primary_organization: Optional[Dict[str, Any]] = field( + primary_organization: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "primaryOrganization"}, ) - organization_representing: Optional[Dict[str, Any]] = field( + organization_representing: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "organizationRepresenting"}, ) - nominated_by_customer: Optional[Dict[str, Any]] = field( + nominated_by_customer: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nominatedByCustomer"}, ) - addresses: Optional[List[Dict[str, Any]]] = None - phones: Optional[List[Dict[str, Any]]] = None - emails: Optional[List[Dict[str, Any]]] = None - rank: Optional[int] = None + addresses: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + phones: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + emails: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + rank: Optional[int] = dataclass_field(default=None, kw_only=True) """Rank.""" @@ -3150,33 +3558,39 @@ class RelationshipData: Definition: RelationshipData """ - relationship_name: Optional[str] = field( + relationship_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "relationshipName"}, ) """Relationship Name.""" - related_to_customer: Optional[Dict[str, Any]] = field( + related_to_customer: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "relatedToCustomer"}, ) """Related To Customer.""" - reciprocal_relationship_name: Optional[str] = field( + reciprocal_relationship_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reciprocalRelationshipName"}, ) """Reciprocal Relationship Name.""" - is_primary: Optional[bool] = field( + is_primary: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isPrimary"}, ) """Is Primary.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """Start Date.""" - end_date: Optional[str] = field( + end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDate"}, ) """End Date.""" @@ -3188,51 +3602,60 @@ class RegistrationData: Definition: RegistrationData """ - individual_id: Optional[str] = field( + individual_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "individualId"}, ) """Individual ID.""" - event: Optional[Dict[str, Any]] = None + event: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Event.""" - sessions: Optional[List[Dict[str, Any]]] = None + sessions: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Sessions.""" - badge_name: Optional[str] = field( + badge_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "badgeName"}, ) """Badge Name.""" - badge_organization: Optional[str] = field( + badge_organization: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "badgeOrganization"}, ) """Badge Organization.""" - badge_city: Optional[str] = field( + badge_city: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "badgeCity"}, ) """Badge City.""" - badge_state: Optional[str] = field( + badge_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "badgeState"}, ) """Badge State.""" - bought_together_with: Optional[List[Dict[str, Any]]] = field( + bought_together_with: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "boughtTogetherWith"}, ) - registrant_type_code: Optional[str] = field( + registrant_type_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "registrantTypeCode"}, ) """Registrant Type Code.""" - registrant_type_name: Optional[str] = field( + registrant_type_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "registrantTypeName"}, ) """Registrant Type Name.""" - registration_number: Optional[str] = field( + registration_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "registrationNumber"}, ) """Registration Number.""" @@ -3244,23 +3667,26 @@ class CommitteeMemberData: Definition: CommitteeMemberData """ - committee: Optional[Dict[str, Any]] = None - position: Optional[str] = None + committee: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + position: Optional[str] = dataclass_field(default=None, kw_only=True) """Position.""" - position_code: Optional[str] = field( + position_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "positionCode"}, ) """Position Code.""" - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Code.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """Start Date.""" - end_date: Optional[str] = field( + end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDate"}, ) """End Date.""" @@ -3272,99 +3698,117 @@ class EventData: Definition: EventData """ - event_id: Optional[str] = field( + event_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventId"}, ) """Event ID.""" - event_code: Optional[str] = field( + event_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventCode"}, ) """Event Code.""" - event_name: Optional[str] = field( + event_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventName"}, ) """Event Name.""" - event_start_date: Optional[str] = field( + event_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventStartDate"}, ) """Event Start Date.""" - event_start_time: Optional[str] = field( + event_start_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventStartTime"}, ) """Event Start Time.""" - event_end_date: Optional[str] = field( + event_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventEndDate"}, ) """Event End Date.""" - event_end_time: Optional[str] = field( + event_end_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventEndTime"}, ) """Event End Time.""" - event_timezone: Optional[str] = field( + event_timezone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventTimezone"}, ) """Event Time Zone.""" - event_description: Optional[str] = field( + event_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventDescription"}, ) """Event Description.""" - short_description: Optional[str] = field( + short_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shortDescription"}, ) """Short Description.""" - public_event: Optional[bool] = field( + public_event: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "publicEvent"}, ) """Public Event.""" - image_url: Optional[List[str]] = field( + image_url: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "imageUrl"}, ) """Image Url.""" - external_url: Optional[str] = field( + external_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "externalUrl"}, ) """External Url.""" - external_code: Optional[str] = field( + external_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "externalCode"}, ) """External Code.""" - event_locations: Optional[List[Dict[str, Any]]] = field( + event_locations: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventLocations"}, ) """Event Locations.""" - categories: Optional[List[Dict[str, Any]]] = None + categories: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Event Locations - Categories.""" - education_credits: Optional[List[Dict[str, Any]]] = field( + education_credits: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "educationCredits"}, ) """Event Locations - Education Credits.""" - uploads_data: Optional[List[Dict[str, Any]]] = field( + uploads_data: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "uploadsData"}, ) """Event Locations - Uploads Data""" - related_products: Optional[List[Dict[str, Any]]] = field( + related_products: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "relatedProducts"}, ) """Event Locations - Related Products.""" - tags: Optional[List[str]] = None + tags: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Event Locations - Tags""" @@ -3374,26 +3818,21 @@ class PhoneSaveData: Definition: PhoneSaveData """ - country_name: Optional[str] = field( - default=None, - metadata={"wire_name": "countryName"}, - ) + country_name: str = dataclass_field(metadata={"wire_name": "countryName"}) """Country Name.""" - primary: Optional[bool] = None + primary: Optional[bool] = dataclass_field(default=None, kw_only=True) """Primary.""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show in Directory.""" - number: Optional[str] = None + number: str """Number.""" - extension: Optional[str] = None + extension: Optional[str] = dataclass_field(default=None, kw_only=True) """Extension.""" - type_name: Optional[str] = field( - default=None, - metadata={"wire_name": "typeName"}, - ) + type_name: str = dataclass_field(metadata={"wire_name": "typeName"}) """Type Name.""" @@ -3403,18 +3842,21 @@ class IndividualPayload: Definition: IndividualPayload """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebhookId"}, ) """Webhook Id.""" - properties: Optional[Dict[str, Any]] = field( + properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Properties.""" - notifications: Optional[List[Dict[str, Any]]] = field( + notifications: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Notifications"}, ) """Notifications.""" @@ -3426,18 +3868,21 @@ class CommitteeMemberPayload: Definition: CommitteeMemberPayload """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebhookId"}, ) """Webhook Id.""" - properties: Optional[Dict[str, Any]] = field( + properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Properties.""" - notifications: Optional[List[Dict[str, Any]]] = field( + notifications: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Notifications"}, ) """Notifications.""" @@ -3449,18 +3894,21 @@ class PurchaseCancelledPayload: Definition: PurchaseCancelledPayload """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebhookId"}, ) """Webhook Id.""" - properties: Optional[Dict[str, Any]] = field( + properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Properties.""" - notifications: Optional[List[Dict[str, Any]]] = field( + notifications: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Notifications"}, ) """Notifications.""" @@ -3472,18 +3920,21 @@ class CustomerRequestPayload: Definition: CustomerRequestPayload """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebhookId"}, ) """Webhook Id,.""" - properties: Optional[Dict[str, Any]] = field( + properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Properties.""" - notifications: Optional[List[Dict[str, Any]]] = field( + notifications: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Notifications"}, ) """Notifications.""" @@ -3495,18 +3946,21 @@ class EmailPayload: Definition: EmailPayload """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebhookId"}, ) """Webhook Id.""" - properties: Optional[Dict[str, Any]] = field( + properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Properties.""" - notifications: Optional[List[Dict[str, Any]]] = field( + notifications: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Notifications"}, ) """Notifications.""" @@ -3518,49 +3972,49 @@ class CommitteeMemberCreateData: Definition: CommitteeMemberCreateData """ - record_number: Optional[str] = field( - default=None, + record_number: str = dataclass_field( metadata={"wire_name": "recordNumber"}, ) """Record Number.""" - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Member Code.""" - position_code: Optional[str] = field( - default=None, + position_code: str = dataclass_field( metadata={"wire_name": "positionCode"}, ) """Position Code.""" - start_date: Optional[str] = field( - default=None, - metadata={"wire_name": "startDate"}, - ) + start_date: str = dataclass_field(metadata={"wire_name": "startDate"}) """Start Date.""" - end_date: Optional[str] = field( + end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDate"}, ) """End Date.""" - representing_organization_record_number: Optional[str] = field( + representing_organization_record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "representingOrganizationRecordNumber"}, ) """Representing Organization - Record Number.""" - representing_organization_relationship_name: Optional[str] = field( + representing_organization_relationship_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "representingOrganizationRelationshipName"}, ) """Representing Organization - Relationship Name.""" - nominated_by_customer_record_number: Optional[str] = field( + nominated_by_customer_record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nominatedByCustomerRecordNumber"}, ) """Nominated By - Record Number""" - committee_term: Optional[int] = field( + committee_term: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "committeeTerm"}, ) """Committee Term.""" - rank: Optional[int] = None + rank: Optional[int] = dataclass_field(default=None, kw_only=True) """Rank.""" @@ -3570,16 +4024,17 @@ class SubscriptionData: Definition: SubscriptionData """ - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Code.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - expire_date: Optional[str] = field( + expire_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "expireDate"}, ) """Expire Date.""" - quantity: Optional[int] = None + quantity: Optional[int] = dataclass_field(default=None, kw_only=True) """Quantity.""" @@ -3589,16 +4044,17 @@ class CommitteePositionData: Definition: CommitteePositionData """ - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Code.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - term: Optional[int] = None + term: Optional[int] = dataclass_field(default=None, kw_only=True) """Term.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description.""" - is_admin: Optional[bool] = field( + is_admin: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAdmin"}, ) """Is Admin.""" @@ -3610,49 +4066,55 @@ class CommitteeData: Definition: CommitteeData """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name.""" - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Code.""" - website: Optional[str] = None + website: Optional[str] = dataclass_field(default=None, kw_only=True) """Website.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id.""" - parent_committee_id: Optional[str] = field( + parent_committee_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentCommitteeId"}, ) """Parent Committee Id.""" - category_name: Optional[str] = field( + category_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "categoryName"}, ) """Category Name.""" - category_code: Optional[str] = field( + category_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "categoryCode"}, ) """Category Code.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """Start Date.""" - end_date: Optional[str] = field( + end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDate"}, ) """End Date.""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory.""" - term: Optional[Dict[str, Any]] = None + term: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Term.""" - tags: Optional[List[str]] = None + tags: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Tags.""" @@ -3662,49 +4124,57 @@ class CommitteeMemberUpdateData: Definition: CommitteeMemberUpdateData """ - record_number: Optional[str] = field( + record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordNumber"}, ) """Record Number.""" - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """Member Code.""" - position_code: Optional[str] = field( + position_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "positionCode"}, ) """New Position Code.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """Start Date.""" - end_date: Optional[str] = field( + end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDate"}, ) """End Date.""" - representing_organization_record_number: Optional[str] = field( + representing_organization_record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "representingOrganizationRecordNumber"}, ) """Representing Organization - Record Number.""" - representing_organization_relationship_name: Optional[str] = field( + representing_organization_relationship_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "representingOrganizationRelationshipName"}, ) """Representing Organization - Relationship Name.""" - nominated_by_customer_record_number: Optional[str] = field( + nominated_by_customer_record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nominatedByCustomerRecordNumber"}, ) """Nominated By - Record Number""" - committee_term: Optional[int] = field( + committee_term: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "committeeTerm"}, ) """Committee Term.""" - rank: Optional[int] = None + rank: Optional[int] = dataclass_field(default=None, kw_only=True) """Rank.""" @@ -3714,34 +4184,33 @@ class EducationCreditData: Definition: EducationCreditData """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """Education Credit Type.""" - description: Optional[str] = None + description: str """Description.""" - number_of_credits: Optional[float] = field( - default=None, + number_of_credits: float = dataclass_field( metadata={"wire_name": "numberOfCredits"}, ) """Number of Credits Earned.""" - date_earned: Optional[str] = field( - default=None, - metadata={"wire_name": "dateEarned"}, - ) + date_earned: str = dataclass_field(metadata={"wire_name": "dateEarned"}) """Earned Date.""" - provider_name: Optional[str] = field( + provider_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "providerName"}, ) """Provider Name.""" - state_name: Optional[str] = field( + state_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "stateName"}, ) """State or Province Name.""" - reference: Optional[str] = None + reference: Optional[str] = dataclass_field(default=None, kw_only=True) """Reference.""" - is_self_reported: Optional[bool] = field( + is_self_reported: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isSelfReported"}, ) """Is Self Reported.""" @@ -3753,24 +4222,27 @@ class NoteData: Definition: NoteData """ - is_alert: Optional[bool] = field( + is_alert: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAlert"}, ) """Is Alert.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" - follow_up_date: Optional[str] = field( + follow_up_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "followUpDate"}, ) """Follow Up Date.""" - content: Optional[str] = None + content: str """Content.""" - category: Optional[str] = None + category: Optional[str] = dataclass_field(default=None, kw_only=True) """Category.""" - is_internal: Optional[bool] = field( + is_internal: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isInternal"}, ) """Is Internal.""" @@ -3782,29 +4254,27 @@ class AwardNominationData: Definition: AwardNominationData """ - nominee_record_number: Optional[str] = field( - default=None, + nominee_record_number: str = dataclass_field( metadata={"wire_name": "nomineeRecordNumber"}, ) """Nominee Record Number.""" - nominated_by_customer_record_number: Optional[str] = field( - default=None, + nominated_by_customer_record_number: str = dataclass_field( metadata={"wire_name": "nominatedByCustomerRecordNumber"}, ) """Nominated By Record Number.""" - nomination_date: Optional[str] = field( - default=None, + nomination_date: str = dataclass_field( metadata={"wire_name": "nominationDate"}, ) """Nomination Date.""" - awarded_date: Optional[str] = field( + awarded_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "awardedDate"}, ) """Awarded Date.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """An explanation why the nominee should be considered for the award.""" @@ -3814,29 +4284,29 @@ class UpdateAwardNominationData: Definition: UpdateAwardNominationData """ - nominee_record_number: Optional[str] = field( + nominee_record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nomineeRecordNumber"}, ) """Nominee Record Number.""" - nominated_by_customer_record_number: Optional[str] = field( - default=None, + nominated_by_customer_record_number: str = dataclass_field( metadata={"wire_name": "nominatedByCustomerRecordNumber"}, ) """Nominated By Record Number.""" - nomination_date: Optional[str] = field( - default=None, + nomination_date: str = dataclass_field( metadata={"wire_name": "nominationDate"}, ) """Nomination Date.""" - awarded_date: Optional[str] = field( + awarded_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "awardedDate"}, ) """Awarded Date.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """An explanation why the nominee should be considered for the award.""" @@ -3846,68 +4316,78 @@ class AwardRecipientIndividualData: Definition: AwardRecipientIndividualData """ - awarded_date: Optional[str] = field( + awarded_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "awardedDate"}, ) """Awarded Date.""" - first_name: Optional[str] = field( + first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "firstName"}, ) """First Name.""" - last_name: Optional[str] = field( + last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastName"}, ) """Last Name.""" - middle_name: Optional[str] = field( + middle_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "middleName"}, ) """Middle Name.""" - preferred_first_name: Optional[str] = field( + preferred_first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "preferredFirstName"}, ) """Preferred First Name.""" - second_last_name: Optional[str] = field( + second_last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "secondLastName"}, ) """Second Last Name.""" - prefix: Optional[str] = None + prefix: Optional[str] = dataclass_field(default=None, kw_only=True) """Prefix.""" - suffix: Optional[str] = None + suffix: Optional[str] = dataclass_field(default=None, kw_only=True) """Suffix.""" - gender: Optional[str] = None + gender: Optional[str] = dataclass_field(default=None, kw_only=True) """Gender.""" - primary_organization: Optional[Dict[str, Any]] = field( + primary_organization: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "primaryOrganization"}, ) - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Individual Id.""" - customer_type: Optional[str] = field( + customer_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customerType"}, ) """Customer Type.""" - record_number: Optional[str] = field( + record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordNumber"}, ) """Record Number.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" - addresses: Optional[List[Dict[str, Any]]] = None + addresses: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Addresses.""" - emails: Optional[List[Dict[str, Any]]] = None + emails: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Emails.""" - phones: Optional[List[Dict[str, Any]]] = None + phones: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Phones.""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory.""" @@ -3919,52 +4399,59 @@ class AwardRecipientOrganizationData: Definition: AwardRecipientOrganizationData """ - awarded_date: Optional[str] = field( + awarded_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "awardedDate"}, ) """Awarded Date.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Organization Name.""" - acronym: Optional[str] = None + acronym: Optional[str] = dataclass_field(default=None, kw_only=True) """Acronym.""" - branch_name: Optional[str] = field( + branch_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "branchName"}, ) """Branch Name.""" - annual_sales: Optional[float] = field( + annual_sales: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "annualSales"}, ) """Annual Sales.""" - employee_range_id: Optional[str] = field( + employee_range_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "employeeRangeId"}, ) """Employee Range Id.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Organization Id.""" - customer_type: Optional[str] = field( + customer_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customerType"}, ) """Customer Type.""" - record_number: Optional[str] = field( + record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordNumber"}, ) """Record Number.""" - show_in_directory: Optional[bool] = field( + show_in_directory: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInDirectory"}, ) """Show In Directory.""" - addresses: Optional[List[Dict[str, Any]]] = None + addresses: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Addresses.""" - emails: Optional[List[Dict[str, Any]]] = None + emails: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Emails.""" - phones: Optional[List[Dict[str, Any]]] = None + phones: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Phones.""" @@ -3974,28 +4461,31 @@ class OrganizationLookupBasicData: Definition: OrganizationLookupBasicData """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Organization Name.""" - acronym: Optional[str] = None + acronym: Optional[str] = dataclass_field(default=None, kw_only=True) """Acronym.""" - branch_name: Optional[str] = field( + branch_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "branchName"}, ) """Branch Name.""" - employee_range_id: Optional[str] = field( + employee_range_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "employeeRangeId"}, ) """Employee Range Id.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Organization Id.""" - record_number: Optional[str] = field( + record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordNumber"}, ) """Record Number.""" - addresses: Optional[List[Dict[str, Any]]] = None + addresses: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Addresses.""" @@ -4005,47 +4495,54 @@ class IndividualLookupBasicData: Definition: IndividualLookupBasicData """ - first_name: Optional[str] = field( + first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "firstName"}, ) """First Name.""" - last_name: Optional[str] = field( + last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastName"}, ) """Last Name.""" - middle_name: Optional[str] = field( + middle_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "middleName"}, ) """Middle Name.""" - preferred_first_name: Optional[str] = field( + preferred_first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "preferredFirstName"}, ) """Preferred First Name.""" - second_last_name: Optional[str] = field( + second_last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "secondLastName"}, ) """Second Last Name.""" - prefix: Optional[str] = None + prefix: Optional[str] = dataclass_field(default=None, kw_only=True) """Prefix.""" - suffix: Optional[str] = None + suffix: Optional[str] = dataclass_field(default=None, kw_only=True) """Suffix.""" - gender: Optional[str] = None + gender: Optional[str] = dataclass_field(default=None, kw_only=True) """Gender.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title.""" - primary_organization: Optional[Dict[str, Any]] = field( + primary_organization: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "primaryOrganization"}, ) - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Individual Id.""" - record_number: Optional[str] = field( + record_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordNumber"}, ) """Record Number.""" @@ -4057,18 +4554,21 @@ class CustomerCustomFieldValuePayload: Definition: CustomerCustomFieldValuePayload """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebhookId"}, ) """Webhook Id.""" - properties: Optional[Dict[str, Any]] = field( + properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Properties.""" - notifications: Optional[List[Dict[str, Any]]] = field( + notifications: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Notifications"}, ) @@ -4079,18 +4579,21 @@ class CustomerMergedPayload: Definition: CustomerMergedPayload """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebhookId"}, ) """Webhook Id.""" - properties: Optional[Dict[str, Any]] = field( + properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Properties.""" - notifications: Optional[List[Dict[str, Any]]] = field( + notifications: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Notifications"}, ) @@ -4101,18 +4604,21 @@ class CustomerRelationshipUpdatedPayload: Definition: CustomerRelationshipUpdatedPayload """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebhookId"}, ) """Webhook Id.""" - properties: Optional[Dict[str, Any]] = field( + properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Properties.""" - notifications: Optional[List[Dict[str, Any]]] = field( + notifications: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Notifications"}, ) @@ -4123,18 +4629,21 @@ class CustomerPhoneUpdatedPayload: Definition: CustomerPhoneUpdatedPayload """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebhookId"}, ) """Webhook Id.""" - properties: Optional[Dict[str, Any]] = field( + properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Properties.""" - notifications: Optional[List[Dict[str, Any]]] = field( + notifications: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Notifications"}, ) @@ -4145,18 +4654,21 @@ class CustomerAddressUpdatedPayload: Definition: CustomerAddressUpdatedPayload """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebhookId"}, ) """Webhook Id.""" - properties: Optional[Dict[str, Any]] = field( + properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Properties.""" - notifications: Optional[List[Dict[str, Any]]] = field( + notifications: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Notifications"}, ) @@ -4167,18 +4679,21 @@ class EventRegistrationSubstitutedPayload: Definition: EventRegistrationSubstitutedPayload """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebhookId"}, ) """Webhook Id.""" - properties: Optional[Dict[str, Any]] = field( + properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Properties.""" - notifications: Optional[List[Dict[str, Any]]] = field( + notifications: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Notifications"}, ) @@ -4189,18 +4704,21 @@ class IndividualRequestToBeForgottenPayload: Definition: IndividualRequestToBeForgottenPayload """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebhookId"}, ) """Webhook Id.""" - properties: Optional[Dict[str, Any]] = field( + properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Properties.""" - notifications: Optional[List[Dict[str, Any]]] = field( + notifications: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Notifications"}, ) @@ -4211,18 +4729,21 @@ class ProductPurchasePayload: Definition: ProductPurchasePayload """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebhookId"}, ) """Webhook Id.""" - properties: Optional[Dict[str, Any]] = field( + properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Properties.""" - notifications: Optional[List[Dict[str, Any]]] = field( + notifications: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Notifications"}, ) @@ -4233,18 +4754,21 @@ class MembershipTypeTerminatedPayload: Definition: MembershipTypeTerminatedPayload """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebhookId"}, ) """Webhook Id.""" - properties: Optional[Dict[str, Any]] = field( + properties: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Properties.""" - notifications: Optional[List[Dict[str, Any]]] = field( + notifications: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Notifications"}, ) @@ -4257,16 +4781,16 @@ class ImpexiumClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -4277,8 +4801,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -4286,8 +4810,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -4299,7 +4823,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -4314,13 +4838,52 @@ def __init__( def connector_name(self) -> str: return "impexium" - async def get_abandoned_checkouts_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def get_abandoned_checkouts( self, page_number: int, abandoned_from: str, + *, product_code: Optional[str] = None, customer_record_number: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4330,6 +4893,24 @@ async def get_abandoned_checkouts_async( Get Abandoned Checkouts Get Abandoned Checkouts + + Swagger operation ID: `GetAbandonedCheckouts`. + + Args: + page_number: Page Number. + abandoned_from: Abandoned From. + product_code: Product Code. + customer_record_number: Customer Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4357,7 +4938,7 @@ async def get_abandoned_checkouts_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4371,6 +4952,7 @@ async def get_abandoned_checkouts_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4378,7 +4960,7 @@ async def get_abandoned_checkouts_async( return json.loads(response.text) - async def list_all_exhibitors_async( + def list_all_exhibitors( self, exhibit_code: str, page_number: int, @@ -4387,11 +4969,31 @@ async def list_all_exhibitors_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List All Exhibitors List All Exhibitors + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `List-All-Exhibitors`. + + Args: + exhibit_code: Exhibit Code. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4402,47 +5004,97 @@ async def list_all_exhibitors_async( f"/Exhibitors" f"/{quote(str(page_number), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() - async def list_of_exams_async( + return ItemPaged(get_next, extract_data) + + def list_of_exams( self, page_number: int, + *, code: Optional[str] = None, category_name: Optional[str] = None, is_public: Optional[bool] = None, changed_since: Optional[str] = None, tag: Optional[str] = None, include_prices: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List of Exams List of Exams + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `List-of-Exams`. + + Args: + page_number: The page number of the result set. + code: A specific Exam code. + category_name: A specific Exam Category name. + is_public: When set to true, only public Exams will be displayed; + If it's not specified will display all. + changed_since: When a date (yyyy-MM-ddTHH:mm:ss (UTC)) is + specified, only Exams modified after this date will be + displayed. + tag: Tag. + include_prices: When set to true, add the active price list for + every product. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4481,45 +5133,89 @@ async def list_of_exams_async( query_params.append(f"includePrices={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() - async def list_registrants_async( + return ItemPaged(get_next, extract_data) + + def list_registrants( self, event_code: str, page_number: int, + *, session_code: Optional[str] = None, include_details: Optional[bool] = None, registered_since: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List Registrants List Registrants + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `List-Registrants`. + + Args: + event_code: Event Code. + page_number: Page Number. + session_code: Session Code. + include_details: Include Details. + registered_since: Registered Since. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4548,29 +5244,50 @@ async def list_registrants_async( query_params.append(f"registeredSince={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() - async def get_course_attendees_async( + return ItemPaged(get_next, extract_data) + + def get_course_attendees( self, code: str, page_number: int, @@ -4584,6 +5301,22 @@ async def get_course_attendees_async( Get Course Attendees Get Course Attendees + + Swagger operation ID: `Get-Course-Attendees`. + + Args: + code: Course Code. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4595,7 +5328,7 @@ async def get_course_attendees_async( f"/{quote(str(page_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4609,6 +5342,7 @@ async def get_course_attendees_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4616,7 +5350,7 @@ async def get_course_attendees_async( return json.loads(response.text) - async def add_exam_scores_async( + def add_exam_scores( self, input: AddExamScoresInput, exam_code: str, @@ -4630,13 +5364,29 @@ async def add_exam_scores_async( Add Exam Scores Add Exam Scores + + Swagger operation ID: `Add-Exam-Scores`. + + Args: + input: The request body. + exam_code: Exam Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Exams/{quote(str(exam_code), safe='')}/Scores" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4650,6 +5400,7 @@ async def add_exam_scores_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4657,7 +5408,7 @@ async def add_exam_scores_async( return json.loads(response.text) - async def find_members_by_name_async( + def find_members_by_name( self, name: str, page_number: int, @@ -4671,6 +5422,22 @@ async def find_members_by_name_async( Find Members by Name Find Members by Name + + Swagger operation ID: `Find-Members-by-Name`. + + Args: + name: Individual or Organization name. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4683,7 +5450,7 @@ async def find_members_by_name_async( f"/{quote(str(page_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4697,6 +5464,7 @@ async def find_members_by_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4704,14 +5472,14 @@ async def find_members_by_name_async( return json.loads(response.text) - async def get_purchases_for_an_individual_async( + def get_purchases_for_an_individual( self, id_or_record_number: str, page_number: int, + *, product_code: Optional[str] = None, purchased_since: Optional[str] = None, product_category_code: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4721,6 +5489,25 @@ async def get_purchases_for_an_individual_async( Get Purchases for an Individual Get Purchases for an Individual + + Swagger operation ID: `Get-Purchases-for-an-Individual`. + + Args: + id_or_record_number: Individual ID or Record Number. + page_number: Page Number. + product_code: Product Code. + purchased_since: yyyy-MM-ddTHH:mm:ss. + product_category_code: Product Category Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4750,7 +5537,7 @@ async def get_purchases_for_an_individual_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4764,6 +5551,7 @@ async def get_purchases_for_an_individual_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4771,7 +5559,7 @@ async def get_purchases_for_an_individual_async( return json.loads(response.text) - async def add_or_update_a_list_of_custom_fields_per_organization_async( + def add_or_update_a_list_of_custom_fields_per_organization( self, input: AddOrUpdateAListOfCustomFieldsPerOrganizationInput, id_or_record_number: str, @@ -4785,6 +5573,23 @@ async def add_or_update_a_list_of_custom_fields_per_organization_async( Add or Update a List of Custom Fields Per Organization Add or Update a List of Custom Fields Per Organization + + Swagger operation ID: + `Add-or-Update-a-List-of-Custom-Fields-Per-Organization`. + + Args: + input: The request body. + id_or_record_number: Organization ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4795,7 +5600,7 @@ async def add_or_update_a_list_of_custom_fields_per_organization_async( f"/CustomFieldsList" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4809,6 +5614,7 @@ async def add_or_update_a_list_of_custom_fields_per_organization_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4816,9 +5622,9 @@ async def add_or_update_a_list_of_custom_fields_per_organization_async( return json.loads(response.text) - async def add_nominee_async( + def add_nominee( self, - input: CommitteeNomineeSaveData, + input: CommitteeNomineeSaveData | Mapping[str, Any], code: str, *, timeout: Optional[float] = None, @@ -4830,13 +5636,30 @@ async def add_nominee_async( Add Nominee Add Nominee + + Swagger operation ID: `Add-Nominee`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + code: Committee Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Committees/{quote(str(code), safe='')}/Nominations" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4850,9 +5673,10 @@ async def add_nominee_async( request_url, response.status, response.text, + response=response, ) - async def get_individual_custom_field_values_async( + def list_individual_custom_field_values( self, id: str, *, @@ -4860,41 +5684,81 @@ async def get_individual_custom_field_values_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Individual Custom Field Values Get Individual Custom Field Values - """ - request_url = ( - f"{self._connection_runtime_url}" - f"/api/v1/Individuals/{quote(str(id), safe='')}/CustomFields" - ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + Returns an Azure Core pager that follows the connector continuation + URL. - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + Swagger operation ID: `Get-Individual-Custom-Field-Values`. + + Args: + id: Individual ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = ( + f"{self._connection_runtime_url}" + f"/api/v1/Individuals/{quote(str(id), safe='')}/CustomFields" + ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def update_custom_field_value_async( + return ItemPaged(get_next, extract_data) + + def update_custom_field_value( self, - input: CustomFieldData, + input: CustomFieldData | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -4906,13 +5770,30 @@ async def update_custom_field_value_async( Update Individual Custom Field Values Update Individual Custom Field Values. + + Swagger operation ID: `Update-custom-field-value`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Customer ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Individuals/{quote(str(id), safe='')}/CustomFields" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4926,24 +5807,49 @@ async def update_custom_field_value_async( request_url, response.status, response.text, + response=response, ) - async def list_all_event_cancellations_by_event_async( + def list_all_event_cancellations_by_event( self, event_code: str, page_number: int, + *, include_details: Optional[bool] = None, cancelled_since: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List All Event Cancellations by Event List All Event Cancellations by Event + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `List-All-Event-Cancellations-by-Event`. + + Args: + event_code: A valid Event Code. + page_number: Page Number. + include_details: Indicates if additional information should be + returned. + cancelled_since: The initial date to search cancellations + (yyyy-MM-ddTHH:mm:ss). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4967,36 +5873,57 @@ async def list_all_event_cancellations_by_event_async( query_params.append(f"cancelledSince={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() - async def get_all_open_orders_for_an_individual_async( + return ItemPaged(get_next, extract_data) + + def get_all_open_orders_for_an_individual( self, id_or_record_number: str, page_number: int, + *, include_line_items: Optional[bool] = None, from_date: Optional[str] = None, to_date: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5006,6 +5933,25 @@ async def get_all_open_orders_for_an_individual_async( Get All Open Orders for an Individual Get All Open Orders for an Individual + + Swagger operation ID: `Get-All-Open-Orders-for-an-Individual`. + + Args: + id_or_record_number: Individual ID or Record Number. + page_number: Page Number. + include_line_items: Include Line Items. + from_date: From Date. + to_date: To Date. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5036,7 +5982,7 @@ async def get_all_open_orders_for_an_individual_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5050,6 +5996,7 @@ async def get_all_open_orders_for_an_individual_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5057,7 +6004,7 @@ async def get_all_open_orders_for_an_individual_async( return json.loads(response.text) - async def list_completed_user_tasks_by_user_id_or_email_async( + def list_completed_user_tasks_by_user_id_or_email( self, user_id_or_email: str, page_number: int, @@ -5066,11 +6013,31 @@ async def list_completed_user_tasks_by_user_id_or_email_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List Completed User Tasks by User ID or Email List Completed User Tasks by User ID or Email + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `List-Completed-User-Tasks-by-User-ID-or-Email`. + + Args: + user_id_or_email: A valid User ID or Email. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5082,29 +6049,50 @@ async def list_completed_user_tasks_by_user_id_or_email_async( f"/Completed" f"/{quote(str(page_number), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item - async def list_pending_user_tasks_by_user_id_or_email_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_pending_user_tasks_by_user_id_or_email( self, user_id_or_email: str, page_number: int, @@ -5113,11 +6101,31 @@ async def list_pending_user_tasks_by_user_id_or_email_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List Pending User Tasks by User ID or Email List Pending User Tasks by User ID or Email + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `List-Pending-User-Tasks-by-User-ID-or-Email`. + + Args: + user_id_or_email: A valid User ID or Email. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5129,31 +6137,52 @@ async def list_pending_user_tasks_by_user_id_or_email_async( f"/Pending" f"/{quote(str(page_number), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() - async def add_note_to_sales_opportunity_async( + return ItemPaged(get_next, extract_data) + + def add_note_to_sales_opportunity( self, - input: BaseNoteData, + input: BaseNoteData | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -5165,13 +6194,30 @@ async def add_note_to_sales_opportunity_async( Add Note to Sales Opportunity Add Note to Sales Opportunity + + Swagger operation ID: `Add-Note-to-Sales-Opportunity`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Sales opportunity ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Sales/Opportunities/{quote(str(id), safe='')}/Notes" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5185,11 +6231,12 @@ async def add_note_to_sales_opportunity_async( request_url, response.status, response.text, + response=response, ) - async def add_activity_to_sales_opportunity_async( + def add_activity_to_sales_opportunity( self, - input: ActivityData, + input: ActivityData | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -5201,13 +6248,30 @@ async def add_activity_to_sales_opportunity_async( Add Activity to Sales Opportunity Add Activity to Sales Opportunity + + Swagger operation ID: `Add-Activity-to-Sales-Opportunity`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Opportunity ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Sales/Opportunities/{quote(str(id), safe='')}/Activities" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5221,11 +6285,12 @@ async def add_activity_to_sales_opportunity_async( request_url, response.status, response.text, + response=response, ) - async def update_task_by_task_number_async( + def update_task_by_task_number( self, - input: TaskSaveData, + input: TaskSaveData | Mapping[str, Any], task_number: str, *, timeout: Optional[float] = None, @@ -5237,13 +6302,30 @@ async def update_task_by_task_number_async( Update Task by Task Number Update Task by Task Number + + Swagger operation ID: `Update-Task-by-Task-Number`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + task_number: A valid Task Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/tasks/{quote(str(task_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -5257,6 +6339,7 @@ async def update_task_by_task_number_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5264,7 +6347,7 @@ async def update_task_by_task_number_async( return json.loads(response.text) - async def list_all_countries_async( + def list_all_countries( self, page_number: int, *, @@ -5272,39 +6355,79 @@ async def list_all_countries_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List All Countries List All Countries + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `List-All-Countries`. + + Args: + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Countries/All/{quote(str(page_number), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_all_states_by_country_async( + def get_all_states_by_country( self, country_id: str, page_number: int, @@ -5318,6 +6441,22 @@ async def get_all_states_by_country_async( Get All States by Country Get All States by Country + + Swagger operation ID: `Get-All-States-by-Country`. + + Args: + country_id: Country ID. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5330,7 +6469,7 @@ async def get_all_states_by_country_async( f"/{quote(str(page_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5344,6 +6483,7 @@ async def get_all_states_by_country_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5351,7 +6491,7 @@ async def get_all_states_by_country_async( return json.loads(response.text) - async def list_all_exhibits_async( + def list_all_exhibits( self, page_number: int, *, @@ -5359,39 +6499,79 @@ async def list_all_exhibits_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List All Exhibits List All Exhibits + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `List-All-Exhibits`. + + Args: + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Exhibits/{quote(str(page_number), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() - async def delete_a_category_for_an_organization_async( + return ItemPaged(get_next, extract_data) + + def delete_a_category_for_an_organization( self, record_number: str, category_code: str, @@ -5405,6 +6585,22 @@ async def delete_a_category_for_an_organization_async( Delete a Category for an Organization Delete a Category for an Organization + + Swagger operation ID: `Delete-a-Category-for-an-Organization`. + + Args: + record_number: Record Number. + category_code: Category Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5416,7 +6612,7 @@ async def delete_a_category_for_an_organization_async( f"/{quote(str(category_code), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -5430,11 +6626,12 @@ async def delete_a_category_for_an_organization_async( request_url, response.status, response.text, + response=response, ) - async def add_customer_request_async( + def add_customer_request( self, - input: RequestSaveData, + input: RequestSaveData | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5445,10 +6642,26 @@ async def add_customer_request_async( Add Customer Request Add Customer Request + + Swagger operation ID: `Add-Customer-Request`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/v1/Requests" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5462,11 +6675,12 @@ async def add_customer_request_async( request_url, response.status, response.text, + response=response, ) - async def update_customer_request_async( + def update_customer_request( self, - input: RequestUpdateData, + input: RequestUpdateData | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5477,10 +6691,26 @@ async def update_customer_request_async( Update Customer Request Update Customer Request + + Swagger operation ID: `Update-Customer-Request`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/v1/Requests" - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -5494,6 +6724,7 @@ async def update_customer_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5501,7 +6732,7 @@ async def update_customer_request_async( return json.loads(response.text) - async def add_categories_for_an_organization_async( + def add_categories_for_an_organization( self, input: AddCategoriesForAnOrganizationInput, record_number: str, @@ -5515,6 +6746,22 @@ async def add_categories_for_an_organization_async( Add Categories for an Organization Add Categories for an Organization + + Swagger operation ID: `Add-Categories-for-an-Organization`. + + Args: + input: The request body. + record_number: Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5525,7 +6772,7 @@ async def add_categories_for_an_organization_async( f"/Categories" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5539,9 +6786,10 @@ async def add_categories_for_an_organization_async( request_url, response.status, response.text, + response=response, ) - async def list_of_customer_relationships_async( + def list_of_customer_relationships( self, page_number: int, *, @@ -5549,11 +6797,30 @@ async def list_of_customer_relationships_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List of Customer Relationships List of Customer Relationships + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `List-of-Customer-Relationships`. + + Args: + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5563,29 +6830,50 @@ async def list_of_customer_relationships_async( f"/RelationshipTypes" f"/{quote(str(page_number), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def list_all_open_customer_request_async( + def list_all_open_customer_request( self, page_number: int, *, @@ -5593,39 +6881,79 @@ async def list_all_open_customer_request_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List All Open Customer Request List All Open Customer Request + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `List-All-Open-Customer-Request`. + + Args: + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Requests/Open/{quote(str(page_number), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item - async def get_organization_inactive_memberships_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_organization_inactive_memberships( self, id: str, *, @@ -5638,6 +6966,21 @@ async def get_organization_inactive_memberships_async( Get Organization Inactive Memberships Get Organization Inactive Memberships + + Swagger operation ID: `Get-Organization-Inactive-Memberships`. + + Args: + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5649,7 +6992,7 @@ async def get_organization_inactive_memberships_async( f"/Inactive" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5663,6 +7006,7 @@ async def get_organization_inactive_memberships_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5670,7 +7014,7 @@ async def get_organization_inactive_memberships_async( return json.loads(response.text) - async def delete_record_from_custom_data_table_async( + def delete_record_from_custom_data_table( self, table_name: str, id: str, @@ -5684,6 +7028,22 @@ async def delete_record_from_custom_data_table_async( Delete Record From Custom Data Table Delete Record From Custom Data Table + + Swagger operation ID: `Delete-Record-From-Custom-Data-Table`. + + Args: + table_name: Custom table name. + id: ID of the record to be deleted. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5694,7 +7054,7 @@ async def delete_record_from_custom_data_table_async( f"/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -5708,11 +7068,12 @@ async def delete_record_from_custom_data_table_async( request_url, response.status, response.text, + response=response, ) - async def update_user_task_progress_or_mark_as_completed_async( + def update_user_task_progress_or_mark_as_completed( self, - input: UserTaskData, + input: UserTaskData | Mapping[str, Any], user_id_or_email: str, *, timeout: Optional[float] = None, @@ -5724,13 +7085,30 @@ async def update_user_task_progress_or_mark_as_completed_async( Update User Task Progress or Mark as Completed Update User Task Progress or Mark as Completed + + Swagger operation ID: `Update-User-Task-Progress-or-Mark-as-Completed`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + user_id_or_email: A valid User Id or Email. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/tasks/Users/{quote(str(user_id_or_email), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -5744,6 +7122,7 @@ async def update_user_task_progress_or_mark_as_completed_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5751,12 +7130,12 @@ async def update_user_task_progress_or_mark_as_completed_async( return json.loads(response.text) - async def find_members_or_individuals_by_first_name_async( + def find_members_or_individuals_by_first_name( self, first_name: str, page_number: int, - include_email: Optional[bool] = None, *, + include_email: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5766,6 +7145,23 @@ async def find_members_or_individuals_by_first_name_async( Find Members (Individuals) by First Name Find Members (Individuals) by First Name + + Swagger operation ID: `Find-Members-or-Individuals-by-First-Name`. + + Args: + first_name: First Name. + page_number: Page Number. + include_email: Include Email Data. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5786,7 +7182,7 @@ async def find_members_or_individuals_by_first_name_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5800,6 +7196,7 @@ async def find_members_or_individuals_by_first_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5807,12 +7204,12 @@ async def find_members_or_individuals_by_first_name_async( return json.loads(response.text) - async def find_members_or_individuals_by_last_name_async( + def find_members_or_individuals_by_last_name( self, last_name: str, page_number: int, - include_email: Optional[bool] = None, *, + include_email: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5822,6 +7219,23 @@ async def find_members_or_individuals_by_last_name_async( Find Members (Individuals) by Last Name Find Members (Individuals) by Last Name + + Swagger operation ID: `Find-Members-or-Individuals-by-Last-Name`. + + Args: + last_name: Last Name. + page_number: Page Number. + include_email: Include Email Data. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5842,7 +7256,7 @@ async def find_members_or_individuals_by_last_name_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5856,6 +7270,7 @@ async def find_members_or_individuals_by_last_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5863,9 +7278,9 @@ async def find_members_or_individuals_by_last_name_async( return json.loads(response.text) - async def assign_task_to_a_user_async( + def assign_task_to_a_user( self, - input: UserTaskData, + input: UserTaskData | Mapping[str, Any], user_id_or_email: str, *, timeout: Optional[float] = None, @@ -5877,13 +7292,30 @@ async def assign_task_to_a_user_async( Create a new task or Assign Task to a User Create a new task or Assign Task to a User + + Swagger operation ID: `Assign-Task-to-a-User`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + user_id_or_email: A valid User Id or Email. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/tasks/Users/{quote(str(user_id_or_email), safe='')}/Task" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5897,9 +7329,10 @@ async def assign_task_to_a_user_async( request_url, response.status, response.text, + response=response, ) - async def delete_a_category_for_an_individual_async( + def delete_a_category_for_an_individual( self, record_number: str, category_code: str, @@ -5913,6 +7346,22 @@ async def delete_a_category_for_an_individual_async( Delete a Category for an Individual Delete a Category for an Individual + + Swagger operation ID: `Delete-a-Category-for-an-Individual`. + + Args: + record_number: Record Number. + category_code: Category Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5924,7 +7373,7 @@ async def delete_a_category_for_an_individual_async( f"/{quote(str(category_code), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -5938,11 +7387,12 @@ async def delete_a_category_for_an_individual_async( request_url, response.status, response.text, + response=response, ) - async def add_notification_to_individual_async( + def add_notification_to_individual( self, - input: NotificationData, + input: NotificationData | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -5954,13 +7404,30 @@ async def add_notification_to_individual_async( Add Notification to Individual Add Notification to Individual + + Swagger operation ID: `Add-Notification-to-Individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Individual ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Individuals/{quote(str(id), safe='')}/Notifications" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5974,9 +7441,10 @@ async def add_notification_to_individual_async( request_url, response.status, response.text, + response=response, ) - async def add_categories_for_an_individual_async( + def add_categories_for_an_individual( self, input: AddCategoriesForAnIndividualInput, record_number: str, @@ -5990,6 +7458,22 @@ async def add_categories_for_an_individual_async( Add Categories for an Individual Add Categories for an Individual + + Swagger operation ID: `Add-Categories-for-an-Individual`. + + Args: + input: The request body. + record_number: Individual Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6000,7 +7484,7 @@ async def add_categories_for_an_individual_async( f"/Categories" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6014,11 +7498,12 @@ async def add_categories_for_an_individual_async( request_url, response.status, response.text, + response=response, ) - async def add_a_new_task_async( + def add_a_new_task( self, - input: TaskSaveData, + input: TaskSaveData | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6029,10 +7514,26 @@ async def add_a_new_task_async( Add a New Task Add a New Task + + Swagger operation ID: `Add-a-New-Task`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/v1/tasks" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6046,6 +7547,7 @@ async def add_a_new_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6053,9 +7555,10 @@ async def add_a_new_task_async( return json.loads(response.text) - async def list_of_all_organization_members_async( + def list_of_all_organization_members( self, page_number: int, + *, zip_code: Optional[str] = None, radius: Optional[float] = None, state_abbreviation: Optional[str] = None, @@ -6075,16 +7578,53 @@ async def list_of_all_organization_members_async( include_custom_fields: Optional[bool] = None, expiring_from: Optional[str] = None, expiring_to: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List of All Organization Members List of All Organization Members + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `List-of-All-Organization-Members`. + + Args: + page_number: Page Number. + zip_code: Zip Code. + radius: Radius in Miles. + state_abbreviation: State Abbreviation. + congressional_district: Congressional District. + membership_type_code: A valid code for a Membership Type. + membership_type_category: A valid Membership Type Category name. + city: City. + name: Name. + tag: Tag. + latitude: Latitude. + longitude: Longitude. + domain: Domain. + include_membership: Include Membership Data. + include_address: Include Address Data. + include_phone: Include Phone Data. + include_email: Include Email Data. + include_custom_fields: Include Custom Field Data. + expiring_from: Expire Date - From. + expiring_to: Expire Date - To. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6193,31 +7733,53 @@ async def list_of_all_organization_members_async( query_params.append(f"expiringTo={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item - async def list_of_all_individual_members_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_of_all_individual_members( self, page_number: int, + *, zip_code: Optional[str] = None, radius: Optional[float] = None, membership_type_code: Optional[str] = None, @@ -6233,16 +7795,49 @@ async def list_of_all_individual_members_async( include_membership_renewal_url: Optional[bool] = None, expiring_from: Optional[str] = None, expiring_to: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List of All Individual Members List of All Individual Members + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `List-of-All-Individual-Members`. + + Args: + page_number: Page Number. + zip_code: Zip Code. + radius: Radius in Miles. + membership_type_code: A valid code for a Membership Type. + membership_type_category: A valid Membership Type Category name. + tag: Tag. + include_membership: Include Membership Data. + include_address: Include Address Data. + include_phone: Include Phone Data. + include_email: Include Email Data. + include_link: Include Link Data. + include_custom_fields: Include Custom Field Data. + include_categories: Include Categories Data. + include_membership_renewal_url: Include Membership Renewal URLs. + expiring_from: Expire Date - From. + expiring_to: Expire Date - To. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6331,29 +7926,50 @@ async def list_of_all_individual_members_async( query_params.append(f"expiringTo={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_list_of_active_certifications_for_an_organization_async( + def get_list_of_active_certifications_for_an_organization( self, id_or_record_number: str, page_number: int, @@ -6367,6 +7983,23 @@ async def get_list_of_active_certifications_for_an_organization_async( Get List of Active Certifications for an Organization Get List of Active Certifications for an Organization + + Swagger operation ID: + `Get-List-of-Active-Certifications-for-an-Organization`. + + Args: + id_or_record_number: Organization ID or Record Number. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6378,7 +8011,7 @@ async def get_list_of_active_certifications_for_an_organization_async( f"/{quote(str(page_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6392,6 +8025,7 @@ async def get_list_of_active_certifications_for_an_organization_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6399,7 +8033,7 @@ async def get_list_of_active_certifications_for_an_organization_async( return json.loads(response.text) - async def get_list_of_active_certifications_for_an_individual_async( + def get_list_of_active_certifications_for_an_individual( self, id_or_record_number: str, page_number: int, @@ -6413,6 +8047,23 @@ async def get_list_of_active_certifications_for_an_individual_async( Get List of Active Certifications for an Individual Get List of Active Certifications for an Individual + + Swagger operation ID: + `Get-List-of-Active-Certifications-for-an-Individual`. + + Args: + id_or_record_number: Individual ID or Record Number. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6424,7 +8075,7 @@ async def get_list_of_active_certifications_for_an_individual_async( f"/{quote(str(page_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6438,6 +8089,7 @@ async def get_list_of_active_certifications_for_an_individual_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6445,7 +8097,7 @@ async def get_list_of_active_certifications_for_an_individual_async( return json.loads(response.text) - async def get_individual_inactive_memberships_async( + def get_individual_inactive_memberships( self, id: str, *, @@ -6458,6 +8110,21 @@ async def get_individual_inactive_memberships_async( Get Individual Inactive Memberships Get Individual Inactive Memberships + + Swagger operation ID: `Get-Individual-Inactive-Memberships`. + + Args: + id: Individual ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6469,7 +8136,7 @@ async def get_individual_inactive_memberships_async( f"/Inactive" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6483,6 +8150,7 @@ async def get_individual_inactive_memberships_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6490,9 +8158,9 @@ async def get_individual_inactive_memberships_async( return json.loads(response.text) - async def add_activity_to_organization_async( + def add_activity_to_organization( self, - input: ActivityData, + input: ActivityData | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -6504,13 +8172,30 @@ async def add_activity_to_organization_async( Add Activity to Organization Add Activity to Organization + + Swagger operation ID: `Add-Activity-to-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Organizations/{quote(str(id), safe='')}/Activities" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6524,15 +8209,16 @@ async def add_activity_to_organization_async( request_url, response.status, response.text, + response=response, ) - async def register_an_individual_for_a_free_session_async( + def register_an_individual_for_a_free_session( self, input: RegisterAnIndividualForAFreeSessionInput, event_code: str, customer_id_or_record_number: str, - registration_number: Optional[str] = None, *, + registration_number: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -6542,6 +8228,25 @@ async def register_an_individual_for_a_free_session_async( Register an Individual for a Free Session Register an Individual for a Free Session + + Swagger operation ID: `Register-an-Individual-for-a-Free-Session`. + + Args: + input: The request body. + event_code: A Valid Event Code. + customer_id_or_record_number: A Valid Individual ID or Record + Number. + registration_number: A Valid Registration Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6562,7 +8267,7 @@ async def register_an_individual_for_a_free_session_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6576,9 +8281,10 @@ async def register_an_individual_for_a_free_session_async( request_url, response.status, response.text, + response=response, ) - async def get_a_list_of_licenses_async( + def get_a_list_of_licenses( self, id: str, page_number: int, @@ -6592,6 +8298,22 @@ async def get_a_list_of_licenses_async( Get a List of Licenses Get a List of Licenses + + Swagger operation ID: `Get-a-List-of-Licenses`. + + Args: + id: Individual ID. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6603,7 +8325,7 @@ async def get_a_list_of_licenses_async( f"/{quote(str(page_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6617,6 +8339,7 @@ async def get_a_list_of_licenses_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6624,20 +8347,40 @@ async def get_a_list_of_licenses_async( return json.loads(response.text) - async def list_all_awards_async( + def list_all_awards( self, page_number: int, - year: Optional[int] = None, *, + year: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List All Awards List All Awards + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `List-All-Awards`. + + Args: + page_number: Page Number. + year: Year. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6651,34 +8394,55 @@ async def list_all_awards_async( query_params.append(f"Year={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item - async def find_members_or_individuals_by_name_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def find_members_or_individuals_by_name( self, name: str, page_number: int, - include_email: Optional[bool] = None, *, + include_email: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -6688,6 +8452,23 @@ async def find_members_or_individuals_by_name_async( Find Members (Individuals) by Name Find Members (Individuals) by Name + + Swagger operation ID: `Find-Members-or-Individuals-by-Name`. + + Args: + name: Individual Name. + page_number: Page Number. + include_email: Include Email Data. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6708,7 +8489,7 @@ async def find_members_or_individuals_by_name_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6722,6 +8503,7 @@ async def find_members_or_individuals_by_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6729,7 +8511,7 @@ async def find_members_or_individuals_by_name_async( return json.loads(response.text) - async def get_a_list_of_all_services_of_an_organization_async( + def get_a_list_of_all_services_of_an_organization( self, id: str, *, @@ -6742,13 +8524,28 @@ async def get_a_list_of_all_services_of_an_organization_async( Get a List of All Services of an Organization Get a List of All Services of an Organization + + Swagger operation ID: `Get-a-List-of-All-Services-of-an-Organization`. + + Args: + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Organizations/{quote(str(id), safe='')}/Services" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6762,6 +8559,7 @@ async def get_a_list_of_all_services_of_an_organization_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6769,9 +8567,9 @@ async def get_a_list_of_all_services_of_an_organization_async( return json.loads(response.text) - async def add_a_service_to_an_organization_async( + def add_a_service_to_an_organization( self, - input: ServiceData, + input: ServiceData | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -6783,13 +8581,30 @@ async def add_a_service_to_an_organization_async( Add a Service to an Organization Add a Service to an Organization + + Swagger operation ID: `Add-a-Service-to-an-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Organizations/{quote(str(id), safe='')}/Services" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6803,6 +8618,7 @@ async def add_a_service_to_an_organization_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6810,9 +8626,9 @@ async def add_a_service_to_an_organization_async( return json.loads(response.text) - async def update_phone_for_an_individual_async( + def update_phone_for_an_individual( self, - input: PhoneSaveData, + input: PhoneSaveData | Mapping[str, Any], id_or_record_number: str, id: str, *, @@ -6825,6 +8641,24 @@ async def update_phone_for_an_individual_async( Update Phone for an Individual Update Phone for an Individual + + Swagger operation ID: `Update-Phone-for-an-Individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Individual ID or Record Number. + id: Phone ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6836,7 +8670,7 @@ async def update_phone_for_an_individual_async( f"/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -6850,6 +8684,7 @@ async def update_phone_for_an_individual_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6857,9 +8692,9 @@ async def update_phone_for_an_individual_async( return json.loads(response.text) - async def update_phone_for_an_organization_async( + def update_phone_for_an_organization( self, - input: PhoneSaveData, + input: PhoneSaveData | Mapping[str, Any], id_or_record_number: str, id: str, *, @@ -6872,6 +8707,24 @@ async def update_phone_for_an_organization_async( Update Phone for an Organization Update Phone for an Organization + + Swagger operation ID: `Update-Phone-for-an-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Organization ID or Record Number. + id: Phone ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6883,7 +8736,7 @@ async def update_phone_for_an_organization_async( f"/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -6897,6 +8750,7 @@ async def update_phone_for_an_organization_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6904,9 +8758,9 @@ async def update_phone_for_an_organization_async( return json.loads(response.text) - async def delete_an_individual_web_link_async( + def delete_an_individual_web_link( self, - input: DeleteAnIndividualWebLinkInput, + input: DeleteAnIndividualWebLinkInput | Mapping[str, Any], id_or_record_number: str, *, timeout: Optional[float] = None, @@ -6918,6 +8772,23 @@ async def delete_an_individual_web_link_async( Delete an Individual Web Link Delete an Individual Web Link + + Swagger operation ID: `Delete-an-Individual-Web-Link`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: A valid Individual ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6928,7 +8799,7 @@ async def delete_an_individual_web_link_async( f"/Links" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=input, timeout=timeout, headers=headers, @@ -6942,11 +8813,12 @@ async def delete_an_individual_web_link_async( request_url, response.status, response.text, + response=response, ) - async def add_web_link_for_individual_async( + def add_web_link_for_individual( self, - input: AddWebLinkForIndividualInput, + input: AddWebLinkForIndividualInput | Mapping[str, Any], id_or_record_number: str, *, timeout: Optional[float] = None, @@ -6958,6 +8830,23 @@ async def add_web_link_for_individual_async( Add Web Link for Individual Add Web Link for Individual + + Swagger operation ID: `Add-Web-Link-for-Individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: A valid Individual Id or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6968,7 +8857,7 @@ async def add_web_link_for_individual_async( f"/Links" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6982,11 +8871,12 @@ async def add_web_link_for_individual_async( request_url, response.status, response.text, + response=response, ) - async def add_phone_to_organization_async( + def add_phone_to_organization( self, - input: PhoneSaveData, + input: PhoneSaveData | Mapping[str, Any], id_or_record_number: str, *, timeout: Optional[float] = None, @@ -6998,6 +8888,23 @@ async def add_phone_to_organization_async( Add Phone to Organization Add Phone to Organization + + Swagger operation ID: `Add-Phone-to-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Organization ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7008,7 +8915,7 @@ async def add_phone_to_organization_async( f"/Phones" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7022,6 +8929,7 @@ async def add_phone_to_organization_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7029,12 +8937,12 @@ async def add_phone_to_organization_async( return json.loads(response.text) - async def get_nominees_by_committee_async( + def get_nominees_by_committee( self, code: str, page_number: int, - term: Optional[str] = None, *, + term: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -7044,6 +8952,23 @@ async def get_nominees_by_committee_async( Get Nominees by Committee Get Nominees by Committee + + Swagger operation ID: `Get-Nominees-by-Committee`. + + Args: + code: Committee Code. + page_number: Page Number. + term: Term. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7063,7 +8988,7 @@ async def get_nominees_by_committee_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7077,6 +9002,7 @@ async def get_nominees_by_committee_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7084,7 +9010,7 @@ async def get_nominees_by_committee_async( return json.loads(response.text) - async def get_organizations_active_subscriptions_async( + def get_organizations_active_subscriptions( self, id: str, page_number: int, @@ -7098,6 +9024,22 @@ async def get_organizations_active_subscriptions_async( Get Organization's Active Subscriptions Get Organization's Active Subscriptions + + Swagger operation ID: `Get-Organizations-Active-Subscriptions`. + + Args: + id: Organization ID. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7109,7 +9051,7 @@ async def get_organizations_active_subscriptions_async( f"/{quote(str(page_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7123,6 +9065,7 @@ async def get_organizations_active_subscriptions_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7130,9 +9073,9 @@ async def get_organizations_active_subscriptions_async( return json.loads(response.text) - async def delete_an_organization_web_link_async( + def delete_an_organization_web_link( self, - input: DeleteAnOrganizationWebLinkInput, + input: DeleteAnOrganizationWebLinkInput | Mapping[str, Any], id_or_record_number: str, *, timeout: Optional[float] = None, @@ -7144,6 +9087,23 @@ async def delete_an_organization_web_link_async( Delete an Organization Web Link Delete an Organization Web Link + + Swagger operation ID: `Delete-an-Organization-Web-Link`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Organization ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7154,7 +9114,7 @@ async def delete_an_organization_web_link_async( f"/Links" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=input, timeout=timeout, headers=headers, @@ -7168,11 +9128,12 @@ async def delete_an_organization_web_link_async( request_url, response.status, response.text, + response=response, ) - async def add_web_link_for_organization_async( + def add_web_link_for_organization( self, - input: AddWebLinkForOrganizationInput, + input: AddWebLinkForOrganizationInput | Mapping[str, Any], id_or_record_number: str, *, timeout: Optional[float] = None, @@ -7184,6 +9145,23 @@ async def add_web_link_for_organization_async( Add Web Link for Organization Add Web Link for Organization + + Swagger operation ID: `Add-Web-Link-for-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Organization ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7194,7 +9172,7 @@ async def add_web_link_for_organization_async( f"/Links" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7208,11 +9186,12 @@ async def add_web_link_for_organization_async( request_url, response.status, response.text, + response=response, ) - async def add_email_to_organization_async( + def add_email_to_organization( self, - input: EmailData, + input: EmailData | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -7224,13 +9203,30 @@ async def add_email_to_organization_async( Add Email to Organization Add Email to Organization + + Swagger operation ID: `Add-Email-to-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Organizations/{quote(str(id), safe='')}/Emails" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7244,15 +9240,16 @@ async def add_email_to_organization_async( request_url, response.status, response.text, + response=response, ) - async def get_organizations_relationships_async( + def get_organizations_relationships( self, id: str, page_number: int, + *, relationship_name: Optional[str] = None, includes_details: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -7262,6 +9259,24 @@ async def get_organizations_relationships_async( Get Organization's Relationships Get Organization's Relationships + + Swagger operation ID: `Get-Organizations-Relationships`. + + Args: + id: Organization ID. + page_number: Page Number. + relationship_name: Name of the Relationship. + includes_details: Includes Details. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7286,7 +9301,7 @@ async def get_organizations_relationships_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7300,6 +9315,7 @@ async def get_organizations_relationships_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7307,9 +9323,9 @@ async def get_organizations_relationships_async( return json.loads(response.text) - async def add_or_update_address_to_organization_async( + def add_or_update_address_to_organization( self, - input: AddressSaveData, + input: AddressSaveData | Mapping[str, Any], id_or_record_number: str, *, timeout: Optional[float] = None, @@ -7321,6 +9337,23 @@ async def add_or_update_address_to_organization_async( Add or Update Address to Organization Add or Update Address to Organization + + Swagger operation ID: `Add-or-Update-Address-to-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Organization ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7331,7 +9364,7 @@ async def add_or_update_address_to_organization_async( f"/Addresses" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7345,6 +9378,7 @@ async def add_or_update_address_to_organization_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7352,7 +9386,7 @@ async def add_or_update_address_to_organization_async( return json.loads(response.text) - async def add_or_update_a_list_of_custom_fields_per_individual_async( + def add_or_update_a_list_of_custom_fields_per_individual( self, input: AddOrUpdateAListOfCustomFieldsPerIndividualInput, id_or_record_number: str, @@ -7366,6 +9400,23 @@ async def add_or_update_a_list_of_custom_fields_per_individual_async( Add or Update a List of Custom Fields Per Individual Add or Update a List of Custom Fields Per Individual + + Swagger operation ID: + `Add-or-Update-a-List-of-Custom-Fields-Per-Individual`. + + Args: + input: The request body. + id_or_record_number: Individual ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7376,7 +9427,7 @@ async def add_or_update_a_list_of_custom_fields_per_individual_async( f"/CustomFieldsList" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7390,6 +9441,7 @@ async def add_or_update_a_list_of_custom_fields_per_individual_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7397,7 +9449,7 @@ async def add_or_update_a_list_of_custom_fields_per_individual_async( return json.loads(response.text) - async def get_upcoming_events_async( + def get_upcoming_events( self, page_number: int, *, @@ -7410,13 +9462,28 @@ async def get_upcoming_events_async( Get Upcoming Events Get Upcoming Events + + Swagger operation ID: `Get-Upcoming-Events`. + + Args: + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Events/Upcoming/{quote(str(page_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7430,6 +9497,7 @@ async def get_upcoming_events_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7437,9 +9505,9 @@ async def get_upcoming_events_async( return json.loads(response.text) - async def add_phone_to_individual_async( + def add_phone_to_individual( self, - input: PhoneSaveData, + input: PhoneSaveData | Mapping[str, Any], id_or_record_number: str, *, timeout: Optional[float] = None, @@ -7451,6 +9519,23 @@ async def add_phone_to_individual_async( Add Phone to Individual Add Phone to Individual + + Swagger operation ID: `Add-Phone-to-Individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Individual ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7461,7 +9546,7 @@ async def add_phone_to_individual_async( f"/Phones" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7475,6 +9560,7 @@ async def add_phone_to_individual_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7482,12 +9568,12 @@ async def add_phone_to_individual_async( return json.loads(response.text) - async def get_committee_information_for_an_individual_async( + def get_committee_information_for_an_individual( self, id: str, page_number: int, - include_inactive: Optional[bool] = None, *, + include_inactive: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -7497,6 +9583,23 @@ async def get_committee_information_for_an_individual_async( Get Committee Information for an Individual Get Committee Information for an Individual + + Swagger operation ID: `Get-Committee-Information-for-an-Individual`. + + Args: + id: Individual ID. + page_number: Page Number. + include_inactive: Include Inactive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7516,7 +9619,7 @@ async def get_committee_information_for_an_individual_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7530,6 +9633,7 @@ async def get_committee_information_for_an_individual_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7537,7 +9641,7 @@ async def get_committee_information_for_an_individual_async( return json.loads(response.text) - async def get_organization_custom_field_values_async( + def list_organization_custom_field_values( self, id: str, *, @@ -7545,39 +9649,79 @@ async def get_organization_custom_field_values_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Organization Custom Field Values Get Organization Custom Field Values + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Get-Organization-Custom-Field-Values`. + + Args: + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Organizations/{quote(str(id), safe='')}/CustomFields" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - if not response.text: - return None + return None, items() - return json.loads(response.text) + return ItemPaged(get_next, extract_data) - async def get_organization_active_memberships_async( + def list_organization_active_memberships( self, id: str, *, @@ -7585,11 +9729,30 @@ async def get_organization_active_memberships_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Organization Active Memberships Get Organization Active Memberships + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Get-Organization-Active-Memberships`. + + Args: + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7600,35 +9763,56 @@ async def get_organization_active_memberships_async( f"/Memberships" f"/Active" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def get_all_events_async( + return ItemPaged(get_next, extract_data) + + def get_all_events( self, page_number: int, + *, code: Optional[str] = None, name: Optional[str] = None, tag: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -7638,6 +9822,24 @@ async def get_all_events_async( Get All Events Get All Events + + Swagger operation ID: `Get-All-Events`. + + Args: + page_number: Page Number. + code: Code. + name: Name. + tag: Tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7662,7 +9864,7 @@ async def get_all_events_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7676,6 +9878,7 @@ async def get_all_events_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7683,7 +9886,7 @@ async def get_all_events_async( return json.loads(response.text) - async def get_individual_active_memberships_async( + def list_individual_active_memberships( self, id: str, *, @@ -7691,44 +9894,84 @@ async def get_individual_active_memberships_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Individual Active Memberships Get Individual Active Memberships + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Get-Individual-Active-Memberships`. + + Args: + id: Individual ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Individuals/{quote(str(id), safe='')}/Memberships/Active" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def get_all_event_registrations_information_for_an_individual_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_all_event_registrations_information_for_an_individual( self, id_or_record_number: str, page_number: int, - event_code: Optional[str] = None, *, + event_code: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -7738,6 +9981,24 @@ async def get_all_event_registrations_information_for_an_individual_async( Get All Event Registrations Information for an Individual Get All Event Registrations Information for an Individual + + Swagger operation ID: + `Get-All-Event-Registrations-Information-for-an-Individual`. + + Args: + id_or_record_number: Individual ID or Record Number. + page_number: Page Number. + event_code: Event Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7757,7 +10018,7 @@ async def get_all_event_registrations_information_for_an_individual_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7771,6 +10032,7 @@ async def get_all_event_registrations_information_for_an_individual_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7778,13 +10040,13 @@ async def get_all_event_registrations_information_for_an_individual_async( return json.loads(response.text) - async def get_individuals_relationships_async( + def get_individuals_relationships( self, id: str, page_number: int, + *, relationship_name: Optional[str] = None, include_details: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -7794,6 +10056,24 @@ async def get_individuals_relationships_async( Get Individual's Relationships Get Individual's Relationships + + Swagger operation ID: `Get-Individuals-Relationships`. + + Args: + id: Individual ID. + page_number: Page Number. + relationship_name: Name of the Relationship. + include_details: Include Details. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7818,7 +10098,7 @@ async def get_individuals_relationships_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7832,6 +10112,7 @@ async def get_individuals_relationships_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7839,9 +10120,9 @@ async def get_individuals_relationships_async( return json.loads(response.text) - async def update_an_individual_email_async( + def update_an_individual_email( self, - input: UpdateAnIndividualEmailInput, + input: UpdateAnIndividualEmailInput | Mapping[str, Any], id_or_record_number: str, current_email_address: str, *, @@ -7854,6 +10135,24 @@ async def update_an_individual_email_async( Update an Individual Email Update an Individual Email + + Swagger operation ID: `Update-an-Individual-Email`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Individual ID or Record Number. + current_email_address: Email Address to Update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7865,7 +10164,7 @@ async def update_an_individual_email_async( f"/{quote(str(current_email_address), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -7879,11 +10178,12 @@ async def update_an_individual_email_async( request_url, response.status, response.text, + response=response, ) - async def save_relationship_for_organization_async( + def save_relationship_for_organization( self, - input: SaveRelationshipForOrganizationInput, + input: SaveRelationshipForOrganizationInput | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -7895,13 +10195,30 @@ async def save_relationship_for_organization_async( Save Relationship for Organization Save Relationship for Organization + + Swagger operation ID: `Save-Relationship-for-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Organization ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Organizations/{quote(str(id), safe='')}/Relationships" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7915,13 +10232,14 @@ async def save_relationship_for_organization_async( request_url, response.status, response.text, + response=response, ) - async def add_individual_async( + def add_individual( self, - input: AddIndividualInput, - create_user: Optional[bool] = None, + input: AddIndividualInput | Mapping[str, Any], *, + create_user: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -7931,6 +10249,24 @@ async def add_individual_async( Add Individual Adds an Individual. + + Swagger operation ID: `Add-Individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + create_user: Choose True if a user account should be created when + the individual is created. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/v1/Individuals" query_params = [] @@ -7942,7 +10278,7 @@ async def add_individual_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7956,6 +10292,7 @@ async def add_individual_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7963,9 +10300,9 @@ async def add_individual_async( return json.loads(response.text) - async def add_email_to_individual_async( + def add_email_to_individual( self, - input: AddEmailToIndividualInput, + input: AddEmailToIndividualInput | Mapping[str, Any], id_or_record_number: str, *, timeout: Optional[float] = None, @@ -7977,6 +10314,23 @@ async def add_email_to_individual_async( Add Email to Individual Add Email to Individual + + Swagger operation ID: `Add-Email-to-Individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Individual ID Or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7987,7 +10341,7 @@ async def add_email_to_individual_async( f"/Emails" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -8001,6 +10355,7 @@ async def add_email_to_individual_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8008,9 +10363,9 @@ async def add_email_to_individual_async( return json.loads(response.text) - async def add_or_update_address_to_individual_async( + def add_or_update_address_to_individual( self, - input: AddressSaveData, + input: AddressSaveData | Mapping[str, Any], id_or_record_number: str, *, timeout: Optional[float] = None, @@ -8022,6 +10377,23 @@ async def add_or_update_address_to_individual_async( Add or Update Address to Individual Add or Update Address to Individual + + Swagger operation ID: `Add-or-Update-Address-to-Individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Individual ID or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8032,7 +10404,7 @@ async def add_or_update_address_to_individual_async( f"/Addresses" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -8046,6 +10418,7 @@ async def add_or_update_address_to_individual_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8053,13 +10426,13 @@ async def add_or_update_address_to_individual_async( return json.loads(response.text) - async def find_members_or_individuals_by_first_and_last_name_async( + def find_members_or_individuals_by_first_and_last_name( self, first_name: str, last_name: str, page_number: int, - include_email: Optional[bool] = None, *, + include_email: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -8069,6 +10442,25 @@ async def find_members_or_individuals_by_first_and_last_name_async( Find Members (Individuals) by First Name and Last Name Find Members (Individuals) by First Name and Last Name + + Swagger operation ID: + `Find-members-or-individuals-by-first-and-last-name`. + + Args: + first_name: First Name. + last_name: Last Name. + page_number: Page Number. + include_email: Include Email Data. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8090,7 +10482,7 @@ async def find_members_or_individuals_by_first_and_last_name_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -8104,6 +10496,7 @@ async def find_members_or_individuals_by_first_and_last_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8111,13 +10504,13 @@ async def find_members_or_individuals_by_first_and_last_name_async( return json.loads(response.text) - async def get_committee_members_by_committee_id_or_code_async( + def get_committee_members_by_committee_id_or_code( self, id_or_code: str, page_number: int, + *, term: Optional[int] = None, position_codes: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -8127,6 +10520,24 @@ async def get_committee_members_by_committee_id_or_code_async( Get Committee Members by committee ID or code Get Committee Members by Committee ID or Code + + Swagger operation ID: `Get-Committee-Members-by-committee-ID-or-code`. + + Args: + id_or_code: Committee ID or Code. + page_number: Page Number. + term: Term. + position_codes: Position Codes. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8151,7 +10562,7 @@ async def get_committee_members_by_committee_id_or_code_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -8165,11 +10576,12 @@ async def get_committee_members_by_committee_id_or_code_async( request_url, response.status, response.text, + response=response, ) - async def add_activity_async( + def add_activity( self, - input: AddActivityInput, + input: AddActivityInput | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -8181,13 +10593,30 @@ async def add_activity_async( Add Activity Add Activity. + + Swagger operation ID: `Add-Activity`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Individual Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Individuals/{quote(str(id), safe='')}/Activities" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -8201,9 +10630,10 @@ async def add_activity_async( request_url, response.status, response.text, + response=response, ) - async def find_individual_id_or_email_async( + def find_individual_id_or_email( self, id_or_record_number_or_email: str, page_number: int, @@ -8217,6 +10647,22 @@ async def find_individual_id_or_email_async( Find Individual by Id or Email or Record Number Find Individual by Id or Email. + + Swagger operation ID: `Find-Individual-IDOrEmail`. + + Args: + id_or_record_number_or_email: Id or Record Number or Email. + page_number: pageNumber. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8232,7 +10678,7 @@ async def find_individual_id_or_email_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -8246,6 +10692,7 @@ async def find_individual_id_or_email_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8253,9 +10700,9 @@ async def find_individual_id_or_email_async( return json.loads(response.text) - async def add_relationship_to_individual_async( + def add_relationship_to_individual( self, - input: AddRelationshipToIndividualInput, + input: AddRelationshipToIndividualInput | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -8267,13 +10714,30 @@ async def add_relationship_to_individual_async( Add Relationship to Individual Add Relationship to Individual. + + Swagger operation ID: `Add-relationship-to-individual`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Individual Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Individuals/{quote(str(id), safe='')}/Relationships" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -8287,11 +10751,12 @@ async def add_relationship_to_individual_async( request_url, response.status, response.text, + response=response, ) - async def individual_add_education_credit_async( + def individual_add_education_credit( self, - input: EducationCreditData, + input: EducationCreditData | Mapping[str, Any], id_or_record_number: str, *, timeout: Optional[float] = None, @@ -8303,6 +10768,23 @@ async def individual_add_education_credit_async( Add Education Credits to Individual Add a new Education Credit to an Individual. + + Swagger operation ID: `Individual-Add-Education-Credit`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id_or_record_number: Individual Id or Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8313,7 +10795,7 @@ async def individual_add_education_credit_async( f"/EducationCredits" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -8327,11 +10809,12 @@ async def individual_add_education_credit_async( request_url, response.status, response.text, + response=response, ) - async def individual_add_note_async( + def individual_add_note( self, - input: NoteData, + input: NoteData | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -8343,13 +10826,30 @@ async def individual_add_note_async( Add Note to Individual Add a Note to an Individual. + + Swagger operation ID: `Individual-AddNote`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Individual Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Individuals/{quote(str(id), safe='')}/Notes" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -8363,9 +10863,10 @@ async def individual_add_note_async( request_url, response.status, response.text, + response=response, ) - async def individuals_lookup_by_name_async( + def individuals_lookup_by_name( self, page_number: int, name: str, @@ -8379,6 +10880,22 @@ async def individuals_lookup_by_name_async( Lookup Individuals Lookup Individuals by Name + + Swagger operation ID: `Individuals-LookupByName`. + + Args: + page_number: pageNumber. + name: Individual Name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8393,7 +10910,7 @@ async def individuals_lookup_by_name_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -8407,6 +10924,7 @@ async def individuals_lookup_by_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8414,9 +10932,9 @@ async def individuals_lookup_by_name_async( return json.loads(response.text) - async def add_to_committee_async( + def add_to_committee( self, - input: CommitteeMemberCreateData, + input: CommitteeMemberCreateData | Mapping[str, Any], code: str, *, timeout: Optional[float] = None, @@ -8428,13 +10946,30 @@ async def add_to_committee_async( Add Individual to Committee Add Individual to Committee. + + Swagger operation ID: `Add-To-Committee`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + code: Committee Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Committees/{quote(str(code), safe='')}/Members" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -8448,6 +10983,7 @@ async def add_to_committee_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8455,9 +10991,9 @@ async def add_to_committee_async( return json.loads(response.text) - async def update_committee_member_async( + def update_committee_member( self, - input: CommitteeMemberUpdateData, + input: CommitteeMemberUpdateData | Mapping[str, Any], code: str, member_record_number: str, current_position_code: str, @@ -8471,6 +11007,25 @@ async def update_committee_member_async( Update Committee Member Update Committee Member. + + Swagger operation ID: `Update-Committee-Member`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + code: Committee Code. + member_record_number: Member Record Number. + current_position_code: Current Position Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8483,7 +11038,7 @@ async def update_committee_member_async( f"/{quote(str(current_position_code), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -8497,11 +11052,12 @@ async def update_committee_member_async( request_url, response.status, response.text, + response=response, ) - async def add_organization_async( + def add_organization( self, - input: AddOrganizationInput, + input: AddOrganizationInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -8512,10 +11068,26 @@ async def add_organization_async( Add Organization Add Organization. + + Swagger operation ID: `Add-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/v1/Organizations" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -8529,6 +11101,7 @@ async def add_organization_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8536,9 +11109,9 @@ async def add_organization_async( return json.loads(response.text) - async def update_organization_async( + def update_organization( self, - input: UpdateOrganizationInput, + input: UpdateOrganizationInput | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -8550,13 +11123,30 @@ async def update_organization_async( Update Organization Update Organization. + + Swagger operation ID: `Update-Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Organization Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Organizations/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -8570,6 +11160,7 @@ async def update_organization_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8577,7 +11168,7 @@ async def update_organization_async( return json.loads(response.text) - async def organization_get_profile_async( + def organization_get_profile( self, id_or_recordnumber: str, page_number: int, @@ -8591,6 +11182,22 @@ async def organization_get_profile_async( Find Organization by Id or Record Number Get organization's profile information by ID or Record Number + + Swagger operation ID: `Organization-Get-Profile`. + + Args: + id_or_recordnumber: Organization Id or Record Number. + page_number: pageNumber. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8606,7 +11213,7 @@ async def organization_get_profile_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -8620,6 +11227,7 @@ async def organization_get_profile_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8627,9 +11235,9 @@ async def organization_get_profile_async( return json.loads(response.text) - async def organization_add_note_async( + def organization_add_note( self, - input: NoteData, + input: NoteData | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -8641,13 +11249,30 @@ async def organization_add_note_async( Add Note to Organization Add a Note to an Organization. + + Swagger operation ID: `Organization-AddNote`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Organization Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Organizations/{quote(str(id), safe='')}/Notes" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -8661,9 +11286,10 @@ async def organization_add_note_async( request_url, response.status, response.text, + response=response, ) - async def organization_lookup_by_name_async( + def organization_lookup_by_name( self, page_number: int, name: str, @@ -8677,6 +11303,22 @@ async def organization_lookup_by_name_async( Lookup Organizations Lookup Organizations by Name or Acronym + + Swagger operation ID: `Organization-LookupByName`. + + Args: + page_number: pageNumber. + name: Name or Acronym. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8691,7 +11333,7 @@ async def organization_lookup_by_name_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -8705,6 +11347,7 @@ async def organization_lookup_by_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8712,14 +11355,14 @@ async def organization_lookup_by_name_async( return json.loads(response.text) - async def get_all_committees_async( + def get_all_committees( self, page_number: int, + *, code: Optional[str] = None, name: Optional[str] = None, term: Optional[int] = None, active_only: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -8729,6 +11372,25 @@ async def get_all_committees_async( Get All Committees Get All Committees + + Swagger operation ID: `Get-All-Committees`. + + Args: + page_number: Page Number. + code: Committee Code. + name: Committee Name. + term: Term. + active_only: Active Only. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8758,7 +11420,7 @@ async def get_all_committees_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -8772,6 +11434,7 @@ async def get_all_committees_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8779,7 +11442,7 @@ async def get_all_committees_async( return json.loads(response.text) - async def get_positions_by_committee_async( + def get_positions_by_committee( self, code: str, *, @@ -8792,13 +11455,28 @@ async def get_positions_by_committee_async( Get Positions by Committee Get Positions by Committee + + Swagger operation ID: `Get-Positions-by-Committee`. + + Args: + code: Committee Code. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Committees/{quote(str(code), safe='')}/Positions" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -8812,6 +11490,7 @@ async def get_positions_by_committee_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8819,7 +11498,7 @@ async def get_positions_by_committee_async( return json.loads(response.text) - async def get_sub_committees_async( + def get_sub_committees( self, code: str, page_number: int, @@ -8833,6 +11512,22 @@ async def get_sub_committees_async( Get Sub-Committees Get Sub-Committees + + Swagger operation ID: `Get-Sub-Committees`. + + Args: + code: Code. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8844,7 +11539,7 @@ async def get_sub_committees_async( f"/{quote(str(page_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -8858,6 +11553,7 @@ async def get_sub_committees_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8865,7 +11561,7 @@ async def get_sub_committees_async( return json.loads(response.text) - async def get_individuals_active_subscriptions_async( + def get_individuals_active_subscriptions( self, id: str, page_number: int, @@ -8879,6 +11575,22 @@ async def get_individuals_active_subscriptions_async( Get Individual's Active Subscriptions Get Individual's Active Subscriptions + + Swagger operation ID: `Get-Individuals-Active-Subscriptions`. + + Args: + id: Individual. + page_number: Page Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8891,7 +11603,7 @@ async def get_individuals_active_subscriptions_async( f"/{quote(str(page_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -8905,6 +11617,7 @@ async def get_individuals_active_subscriptions_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8912,22 +11625,44 @@ async def get_individuals_active_subscriptions_async( return json.loads(response.text) - async def list_all_individuals_async( + def list_all_individuals( self, page_number: int, + *, name: Optional[str] = None, include_details: Optional[bool] = None, old_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List all Individuals List all Individuals + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `List-all-Individuals`. + + Args: + page_number: Page Number. + name: Individual Name. + include_details: Include Details. + old_id: Individual Old ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8951,29 +11686,50 @@ async def list_all_individuals_async( query_params.append(f"oldID={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("dataList", []): + yield item - async def find_customer_phone_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def find_customer_phone( self, page_number: str, phone_number: str, @@ -8987,6 +11743,22 @@ async def find_customer_phone_async( Find Customer by Phone Number Find Customer by Phone Number. + + Swagger operation ID: `Find-Customer-Phone`. + + Args: + page_number: pageNumber. + phone_number: Phone Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -9003,7 +11775,7 @@ async def find_customer_phone_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -9017,6 +11789,7 @@ async def find_customer_phone_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -9024,7 +11797,7 @@ async def find_customer_phone_async( return json.loads(response.text) - async def mark_registrant_attended_async( + def mark_registrant_attended( self, input: MarkRegistrantAttendedInput, record_number: str, @@ -9038,6 +11811,22 @@ async def mark_registrant_attended_async( Mark Registrant as Attended Mark the Registrant as Attended for the specified Events. + + Swagger operation ID: `Mark-Registrant-Attended`. + + Args: + input: The request body. + record_number: Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -9049,7 +11838,7 @@ async def mark_registrant_attended_async( f"/Attended" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -9063,11 +11852,12 @@ async def mark_registrant_attended_async( request_url, response.status, response.text, + response=response, ) - async def awards_add_award_nomination_async( + def awards_add_award_nomination( self, - input: AwardNominationData, + input: AwardNominationData | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -9079,13 +11869,30 @@ async def awards_add_award_nomination_async( Add Award Nomination Add a new Award Nomination. + + Swagger operation ID: `Awards-AddAwardNomination`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Award Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v1/Awards/{quote(str(id), safe='')}/Nominations" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -9099,11 +11906,12 @@ async def awards_add_award_nomination_async( request_url, response.status, response.text, + response=response, ) - async def awards_update_award_nomination_async( + def awards_update_award_nomination( self, - input: UpdateAwardNominationData, + input: UpdateAwardNominationData | Mapping[str, Any], id: str, nominee_record_number: str, *, @@ -9116,6 +11924,24 @@ async def awards_update_award_nomination_async( Update Award Nomination Update an existing Award Nomination. + + Swagger operation ID: `Awards-UpdateAwardNomination`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Award Id. + nominee_record_number: Nominee Record Number. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -9127,7 +11953,7 @@ async def awards_update_award_nomination_async( f"/{quote(str(nominee_record_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -9141,9 +11967,10 @@ async def awards_update_award_nomination_async( request_url, response.status, response.text, + response=response, ) - async def awards_get_individual_award_recipients_async( + def awards_get_individual_award_recipients( self, page_number: int, id: str, @@ -9157,6 +11984,22 @@ async def awards_get_individual_award_recipients_async( List Award Individual Recipients List all Individuals that are Award Recipients. + + Swagger operation ID: `Awards-GetIndividualAwardRecipients`. + + Args: + page_number: pageNumber. + id: Award Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -9173,7 +12016,7 @@ async def awards_get_individual_award_recipients_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -9187,6 +12030,7 @@ async def awards_get_individual_award_recipients_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -9194,7 +12038,7 @@ async def awards_get_individual_award_recipients_async( return json.loads(response.text) - async def awards_get_organization_award_recipients_async( + def awards_get_organization_award_recipients( self, page_number: int, id: str, @@ -9208,6 +12052,22 @@ async def awards_get_organization_award_recipients_async( List Award Organization Recipients List all Organizations that are Award Recipients. + + Swagger operation ID: `Awards-GetOrganizationAwardRecipients`. + + Args: + page_number: pageNumber. + id: Award Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -9224,7 +12084,7 @@ async def awards_get_organization_award_recipients_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -9238,6 +12098,7 @@ async def awards_get_organization_award_recipients_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/infusionsoft.py b/src/azure/connectors/infusionsoft.py index eac6265..d6232c7 100644 --- a/src/azure/connectors/infusionsoft.py +++ b/src/azure/connectors/infusionsoft.py @@ -5,21 +5,32 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "InfusionsoftClient", + "CreateTaskRequest", + "ListOrdersResponse", + "ListTasksResponse", + "OnNewTaskResponse", + "TaskResponse", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,28 +40,32 @@ class TaskResponse: Response for Create a task """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """An integer that uniquely identifies this task.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The actual task name (Do this thing).""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """A description of the task defined by the user.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """ A string representing the type of Task as defined by the user from a list of types editable in the Infusionsoft application. """ - priority: Optional[int] = None + priority: Optional[int] = dataclass_field(default=None, kw_only=True) """The priority of the task.""" - completed: Optional[bool] = None + completed: Optional[bool] = dataclass_field(default=None, kw_only=True) """A boolean indicating the completed status of the task.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The link to the task.""" - due_date: Optional[str] = None + due_date: Optional[str] = dataclass_field(default=None, kw_only=True) """The datetime the task is due, given as GMT in ISO 8601 format.""" -OnNewTaskResponse = List["TaskResponse"] +OnNewTaskResponse = List["TaskResponse | Mapping[str, Any]"] ListOrdersResponse = List[Dict[str, Any]] @@ -62,7 +77,7 @@ class ListTasksResponse: Response for List tasks """ - tasks: Optional[List[Dict[str, Any]]] = None + tasks: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Collection of tasks.""" @@ -72,15 +87,19 @@ class CreateTaskRequest: Definition: CreateTask_Request """ - title: Optional[str] = None + title: str """The title of the task.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """A description of the task title.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type of the task.""" - priority: Optional[int] = None + priority: Optional[int] = dataclass_field(default=None, kw_only=True) """Priority of the task (1, 2, 3, etc.)""" - due_date: Optional[str] = None + due_date: Optional[str] = dataclass_field(default=None, kw_only=True) """Due date of the task (Ex. 2014-06-17T17:12:52.000Z""" @@ -92,16 +111,16 @@ class InfusionsoftClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -112,8 +131,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -121,8 +140,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -134,7 +153,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -149,9 +168,48 @@ def __init__( def connector_name(self) -> str: return "infusionsoft" - async def create_task_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def create_task( self, - input: CreateTaskRequest, + input: CreateTaskRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -162,10 +220,26 @@ async def create_task_async( Create a task Create a new task. + + Swagger operation ID: `CreateTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/crm/rest/v1/tasks/" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -179,6 +253,7 @@ async def create_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -186,9 +261,9 @@ async def create_task_async( return json.loads(response.text) - async def update_task_async( + def update_task( self, - input: CreateTaskRequest, + input: CreateTaskRequest | Mapping[str, Any], id: int, *, timeout: Optional[float] = None, @@ -200,13 +275,30 @@ async def update_task_async( Update a task Update an existing task. + + Swagger operation ID: `UpdateTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Id of the task. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/crm/rest/v1/tasks/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -220,6 +312,7 @@ async def update_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -227,18 +320,36 @@ async def update_task_async( return json.loads(response.text) - async def list_tasks_async( + def list_tasks( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List tasks Retrieve a page of tasks ordered by due date. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTasks`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/crm/rest/v1/tasks/search" @@ -247,27 +358,48 @@ async def list_tasks_async( query_params.append("order=" + quote("-due_date", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("tasks", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/insightly.py b/src/azure/connectors/insightly.py index 2a09aa7..60f05ad 100644 --- a/src/azure/connectors/insightly.py +++ b/src/azure/connectors/insightly.py @@ -5,21 +5,49 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "InsightlyClient", + "Address", + "Contact", + "ContactInfo", + "ContactRequest", + "Event", + "Lead", + "LeadRequest", + "ListContactsResponse", + "ListEventsResponse", + "ListLeadsResponse", + "ListProjectsResponse", + "ListTasksResponse", + "ListUsersResponse", + "ObjectEntity", + "Organization", + "OrganizationRequest", + "Project", + "ProjectRequest", + "Tag", + "TaskObject", + "TaskRequest", + "User", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +57,12 @@ class ListTasksResponse: Response for List tasks """ - tasks: Optional[List[TaskObject]] = None + tasks: Optional[ + List[TaskObject | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A collection of tasks""" @@ -39,162 +72,193 @@ class TaskObject: Response for Update task """ - t_a_s_k_id: Optional[int] = field( + t_a_s_k_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TASK_ID"}, ) """The unique identifier of the task.""" - t_i_t_l_e: Optional[str] = field( + t_i_t_l_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TITLE"}, ) """The title of the task.""" - d_u_e_d_a_t_e: Optional[str] = field( + d_u_e_d_a_t_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DUE_DATE"}, ) """yyyy-MM-dd HH:mm:ss""" - c_a_t_e_g_o_r_y_id: Optional[int] = field( + c_a_t_e_g_o_r_y_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CATEGORY_ID"}, ) """The unique identifier of the category.""" - c_o_m_p_l_e_t_e_d_d_a_t_e_u_t_c: Optional[str] = field( + c_o_m_p_l_e_t_e_d_d_a_t_e_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "COMPLETED_DATE_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - c_o_m_p_l_e_t_e_d: Optional[bool] = field( + c_o_m_p_l_e_t_e_d: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "COMPLETED"}, ) """A boolean value determining whether or not the task is completed.""" - d_e_t_a_i_l_s: Optional[str] = field( + d_e_t_a_i_l_s: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DETAILS"}, ) """The details of the task.""" - s_t_a_t_u_s: Optional[str] = field( + s_t_a_t_u_s: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "STATUS"}, ) """The status of the task.""" - p_r_i_o_r_i_t_y: Optional[int] = field( + p_r_i_o_r_i_t_y: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PRIORITY"}, ) """The priority of the task.""" - s_t_a_r_t_d_a_t_e: Optional[str] = field( + s_t_a_r_t_d_a_t_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "START_DATE"}, ) """yyyy-MM-dd HH:mm:ss""" - p_r_o_j_e_c_t_id: Optional[int] = field( + p_r_o_j_e_c_t_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PROJECT_ID"}, ) """The unique identifier of the project.""" - o_p_p_o_r_t_u_n_i_t_y_id: Optional[int] = field( + o_p_p_o_r_t_u_n_i_t_y_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OPPORTUNITY_ID"}, ) """The unique identifier of the opportunity.""" - m_i_l_e_s_t_o_n_e_id: Optional[int] = field( + m_i_l_e_s_t_o_n_e_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MILESTONE_ID"}, ) """The unique identifier of the milestone.""" - p_i_p_e_l_i_n_e_id: Optional[int] = field( + p_i_p_e_l_i_n_e_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PIPELINE_ID"}, ) """The unique identifier of the pipeline.""" - s_t_a_g_e_id: Optional[int] = field( + s_t_a_g_e_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "STAGE_ID"}, ) """The unique identifier of the stage.""" - p_e_r_c_e_n_t_c_o_m_p_l_e_t_e: Optional[int] = field( + p_e_r_c_e_n_t_c_o_m_p_l_e_t_e: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PERCENT_COMPLETE"}, ) """The task completed value in percent.""" - o_w_n_e_r_u_s_e_r_id: Optional[int] = field( + o_w_n_e_r_u_s_e_r_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OWNER_USER_ID"}, ) """The unique identifier of the task owner.""" - r_e_s_p_o_n_s_i_b_l_e_u_s_e_r_id: Optional[int] = field( + r_e_s_p_o_n_s_i_b_l_e_u_s_e_r_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RESPONSIBLE_USER_ID"}, ) """The unique identifier of the user assigned to the task.""" - p_u_b_l_i_c_l_y_v_i_s_i_b_l_e: Optional[bool] = field( + p_u_b_l_i_c_l_y_v_i_s_i_b_l_e: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PUBLICLY_VISIBLE"}, ) """ A boolean value determining whether or not the task is publicly visible. """ - d_a_t_e_c_r_e_a_t_e_d_u_t_c: Optional[str] = field( + d_a_t_e_c_r_e_a_t_e_d_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DATE_CREATED_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - d_a_t_e_u_p_d_a_t_e_d_u_t_c: Optional[str] = field( + d_a_t_e_u_p_d_a_t_e_d_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DATE_UPDATED_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - a_s_s_i_g_n_e_d_b_y_u_s_e_r_id: Optional[int] = field( + a_s_s_i_g_n_e_d_b_y_u_s_e_r_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ASSIGNED_BY_USER_ID"}, ) """The unique identifier of the assigned by user.""" - p_a_r_e_n_t_t_a_s_k_id: Optional[int] = field( + p_a_r_e_n_t_t_a_s_k_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PARENT_TASK_ID"}, ) """The unique identifier of the parent task.""" - o_w_n_e_r_v_i_s_i_b_l_e: Optional[bool] = field( + o_w_n_e_r_v_i_s_i_b_l_e: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OWNER_VISIBLE"}, ) """ A boolean value determining whether or not the owner is publicly visible. """ - a_s_s_i_g_n_e_d_t_e_a_m_id: Optional[int] = field( + a_s_s_i_g_n_e_d_t_e_a_m_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ASSIGNED_TEAM_ID"}, ) """The unique identifier of the assigned team.""" - a_s_s_i_g_n_e_d_d_a_t_e_u_t_c: Optional[str] = field( + a_s_s_i_g_n_e_d_d_a_t_e_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ASSIGNED_DATE_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - r_e_m_i_n_d_e_r_d_a_t_e_u_t_c: Optional[str] = field( + r_e_m_i_n_d_e_r_d_a_t_e_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "REMINDER_DATE_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - r_e_m_i_n_d_e_r_s_e_n_t: Optional[bool] = field( + r_e_m_i_n_d_e_r_s_e_n_t: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "REMINDER_SENT"}, ) """A boolean value determining whether or not a reminder is set.""" - r_e_c_u_r_r_e_n_c_e: Optional[str] = field( + r_e_c_u_r_r_e_n_c_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RECURRENCE"}, ) """Recurrence""" - c_a_n_e_d_i_t: Optional[bool] = field( + c_a_n_e_d_i_t: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CAN_EDIT"}, ) """Can edit.""" - c_a_n_d_e_l_e_t_e: Optional[bool] = field( + c_a_n_d_e_l_e_t_e: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CAN_DELETE"}, ) """Can delete""" @@ -206,8 +270,19 @@ class ListProjectsResponse: Response for List projects """ - projects: Optional[List[Project]] = None + projects: Optional[ + List[Project | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A collection of projects""" + next_link: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "nextLink"}, + ) + """The URL to retrieve the next page.""" @dataclass @@ -216,103 +291,123 @@ class Project: Response for Update project """ - p_r_o_j_e_c_t_id: Optional[int] = field( + p_r_o_j_e_c_t_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PROJECT_ID"}, ) """The unique identifier of the project.""" - p_r_o_j_e_c_t_n_a_m_e: Optional[str] = field( + p_r_o_j_e_c_t_n_a_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PROJECT_NAME"}, ) """The name of the project.""" - s_t_a_t_u_s: Optional[str] = field( + s_t_a_t_u_s: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "STATUS"}, ) """The status of the project.""" - p_r_o_j_e_c_t_d_e_t_a_i_l_s: Optional[str] = field( + p_r_o_j_e_c_t_d_e_t_a_i_l_s: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PROJECT_DETAILS"}, ) """The details of the project.""" - i_m_a_g_e_u_r_l: Optional[str] = field( + i_m_a_g_e_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IMAGE_URL"}, ) """The image URL of the project.""" - d_a_t_e_c_r_e_a_t_e_d_u_t_c: Optional[str] = field( + d_a_t_e_c_r_e_a_t_e_d_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DATE_CREATED_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - v_i_s_i_b_l_e_t_o: Optional[str] = field( + v_i_s_i_b_l_e_t_o: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TO"}, ) """Project Visibility.""" - d_a_t_e_u_p_d_a_t_e_d_u_t_c: Optional[str] = field( + d_a_t_e_u_p_d_a_t_e_d_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DATE_UPDATED_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - s_t_a_r_t_e_d_d_a_t_e: Optional[str] = field( + s_t_a_r_t_e_d_d_a_t_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "STARTED_DATE"}, ) """yyyy-MM-dd HH:mm:ss""" - c_o_m_p_l_e_t_e_d_d_a_t_e: Optional[str] = field( + c_o_m_p_l_e_t_e_d_d_a_t_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "COMPLETED_DATE"}, ) """yyyy-MM-dd HH:mm:ss""" - o_w_n_e_r_u_s_e_r_id: Optional[int] = field( + o_w_n_e_r_u_s_e_r_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OWNER_USER_ID"}, ) """The unique identifier of the project owner.""" - r_e_s_p_o_n_s_i_b_l_e_u_s_e_r_id: Optional[int] = field( + r_e_s_p_o_n_s_i_b_l_e_u_s_e_r_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RESPONSIBLE_USER_ID"}, ) """The unique identifier of the assigned user.""" - o_p_p_o_r_t_u_n_i_t_y_id: Optional[int] = field( + o_p_p_o_r_t_u_n_i_t_y_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OPPORTUNITY_ID"}, ) """The unique identifier of the opportunity.""" - p_i_p_e_l_i_n_e_id: Optional[int] = field( + p_i_p_e_l_i_n_e_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PIPELINE_ID"}, ) """The unique identifier of the pipeline.""" - s_t_a_g_e_id: Optional[int] = field( + s_t_a_g_e_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "STAGE_ID"}, ) """The unique identifier of the stage.""" - c_a_t_e_g_o_r_y_id: Optional[int] = field( + c_a_t_e_g_o_r_y_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CATEGORY_ID"}, ) """The unique identifier of the category.""" - v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = field( + v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TEAM_ID"}, ) """The unique identifier of the team.""" - v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = field( + v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_USER_IDS"}, ) """The unique identifiers of the users.""" - c_a_n_e_d_i_t: Optional[bool] = field( + c_a_n_e_d_i_t: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CAN_EDIT"}, ) """Can edit""" - c_a_n_d_e_l_e_t_e: Optional[bool] = field( + c_a_n_d_e_l_e_t_e: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CAN_DELETE"}, ) """Can delete""" @@ -324,7 +419,12 @@ class ListLeadsResponse: Response for List leads """ - leads: Optional[List[Lead]] = None + leads: Optional[ + List[Lead | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A collection of leads""" @@ -334,188 +434,225 @@ class Lead: Response for Update lead """ - l_e_a_d_id: Optional[int] = field( + l_e_a_d_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LEAD_ID"}, ) """The unique identifier of the lead.""" - s_a_l_u_t_a_t_i_o_n: Optional[str] = field( + s_a_l_u_t_a_t_i_o_n: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SALUTATION"}, ) """The salutation of the lead.""" - t_i_t_l_e: Optional[str] = field( + t_i_t_l_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TITLE"}, ) """The title of the lead.""" - f_i_r_s_t_n_a_m_e: Optional[str] = field( + f_i_r_s_t_n_a_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FIRST_NAME"}, ) """First name of the lead.""" - l_a_s_t_n_a_m_e: Optional[str] = field( + l_a_s_t_n_a_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LAST_NAME"}, ) """Last name of the lead.""" - l_e_a_d_d_e_s_c_r_i_p_t_i_o_n: Optional[str] = field( + l_e_a_d_d_e_s_c_r_i_p_t_i_o_n: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LEAD_DESCRIPTION"}, ) """A brief description of the lead.""" - d_a_t_e_c_r_e_a_t_e_d_u_t_c: Optional[str] = field( + d_a_t_e_c_r_e_a_t_e_d_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DATE_CREATED_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - d_a_t_e_u_p_d_a_t_e_d_u_t_c: Optional[str] = field( + d_a_t_e_u_p_d_a_t_e_d_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DATE_UPDATED_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - c_o_n_v_e_r_t_e_d_d_a_t_e_u_t_c: Optional[str] = field( + c_o_n_v_e_r_t_e_d_d_a_t_e_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONVERTED_DATE_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - l_e_a_d_s_t_a_t_u_s_id: Optional[int] = field( + l_e_a_d_s_t_a_t_u_s_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LEAD_STATUS_ID"}, ) """The status Id of the lead.""" - v_i_s_i_b_l_e_t_o: Optional[str] = field( + v_i_s_i_b_l_e_t_o: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TO"}, ) """Lead visibility.""" - o_r_g_a_n_i_z_a_t_i_o_n_n_a_m_e: Optional[str] = field( + o_r_g_a_n_i_z_a_t_i_o_n_n_a_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ORGANIZATION_NAME"}, ) """The name of the organization.""" - p_h_o_n_e_n_u_m_b_e_r: Optional[str] = field( + p_h_o_n_e_n_u_m_b_e_r: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PHONE_NUMBER"}, ) """Lead phone number.""" - m_o_b_i_l_e_p_h_o_n_e_n_u_m_b_e_r: Optional[str] = field( + m_o_b_i_l_e_p_h_o_n_e_n_u_m_b_e_r: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MOBILE_PHONE_NUMBER"}, ) """Lead mobile phone number.""" - e_m_a_i_l_a_d_d_r_e_s_s: Optional[str] = field( + e_m_a_i_l_a_d_d_r_e_s_s: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EMAIL_ADDRESS"}, ) """Lead email address.""" - c_o_n_v_e_r_t_e_d: Optional[bool] = field( + c_o_n_v_e_r_t_e_d: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONVERTED"}, ) """A boolean value determining whether or not the lead is converted.""" - w_e_b_s_i_t_e_u_r_l: Optional[str] = field( + w_e_b_s_i_t_e_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WEBSITE_URL"}, ) """Lead website URL""" - o_w_n_e_r_u_s_e_r_id: Optional[int] = field( + o_w_n_e_r_u_s_e_r_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OWNER_USER_ID"}, ) """The unique identifier of the lead owner.""" - r_e_s_p_o_n_s_i_b_l_e_u_s_e_r_id: Optional[int] = field( + r_e_s_p_o_n_s_i_b_l_e_u_s_e_r_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RESPONSIBLE_USER_ID"}, ) """The unique identifier of the responsible user.""" - e_m_p_l_o_y_e_e_c_o_u_n_t: Optional[int] = field( + e_m_p_l_o_y_e_e_c_o_u_n_t: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EMPLOYEE_COUNT"}, ) """The employee count of the lead.""" - l_e_a_d_r_a_t_i_n_g: Optional[int] = field( + l_e_a_d_r_a_t_i_n_g: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LEAD_RATING"}, ) """The rating of the lead.""" - i_n_d_u_s_t_r_y: Optional[str] = field( + i_n_d_u_s_t_r_y: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "INDUSTRY"}, ) """The industry of the lead.""" - a_d_d_r_e_s_s_s_t_r_e_e_t: Optional[str] = field( + a_d_d_r_e_s_s_s_t_r_e_e_t: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADDRESS_STREET"}, ) """Address street.""" - a_d_d_r_e_s_s_c_i_t_y: Optional[str] = field( + a_d_d_r_e_s_s_c_i_t_y: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADDRESS_CITY"}, ) """Address city.""" - a_d_d_r_e_s_s_s_t_a_t_e: Optional[str] = field( + a_d_d_r_e_s_s_s_t_a_t_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADDRESS_STATE"}, ) """Address state.""" - a_d_d_r_e_s_s_p_o_s_t_c_o_d_e: Optional[str] = field( + a_d_d_r_e_s_s_p_o_s_t_c_o_d_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADDRESS_POSTCODE"}, ) """Address postcode.""" - a_d_d_r_e_s_s_c_o_u_n_t_r_y: Optional[str] = field( + a_d_d_r_e_s_s_c_o_u_n_t_r_y: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADDRESS_COUNTRY"}, ) """Address country.""" - f_a_x_n_u_m_b_e_r: Optional[str] = field( + f_a_x_n_u_m_b_e_r: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FAX_NUMBER"}, ) """Lead fax number.""" - c_o_n_v_e_r_t_e_d_c_o_n_t_a_c_t_id: Optional[int] = field( + c_o_n_v_e_r_t_e_d_c_o_n_t_a_c_t_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONVERTED_CONTACT_ID"}, ) """The unique identifier of the converted contact.""" - c_o_n_v_e_r_t_e_d_o_r_g_a_n_i_z_a_t_i_o_n_id: Optional[int] = field( + c_o_n_v_e_r_t_e_d_o_r_g_a_n_i_z_a_t_i_o_n_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONVERTED_ORGANIZATION_ID"}, ) """The unique identifier of the converted organization.""" - c_o_n_v_e_r_t_e_d_o_p_p_o_r_t_u_n_i_t_y_id: Optional[int] = field( + c_o_n_v_e_r_t_e_d_o_p_p_o_r_t_u_n_i_t_y_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONVERTED_OPPORTUNITY_ID"}, ) """The unique identifier of the opportunity.""" - l_e_a_d_s_o_u_r_c_e_id: Optional[int] = field( + l_e_a_d_s_o_u_r_c_e_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LEAD_SOURCE_ID"}, ) """The unique identifier of the lead source.""" - v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = field( + v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TEAM_ID"}, ) """The unique identifier of the team.""" - v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = field( + v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_USER_IDS"}, ) """The unique identifiers of the users.""" - i_m_a_g_e_u_r_l: Optional[str] = field( + i_m_a_g_e_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IMAGE_URL"}, ) """Lead Image URL""" - c_a_n_e_d_i_t: Optional[bool] = field( + c_a_n_e_d_i_t: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CAN_EDIT"}, ) """Can edit""" - c_a_n_d_e_l_e_t_e: Optional[bool] = field( + c_a_n_d_e_l_e_t_e: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CAN_DELETE"}, ) """Can delete""" @@ -527,7 +664,12 @@ class ListContactsResponse: Response for List contacts """ - contacts: Optional[List[Contact]] = None + contacts: Optional[ + List[Contact | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A collection of contacts""" @@ -537,153 +679,184 @@ class Contact: Response for Update contact """ - a_d_d_r_e_s_s_w_o_r_k: Optional[Dict[str, Any]] = field( + a_d_d_r_e_s_s_w_o_r_k: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADDRESS_WORK"}, ) - a_d_d_r_e_s_s_h_o_m_e: Optional[Dict[str, Any]] = field( + a_d_d_r_e_s_s_h_o_m_e: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADDRESS_HOME"}, ) - a_d_d_r_e_s_s_p_o_s_t_a_l: Optional[Dict[str, Any]] = field( + a_d_d_r_e_s_s_p_o_s_t_a_l: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADDRESS_POSTAL"}, ) - a_d_d_r_e_s_s_p_r_i_m_a_r_y: Optional[Dict[str, Any]] = field( + a_d_d_r_e_s_s_p_r_i_m_a_r_y: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADDRESS_PRIMARY"}, ) - a_d_d_r_e_s_s_o_t_h_e_r: Optional[Dict[str, Any]] = field( + a_d_d_r_e_s_s_o_t_h_e_r: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADDRESS_OTHER"}, ) - e_m_a_i_l_w_o_r_k: Optional[str] = field( + e_m_a_i_l_w_o_r_k: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EMAIL_WORK"}, ) """The work email of the contact.""" - e_m_a_i_l_h_o_m_e: Optional[str] = field( + e_m_a_i_l_h_o_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EMAIL_HOME"}, ) """The home email of the contact.""" - e_m_a_i_l_p_e_r_s_o_n_a_l: Optional[str] = field( + e_m_a_i_l_p_e_r_s_o_n_a_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EMAIL_PERSONAL"}, ) """The personal email of the contact.""" - e_m_a_i_l_o_t_h_e_r: Optional[str] = field( + e_m_a_i_l_o_t_h_e_r: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EMAIL_OTHER"}, ) """The other email of the contact.""" - p_h_o_n_e_w_o_r_k: Optional[str] = field( + p_h_o_n_e_w_o_r_k: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PHONE_WORK"}, ) """The work phone number of the contact.""" - p_h_o_n_e_h_o_m_e: Optional[str] = field( + p_h_o_n_e_h_o_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PHONE_HOME"}, ) """The home phone number of the contact.""" - p_h_o_n_e_m_o_b_i_l_e: Optional[str] = field( + p_h_o_n_e_m_o_b_i_l_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PHONE_MOBILE"}, ) """The mobile phone number of the contact.""" - p_h_o_n_e_o_t_h_e_r: Optional[str] = field( + p_h_o_n_e_o_t_h_e_r: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PHONE_OTHER"}, ) """The other phone number of the contact.""" - c_o_n_t_a_c_t_id: Optional[int] = field( + c_o_n_t_a_c_t_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONTACT_ID"}, ) """The unique identifier of the contact.""" - s_a_l_u_t_a_t_i_o_n: Optional[str] = field( + s_a_l_u_t_a_t_i_o_n: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SALUTATION"}, ) """The salutation of the contact.""" - f_i_r_s_t_n_a_m_e: Optional[str] = field( + f_i_r_s_t_n_a_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FIRST_NAME"}, ) """First name of the contact.""" - l_a_s_t_n_a_m_e: Optional[str] = field( + l_a_s_t_n_a_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LAST_NAME"}, ) """Last name of the contact.""" - i_m_a_g_e_u_r_l: Optional[str] = field( + i_m_a_g_e_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IMAGE_URL"}, ) """Contact image URL.""" - d_a_t_e_c_r_e_a_t_e_d_u_t_c: Optional[str] = field( + d_a_t_e_c_r_e_a_t_e_d_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DATE_CREATED_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - v_i_s_i_b_l_e_t_o: Optional[str] = field( + v_i_s_i_b_l_e_t_o: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TO"}, ) """Contact visibility.""" - b_a_c_k_g_r_o_u_n_d: Optional[str] = field( + b_a_c_k_g_r_o_u_n_d: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BACKGROUND"}, ) """Background""" - d_e_f_a_u_l_t_l_i_n_k_e_d_o_r_g_a_n_i_s_a_t_i_o_n: Optional[int] = field( + d_e_f_a_u_l_t_l_i_n_k_e_d_o_r_g_a_n_i_s_a_t_i_o_n: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DEFAULT_LINKED_ORGANISATION"}, ) """Default linked organization.""" - o_w_n_e_r_u_s_e_r_id: Optional[int] = field( + o_w_n_e_r_u_s_e_r_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OWNER_USER_ID"}, ) """The unique identifier of the owner.""" - d_a_t_e_u_p_d_a_t_e_d_u_t_c: Optional[str] = field( + d_a_t_e_u_p_d_a_t_e_d_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DATE_UPDATED_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = field( + v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TEAM_ID"}, ) """The unique identifier of the team.""" - v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = field( + v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_USER_IDS"}, ) """The unique identifiers of the users.""" - c_a_n_e_d_i_t: Optional[bool] = field( + c_a_n_e_d_i_t: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CAN_EDIT"}, ) """Can edit""" - c_a_n_d_e_l_e_t_e: Optional[bool] = field( + c_a_n_d_e_l_e_t_e: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CAN_DELETE"}, ) """Can delete""" - s_o_c_i_a_l_l_i_n_k_e_d_i_n: Optional[str] = field( + s_o_c_i_a_l_l_i_n_k_e_d_i_n: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SOCIAL_LINKEDIN"}, ) """Social LinkedIn.""" - s_o_c_i_a_l_f_a_c_e_b_o_o_k: Optional[str] = field( + s_o_c_i_a_l_f_a_c_e_b_o_o_k: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SOCIAL_FACEBOOK"}, ) """Social Facebook.""" - s_o_c_i_a_l_t_w_i_t_t_e_r: Optional[str] = field( + s_o_c_i_a_l_t_w_i_t_t_e_r: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SOCIAL_TWITTER"}, ) """Social Twitter.""" @@ -695,7 +868,12 @@ class ListUsersResponse: Response for List users """ - users: Optional[List[User]] = None + users: Optional[ + List[User | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A collection of users""" @@ -705,7 +883,7 @@ class ObjectEntity: Response for Delete task """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -718,7 +896,12 @@ class ListEventsResponse: Response for When an event is created """ - events: Optional[List[Event]] = None + events: Optional[ + List[Event | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A collection of events""" @@ -728,68 +911,83 @@ class Organization: Response for Add organization """ - o_r_g_a_n_i_s_a_t_i_o_n_id: Optional[int] = field( + o_r_g_a_n_i_s_a_t_i_o_n_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ORGANISATION_ID"}, ) """The unique identifier of the organization.""" - o_r_g_a_n_i_s_a_t_i_o_n_b_a_c_k_g_r_o_u_n_d: Optional[str] = field( + o_r_g_a_n_i_s_a_t_i_o_n_b_a_c_k_g_r_o_u_n_d: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ORGANISATION_BACKGROUND"}, ) """The background of the organization.""" - o_r_g_a_n_i_s_a_t_i_o_n_n_a_m_e: Optional[str] = field( + o_r_g_a_n_i_s_a_t_i_o_n_n_a_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ORGANISATION_NAME"}, ) """The name of the organization.""" - d_a_t_e_c_r_e_a_t_e_d_u_t_c: Optional[str] = field( + d_a_t_e_c_r_e_a_t_e_d_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DATE_CREATED_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - d_a_t_e_u_p_d_a_t_e_d_u_t_c: Optional[str] = field( + d_a_t_e_u_p_d_a_t_e_d_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DATE_UPDATED_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - o_w_n_e_r_u_s_e_r_id: Optional[int] = field( + o_w_n_e_r_u_s_e_r_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OWNER_USER_ID"}, ) """The unique identifier of the owner.""" - v_i_s_i_b_l_e_t_o: Optional[str] = field( + v_i_s_i_b_l_e_t_o: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TO"}, ) """Organization visibility.""" - a_d_d_r_e_s_s_e_s: Optional[List[Address]] = field( + a_d_d_r_e_s_s_e_s: Optional[List[Address | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADDRESSES"}, ) """Organization Addresses""" - c_o_n_t_a_c_t_i_n_f_o_s: Optional[List[ContactInfo]] = field( + c_o_n_t_a_c_t_i_n_f_o_s: Optional[ + List[ContactInfo | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONTACTINFOS"}, ) """Contact Information""" - b_a_c_k_g_r_o_u_n_d: Optional[str] = field( + b_a_c_k_g_r_o_u_n_d: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BACKGROUND"}, ) """The background of the organization.""" - i_m_a_g_e_u_r_l: Optional[str] = field( + i_m_a_g_e_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IMAGE_URL"}, ) """Organization image URL.""" - v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = field( + v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TEAM_ID"}, ) """The unique identifier of the team.""" - v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = field( + v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_USER_IDS"}, ) """The unique identifiers of the users.""" @@ -801,38 +999,33 @@ class TaskRequest: Definition: TaskRequest """ - t_i_t_l_e: Optional[str] = field( - default=None, - metadata={"wire_name": "TITLE"}, - ) + t_i_t_l_e: str = dataclass_field(metadata={"wire_name": "TITLE"}) """The title of the task.""" - d_u_e_d_a_t_e: Optional[str] = field( + d_u_e_d_a_t_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DUE_DATE"}, ) """yyyy-MM-dd HH:mm:ss""" - c_o_m_p_l_e_t_e_d: Optional[bool] = field( - default=None, + c_o_m_p_l_e_t_e_d: bool = dataclass_field( metadata={"wire_name": "COMPLETED"}, ) """A boolean value determining whether or not the task is completed.""" - d_e_t_a_i_l_s: Optional[str] = field( + d_e_t_a_i_l_s: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DETAILS"}, ) """The details of the task.""" - s_t_a_t_u_s: Optional[str] = field( - default=None, - metadata={"wire_name": "STATUS"}, - ) + s_t_a_t_u_s: str = dataclass_field(metadata={"wire_name": "STATUS"}) """The status of the task.""" - p_r_i_o_r_i_t_y: Optional[int] = field( + p_r_i_o_r_i_t_y: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PRIORITY"}, ) """The priority of the task.""" - p_u_b_l_i_c_l_y_v_i_s_i_b_l_e: Optional[bool] = field( - default=None, + p_u_b_l_i_c_l_y_v_i_s_i_b_l_e: bool = dataclass_field( metadata={"wire_name": "PUBLICLY_VISIBLE"}, ) """ @@ -846,8 +1039,9 @@ class Tag: Definition: Tag """ - t_a_g_n_a_m_e: Optional[str] = field( + t_a_g_n_a_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TAG_NAME"}, ) """The name of the tag.""" @@ -859,60 +1053,65 @@ class ProjectRequest: Definition: ProjectRequest """ - p_r_o_j_e_c_t_n_a_m_e: Optional[str] = field( - default=None, + p_r_o_j_e_c_t_n_a_m_e: str = dataclass_field( metadata={"wire_name": "PROJECT_NAME"}, ) """The name of the project.""" - p_r_o_j_e_c_t_d_e_t_a_i_l_s: Optional[str] = field( + p_r_o_j_e_c_t_d_e_t_a_i_l_s: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PROJECT_DETAILS"}, ) """The details of the project.""" - s_t_a_t_u_s: Optional[str] = field( - default=None, - metadata={"wire_name": "STATUS"}, - ) + s_t_a_t_u_s: str = dataclass_field(metadata={"wire_name": "STATUS"}) """The status of the project.""" - i_m_a_g_e_u_r_l: Optional[str] = field( + i_m_a_g_e_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IMAGE_URL"}, ) """The image URL of the project.""" - v_i_s_i_b_l_e_t_o: Optional[str] = field( + v_i_s_i_b_l_e_t_o: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TO"}, ) """Project Visibility.""" - v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = field( + v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TEAM_ID"}, ) """Visible Team Id (Required when team visibility state is selected)""" - v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = field( + v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_USER_IDS"}, ) """ Visible User IDs (Required when individuals visibility state is selected) """ - o_p_p_o_r_t_u_n_i_t_y_id: Optional[int] = field( + o_p_p_o_r_t_u_n_i_t_y_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OPPORTUNITY_ID"}, ) """The unique identifier of the opportunity.""" - p_i_p_e_l_i_n_e_id: Optional[int] = field( + p_i_p_e_l_i_n_e_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PIPELINE_ID"}, ) """The unique identifier of the pipeline.""" - s_t_a_g_e_id: Optional[int] = field( + s_t_a_g_e_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "STAGE_ID"}, ) """The unique identifier of the stage.""" - t_a_g_s: Optional[List[Tag]] = field( + t_a_g_s: Optional[List[Tag | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TAGS"}, ) """Tags""" @@ -924,105 +1123,121 @@ class LeadRequest: Definition: LeadRequest """ - t_i_t_l_e: Optional[str] = field( + t_i_t_l_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TITLE"}, ) """The title of the lead.""" - f_i_r_s_t_n_a_m_e: Optional[str] = field( + f_i_r_s_t_n_a_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FIRST_NAME"}, ) """First name of the lead.""" - l_a_s_t_n_a_m_e: Optional[str] = field( - default=None, - metadata={"wire_name": "LAST_NAME"}, - ) + l_a_s_t_n_a_m_e: str = dataclass_field(metadata={"wire_name": "LAST_NAME"}) """Last name of the lead.""" - l_e_a_d_d_e_s_c_r_i_p_t_i_o_n: Optional[str] = field( + l_e_a_d_d_e_s_c_r_i_p_t_i_o_n: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LEAD_DESCRIPTION"}, ) """A brief description of the lead.""" - c_o_n_v_e_r_t_e_d_d_a_t_e_u_t_c: Optional[str] = field( + c_o_n_v_e_r_t_e_d_d_a_t_e_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONVERTED_DATE_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - v_i_s_i_b_l_e_t_o: Optional[str] = field( + v_i_s_i_b_l_e_t_o: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TO"}, ) """Lead Visibility""" - v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = field( + v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TEAM_ID"}, ) """Visible Team Id (Required when team visibility state is selected)""" - v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = field( + v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_USER_IDS"}, ) """ Visible User IDs (Required when individuals visibility state is selected) """ - o_r_g_a_n_i_z_a_t_i_o_n_n_a_m_e: Optional[str] = field( + o_r_g_a_n_i_z_a_t_i_o_n_n_a_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ORGANIZATION_NAME"}, ) """The name of the organization.""" - p_h_o_n_e_n_u_m_b_e_r: Optional[str] = field( + p_h_o_n_e_n_u_m_b_e_r: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PHONE_NUMBER"}, ) """Lead phone number.""" - m_o_b_i_l_e_p_h_o_n_e_n_u_m_b_e_r: Optional[str] = field( + m_o_b_i_l_e_p_h_o_n_e_n_u_m_b_e_r: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MOBILE_PHONE_NUMBER"}, ) """Lead mobile phone number.""" - e_m_a_i_l_a_d_d_r_e_s_s: Optional[str] = field( + e_m_a_i_l_a_d_d_r_e_s_s: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EMAIL_ADDRESS"}, ) """Lead email address.""" - c_o_n_v_e_r_t_e_d: Optional[bool] = field( + c_o_n_v_e_r_t_e_d: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONVERTED"}, ) """A boolean value determining whether or not the lead is converted.""" - w_e_b_s_i_t_e_u_r_l: Optional[str] = field( + w_e_b_s_i_t_e_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WEBSITE_URL"}, ) """Lead website URL""" - o_w_n_e_r_u_s_e_r_id: Optional[int] = field( + o_w_n_e_r_u_s_e_r_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OWNER_USER_ID"}, ) """The unique identifier of the lead owner.""" - r_e_s_p_o_n_s_i_b_l_e_u_s_e_r_id: Optional[int] = field( + r_e_s_p_o_n_s_i_b_l_e_u_s_e_r_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RESPONSIBLE_USER_ID"}, ) """The unique identifier of the responsible user.""" - e_m_p_l_o_y_e_e_c_o_u_n_t: Optional[int] = field( + e_m_p_l_o_y_e_e_c_o_u_n_t: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EMPLOYEE_COUNT"}, ) """The employee count of the lead.""" - l_e_a_d_r_a_t_i_n_g: Optional[int] = field( + l_e_a_d_r_a_t_i_n_g: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LEAD_RATING"}, ) """The rating of the lead.""" - i_n_d_u_s_t_r_y: Optional[str] = field( + i_n_d_u_s_t_r_y: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "INDUSTRY"}, ) """The industry of the lead.""" - t_a_g_s: Optional[List[Tag]] = field( + t_a_g_s: Optional[List[Tag | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TAGS"}, ) """Tag""" @@ -1034,38 +1249,45 @@ class Address: Definition: Address """ - a_d_d_r_e_s_s_id: Optional[int] = field( + a_d_d_r_e_s_s_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADDRESS_ID"}, ) """The unique identifier of the address.""" - a_d_d_r_e_s_s_t_y_p_e: Optional[str] = field( + a_d_d_r_e_s_s_t_y_p_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADDRESS_TYPE"}, ) """Address type.""" - s_t_r_e_e_t: Optional[str] = field( + s_t_r_e_e_t: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "STREET"}, ) """Address street.""" - c_i_t_y: Optional[str] = field( + c_i_t_y: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CITY"}, ) """Address city.""" - s_t_a_t_e: Optional[str] = field( + s_t_a_t_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "STATE"}, ) """Address state.""" - p_o_s_t_c_o_d_e: Optional[str] = field( + p_o_s_t_c_o_d_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "POSTCODE"}, ) """Address postcode.""" - c_o_u_n_t_r_y: Optional[str] = field( + c_o_u_n_t_r_y: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "COUNTRY"}, ) """Address country.""" @@ -1077,28 +1299,33 @@ class ContactInfo: Definition: ContactInfo """ - c_o_n_t_a_c_t_i_n_f_o_id: Optional[int] = field( + c_o_n_t_a_c_t_i_n_f_o_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONTACT_INFO_ID"}, ) """The unique identifier of the contact info.""" - t_y_p_e: Optional[str] = field( + t_y_p_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TYPE"}, ) """Contact info type.""" - s_u_b_t_y_p_e: Optional[str] = field( + s_u_b_t_y_p_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SUBTYPE"}, ) """Contact info sub-type.""" - l_a_b_e_l: Optional[str] = field( + l_a_b_e_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LABEL"}, ) """Contact info label.""" - d_e_t_a_i_l: Optional[str] = field( + d_e_t_a_i_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DETAIL"}, ) """Contact info detail.""" @@ -1110,50 +1337,55 @@ class ContactRequest: Definition: ContactRequest """ - s_a_l_u_t_a_t_i_o_n: Optional[str] = field( + s_a_l_u_t_a_t_i_o_n: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SALUTATION"}, ) """The salutation of the contact.""" - f_i_r_s_t_n_a_m_e: Optional[str] = field( - default=None, + f_i_r_s_t_n_a_m_e: str = dataclass_field( metadata={"wire_name": "FIRST_NAME"}, ) """First name of the contact.""" - l_a_s_t_n_a_m_e: Optional[str] = field( - default=None, - metadata={"wire_name": "LAST_NAME"}, - ) + l_a_s_t_n_a_m_e: str = dataclass_field(metadata={"wire_name": "LAST_NAME"}) """Last name of the lead.""" - b_a_c_k_g_r_o_u_n_d: Optional[str] = field( + b_a_c_k_g_r_o_u_n_d: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BACKGROUND"}, ) """Background""" - v_i_s_i_b_l_e_t_o: Optional[str] = field( + v_i_s_i_b_l_e_t_o: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TO"}, ) """Contact Visibility""" - v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = field( + v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TEAM_ID"}, ) """Visible Team Id (Required when team visibility state is selected)""" - v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = field( + v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_USER_IDS"}, ) """ Visible User IDs (Required when individuals visibility state is selected) """ - c_o_n_t_a_c_t_i_n_f_o_s: Optional[List[ContactInfo]] = field( + c_o_n_t_a_c_t_i_n_f_o_s: Optional[ + List[ContactInfo | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONTACTINFOS"}, ) """Contact Information""" - t_a_g_s: Optional[List[Tag]] = field( + t_a_g_s: Optional[List[Tag | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TAGS"}, ) """Tag""" @@ -1165,97 +1397,115 @@ class User: Definition: User """ - u_s_e_r_id: Optional[int] = field( + u_s_e_r_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "USER_ID"}, ) """The unique identifier of the user.""" - c_o_n_t_a_c_t_id: Optional[int] = field( + c_o_n_t_a_c_t_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONTACT_ID"}, ) """The unique identifier of the contact.""" - f_i_r_s_t_n_a_m_e: Optional[str] = field( + f_i_r_s_t_n_a_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FIRST_NAME"}, ) """First name of the user.""" - l_a_s_t_n_a_m_e: Optional[str] = field( + l_a_s_t_n_a_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LAST_NAME"}, ) """Last name of the user.""" - e_m_a_i_l_a_d_d_r_e_s_s: Optional[str] = field( + e_m_a_i_l_a_d_d_r_e_s_s: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EMAIL_ADDRESS"}, ) """User email address.""" - t_i_m_e_z_o_n_e_id: Optional[str] = field( + t_i_m_e_z_o_n_e_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TIMEZONE_ID"}, ) """The unique identifier of the timezone.""" - e_m_a_i_l_d_r_o_p_b_o_x_id_e_n_t_i_f_i_e_r: Optional[str] = field( + e_m_a_i_l_d_r_o_p_b_o_x_id_e_n_t_i_f_i_e_r: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EMAIL_DROPBOX_IDENTIFIER"}, ) """The unique identifier of the email dropbox.""" - e_m_a_i_l_d_r_o_p_b_o_x_a_d_d_r_e_s_s: Optional[str] = field( + e_m_a_i_l_d_r_o_p_b_o_x_a_d_d_r_e_s_s: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EMAIL_DROPBOX_ADDRESS"}, ) """Email dropbox address""" - a_d_m_i_n_i_s_t_r_a_t_o_r: Optional[bool] = field( + a_d_m_i_n_i_s_t_r_a_t_o_r: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADMINISTRATOR"}, ) """ A boolean value determining whether or not the user is an administrator. """ - a_c_c_o_u_n_t_o_w_n_e_r: Optional[bool] = field( + a_c_c_o_u_n_t_o_w_n_e_r: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ACCOUNT_OWNER"}, ) """ A boolean value determining whether or not the user is the account owner. """ - a_c_t_i_v_e: Optional[bool] = field( + a_c_t_i_v_e: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ACTIVE"}, ) """A boolean value determining whether or not the user is active.""" - d_a_t_e_c_r_e_a_t_e_d_u_t_c: Optional[str] = field( + d_a_t_e_c_r_e_a_t_e_d_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DATE_CREATED_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - d_a_t_e_u_p_d_a_t_e_d_u_t_c: Optional[str] = field( + d_a_t_e_u_p_d_a_t_e_d_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DATE_UPDATED_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - u_s_e_r_c_u_r_r_e_n_c_y: Optional[str] = field( + u_s_e_r_c_u_r_r_e_n_c_y: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "USER_CURRENCY"}, ) """User currency.""" - c_o_n_t_a_c_t_d_i_s_p_l_a_y: Optional[str] = field( + c_o_n_t_a_c_t_d_i_s_p_l_a_y: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONTACT_DISPLAY"}, ) """Contact display.""" - c_o_n_t_a_c_t_o_r_d_e_r: Optional[str] = field( + c_o_n_t_a_c_t_o_r_d_e_r: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONTACT_ORDER"}, ) """Contact order.""" - t_a_s_k_w_e_e_k_s_t_a_r_t: Optional[int] = field( + t_a_s_k_w_e_e_k_s_t_a_r_t: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TASK_WEEK_START"}, ) """Task week start.""" - i_n_s_t_a_n_c_e_id: Optional[int] = field( + i_n_s_t_a_n_c_e_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "INSTANCE_ID"}, ) """The unique identifier of the instance.""" @@ -1267,65 +1517,77 @@ class Event: Definition: Event """ - e_v_e_n_t_id: Optional[int] = field( + e_v_e_n_t_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EVENT_ID"}, ) """The unique identifier of the event.""" - t_i_t_l_e: Optional[str] = field( + t_i_t_l_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TITLE"}, ) """The title of the event.""" - s_t_a_r_t_d_a_t_e_u_t_c: Optional[str] = field( + s_t_a_r_t_d_a_t_e_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "START_DATE_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - e_n_d_d_a_t_e_u_t_c: Optional[str] = field( + e_n_d_d_a_t_e_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "END_DATE_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - d_a_t_e_c_r_e_a_t_e_d_u_t_c: Optional[str] = field( + d_a_t_e_c_r_e_a_t_e_d_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DATE_CREATED_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - d_a_t_e_u_p_d_a_t_e_d_u_t_c: Optional[str] = field( + d_a_t_e_u_p_d_a_t_e_d_u_t_c: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DATE_UPDATED_UTC"}, ) """yyyy-MM-dd HH:mm:ss""" - o_w_n_e_r_u_s_e_r_id: Optional[int] = field( + o_w_n_e_r_u_s_e_r_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OWNER_USER_ID"}, ) """The unique identifier of the owner.""" - r_e_m_i_n_d_e_r_s_e_n_t: Optional[bool] = field( + r_e_m_i_n_d_e_r_s_e_n_t: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "REMINDER_SENT"}, ) """A boolean value determining whether or not the reminder was sent.""" - a_l_l_d_a_y: Optional[bool] = field( + a_l_l_d_a_y: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ALL_DAY"}, ) """A boolean value determining whether or not the event is all day.""" - p_u_b_l_i_c_l_y_v_i_s_i_b_l_e: Optional[bool] = field( + p_u_b_l_i_c_l_y_v_i_s_i_b_l_e: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PUBLICLY_VISIBLE"}, ) """ A boolean value determining whether or not the event is publicly visible. """ - c_a_n_e_d_i_t: Optional[bool] = field( + c_a_n_e_d_i_t: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CAN_EDIT"}, ) """Can edit""" - c_a_n_d_e_l_e_t_e: Optional[bool] = field( + c_a_n_d_e_l_e_t_e: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CAN_DELETE"}, ) """Can delete""" @@ -1337,45 +1599,53 @@ class OrganizationRequest: Definition: OrganizationRequest """ - o_r_g_a_n_i_s_a_t_i_o_n_n_a_m_e: Optional[str] = field( - default=None, + o_r_g_a_n_i_s_a_t_i_o_n_n_a_m_e: str = dataclass_field( metadata={"wire_name": "ORGANISATION_NAME"}, ) """The name of the organization.""" - o_r_g_a_n_i_s_a_t_i_o_n_b_a_c_k_g_r_o_u_n_d: Optional[str] = field( + o_r_g_a_n_i_s_a_t_i_o_n_b_a_c_k_g_r_o_u_n_d: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ORGANISATION_BACKGROUND"}, ) """The background of the organization.""" - v_i_s_i_b_l_e_t_o: Optional[str] = field( + v_i_s_i_b_l_e_t_o: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TO"}, ) """Organization visibility.""" - v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = field( + v_i_s_i_b_l_e_t_e_a_m_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_TEAM_ID"}, ) """Visible Team Id (Required when team visibility state is selected)""" - v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = field( + v_i_s_i_b_l_e_u_s_e_r_id_s: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VISIBLE_USER_IDS"}, ) """ Visible User IDs (Required when individuals visibility state is selected) """ - a_d_d_r_e_s_s_e_s: Optional[List[Address]] = field( + a_d_d_r_e_s_s_e_s: Optional[List[Address | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ADDRESSES"}, ) """Organization Addresses""" - c_o_n_t_a_c_t_i_n_f_o_s: Optional[List[ContactInfo]] = field( + c_o_n_t_a_c_t_i_n_f_o_s: Optional[ + List[ContactInfo | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CONTACTINFOS"}, ) """Contact Information""" - t_a_g_s: Optional[List[Tag]] = field( + t_a_g_s: Optional[List[Tag | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TAGS"}, ) """Tags""" @@ -1389,16 +1659,16 @@ class InsightlyClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -1409,8 +1679,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -1418,8 +1688,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -1431,7 +1701,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -1446,45 +1716,123 @@ def __init__( def connector_name(self) -> str: return "insightly" - async def list_tasks_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_tasks( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List tasks List tasks + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTasks`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Tasks" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("tasks", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def update_task_async( + def update_task( self, - input: TaskRequest, + input: TaskRequest | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -1496,6 +1844,23 @@ async def update_task_async( Update task Update task + + Swagger operation ID: `UpdateTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique Id of the task to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Tasks" query_params = [] @@ -1506,7 +1871,7 @@ async def update_task_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1520,6 +1885,7 @@ async def update_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1527,9 +1893,9 @@ async def update_task_async( return json.loads(response.text) - async def add_task_async( + def add_task( self, - input: TaskRequest, + input: TaskRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1540,10 +1906,26 @@ async def add_task_async( Add task Add task + + Swagger operation ID: `AddTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Tasks" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1557,6 +1939,7 @@ async def add_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1564,45 +1947,90 @@ async def add_task_async( return json.loads(response.text) - async def list_projects_async( + def list_projects( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List projects List projects + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListProjects`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Projects" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextLink") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None ) - if not response.text: - return None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("projects", []): + yield item - return json.loads(response.text) + return continuation_token, items() + + return ItemPaged(get_next, extract_data) - async def update_project_async( + def update_project( self, - input: ProjectRequest, + input: ProjectRequest | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -1614,6 +2042,23 @@ async def update_project_async( Update project Update project + + Swagger operation ID: `UpdateProject`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique Id of the project to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Projects" query_params = [] @@ -1624,7 +2069,7 @@ async def update_project_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1638,6 +2083,7 @@ async def update_project_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1645,9 +2091,9 @@ async def update_project_async( return json.loads(response.text) - async def add_project_async( + def add_project( self, - input: ProjectRequest, + input: ProjectRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1658,10 +2104,26 @@ async def add_project_async( Add project Add project + + Swagger operation ID: `AddProject`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Projects" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1675,6 +2137,7 @@ async def add_project_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1682,45 +2145,84 @@ async def add_project_async( return json.loads(response.text) - async def list_leads_async( + def list_leads( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List leads List leads + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListLeads`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Leads" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("leads", []): + yield item + + return None, items() - async def update_lead_async( + return ItemPaged(get_next, extract_data) + + def update_lead( self, - input: LeadRequest, + input: LeadRequest | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -1732,6 +2234,23 @@ async def update_lead_async( Update lead Update lead + + Swagger operation ID: `UpdateLead`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique Id of the lead to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Leads" query_params = [] @@ -1742,7 +2261,7 @@ async def update_lead_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1756,6 +2275,7 @@ async def update_lead_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1763,9 +2283,9 @@ async def update_lead_async( return json.loads(response.text) - async def add_lead_async( + def add_lead( self, - input: LeadRequest, + input: LeadRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1776,10 +2296,26 @@ async def add_lead_async( Add lead Add lead + + Swagger operation ID: `AddLead`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Leads" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1793,6 +2329,7 @@ async def add_lead_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1800,45 +2337,84 @@ async def add_lead_async( return json.loads(response.text) - async def list_contacts_async( + def list_contacts( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List contacts List contacts + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListContacts`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Contacts" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("contacts", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def update_contact_async( + def update_contact( self, - input: ContactRequest, + input: ContactRequest | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -1850,6 +2426,23 @@ async def update_contact_async( Update contact Update contact + + Swagger operation ID: `UpdateContact`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Unique Id of the contact to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Contacts" query_params = [] @@ -1860,7 +2453,7 @@ async def update_contact_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1874,6 +2467,7 @@ async def update_contact_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1881,9 +2475,9 @@ async def update_contact_async( return json.loads(response.text) - async def add_contact_async( + def add_contact( self, - input: ContactRequest, + input: ContactRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1894,10 +2488,26 @@ async def add_contact_async( Add contact Add contact + + Swagger operation ID: `AddContact`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Contacts" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1911,6 +2521,7 @@ async def add_contact_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1918,43 +2529,82 @@ async def add_contact_async( return json.loads(response.text) - async def list_users_async( + def list_users( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List users List users + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListUsers`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Users" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("users", []): + yield item + + return None, items() - async def delete_task_async( + return ItemPaged(get_next, extract_data) + + def delete_task( self, task_id: int, *, @@ -1967,13 +2617,28 @@ async def delete_task_async( Delete task Delete task + + Swagger operation ID: `DeleteTask`. + + Args: + task_id: Task Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/Tasks/{quote(str(task_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1987,6 +2652,7 @@ async def delete_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1994,7 +2660,7 @@ async def delete_task_async( return json.loads(response.text) - async def follow_task_async( + def follow_task( self, task_id: int, *, @@ -2007,13 +2673,28 @@ async def follow_task_async( Follow a task Follow a task + + Swagger operation ID: `FollowTask`. + + Args: + task_id: Task Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/Tasks/{quote(str(task_id), safe='')}/Follow" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -2027,6 +2708,7 @@ async def follow_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2034,7 +2716,7 @@ async def follow_task_async( return json.loads(response.text) - async def delete_project_async( + def delete_project( self, project_id: int, *, @@ -2047,13 +2729,28 @@ async def delete_project_async( Delete project Delete project + + Swagger operation ID: `DeleteProject`. + + Args: + project_id: Project Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/Projects/{quote(str(project_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2067,6 +2764,7 @@ async def delete_project_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2074,7 +2772,7 @@ async def delete_project_async( return json.loads(response.text) - async def delete_lead_async( + def delete_lead( self, lead_id: int, *, @@ -2087,13 +2785,28 @@ async def delete_lead_async( Delete lead Delete lead + + Swagger operation ID: `DeleteLead`. + + Args: + lead_id: Lead Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/Leads/{quote(str(lead_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2107,6 +2820,7 @@ async def delete_lead_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2114,7 +2828,7 @@ async def delete_lead_async( return json.loads(response.text) - async def delete_contact_async( + def delete_contact( self, contact_id: int, *, @@ -2127,13 +2841,28 @@ async def delete_contact_async( Delete contact Delete contact + + Swagger operation ID: `DeleteContact`. + + Args: + contact_id: Contact Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/Contacts/{quote(str(contact_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2147,6 +2876,7 @@ async def delete_contact_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2154,9 +2884,9 @@ async def delete_contact_async( return json.loads(response.text) - async def add_organization_async( + def add_organization( self, - input: OrganizationRequest, + input: OrganizationRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -2167,10 +2897,26 @@ async def add_organization_async( Add organization Add organization + + Swagger operation ID: `AddOrganization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Organisations" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2184,6 +2930,7 @@ async def add_organization_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/jedoxodatahub.py b/src/azure/connectors/jedoxodatahub.py index 24f32da..6e5d9b9 100644 --- a/src/azure/connectors/jedoxodatahub.py +++ b/src/azure/connectors/jedoxodatahub.py @@ -5,21 +5,71 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "JedoxodatahubClient", + "Cell", + "CellArray", + "Cube", + "CubeArray", + "CubeCellsResponse", + "CubesResponse", + "Database", + "DatabaseArray", + "DatabasesResponse", + "Dimension", + "DimensionArray", + "DimensionsResponse", + "Element", + "ElementArray", + "ElementsResponse", + "Error", + "ExtractRowsResponse", + "ExtractsResponse", + "GetCubeCellResultSchemaResponse", + "GetExtractRowsResultSchemaResponse", + "GetTransformRowsResultSchemaResponse", + "GetViewCellResultSchemaResponse", + "IntegratorComponent", + "IntegratorComponentArray", + "IntegratorExtractComponentRow", + "IntegratorExtractComponentRowArray", + "IntegratorProject", + "IntegratorProjectArray", + "IntegratorProjectGroup", + "IntegratorProjectGroupArray", + "IntegratorProjectGroupsResponse", + "IntegratorProjectsResponse", + "IntegratorRunResult", + "IntegratorTransformComponentRow", + "IntegratorTransformComponentRowArray", + "JobsResponse", + "LoadsResponse", + "TransformRowsResponse", + "TransformsResponse", + "View", + "ViewArray", + "ViewCell", + "ViewCellArray", + "ViewCellsResponse", + "ViewsResponse", +] + # Type Definitions @@ -29,7 +79,7 @@ class DatabasesResponse: Response for Get databases """ - value: Optional[DatabaseArray] = None + value: Optional[DatabaseArray] = dataclass_field(default=None, kw_only=True) @dataclass @@ -38,17 +88,31 @@ class Database: Response for Get database by id """ - cube_count: Optional[int] = field( + cube_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CubeCount"}, ) - dimension_count: Optional[int] = field( + dimension_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DimensionCount"}, ) - id: Optional[int] = field(default=None, metadata={"wire_name": "Id"}) - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) + id: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Type"}, + ) @dataclass @@ -57,7 +121,7 @@ class CubesResponse: Response for Get cubes """ - value: Optional[CubeArray] = None + value: Optional[CubeArray] = dataclass_field(default=None, kw_only=True) @dataclass @@ -66,13 +130,26 @@ class Cube: Response for Get cube by ID """ - filled_cell_count: Optional[int] = field( + filled_cell_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FilledCellCount"}, ) - id: Optional[int] = field(default=None, metadata={"wire_name": "Id"}) - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) + id: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Type"}, + ) @dataclass @@ -81,7 +158,7 @@ class CubeCellsResponse: Response for Get cube cells """ - value: Optional[CellArray] = None + value: Optional[CellArray] = dataclass_field(default=None, kw_only=True) @dataclass @@ -90,7 +167,7 @@ class DimensionsResponse: Response for Get dimensions """ - value: Optional[DimensionArray] = None + value: Optional[DimensionArray] = dataclass_field(default=None, kw_only=True) @dataclass @@ -99,13 +176,26 @@ class Dimension: Response for Get dimension by ID """ - element_count: Optional[int] = field( + element_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ElementCount"}, ) - id: Optional[int] = field(default=None, metadata={"wire_name": "Id"}) - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) + id: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Type"}, + ) @dataclass @@ -114,7 +204,7 @@ class ElementsResponse: Response for Get elements """ - value: Optional[ElementArray] = None + value: Optional[ElementArray] = dataclass_field(default=None, kw_only=True) @dataclass @@ -123,15 +213,29 @@ class Element: Response for Get element by ID """ - id: Optional[int] = field(default=None, metadata={"wire_name": "Id"}) - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) - position: Optional[int] = field( + id: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) + position: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Position"}, ) - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) - weight: Optional[float] = field( + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Type"}, + ) + weight: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Weight"}, ) @@ -142,7 +246,7 @@ class ViewsResponse: Response for Get stored views """ - value: Optional[ViewArray] = None + value: Optional[ViewArray] = dataclass_field(default=None, kw_only=True) @dataclass @@ -151,33 +255,44 @@ class View: Response for Get stored view by ID """ - creation_date: Optional[str] = field( + creation_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CreationDate"}, ) - cube_id: Optional[int] = field( + cube_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CubeId"}, ) - cube_name: Optional[str] = field( + cube_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CubeName"}, ) - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) - friendly_name: Optional[str] = field( + friendly_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FriendlyName"}, ) - global_: Optional[bool] = field( + global_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Global"}, ) - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) - user_name: Optional[str] = field( + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) + user_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UserName"}, ) @@ -188,7 +303,7 @@ class ViewCellsResponse: Response for Get stored view cells """ - value: Optional[ViewCellArray] = None + value: Optional[ViewCellArray] = dataclass_field(default=None, kw_only=True) @dataclass @@ -197,7 +312,7 @@ class IntegratorProjectGroupsResponse: Response for Get Integrator project groups """ - value: Optional[IntegratorProjectGroupArray] = None + value: Optional[IntegratorProjectGroupArray] = dataclass_field(default=None, kw_only=True) @dataclass @@ -206,26 +321,39 @@ class IntegratorProjectGroup: Response for Get Integrator project group by identifier """ - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) - developer: Optional[str] = field( + developer: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Developer"}, ) - friendly_name: Optional[str] = field( + friendly_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FriendlyName"}, ) - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) - namespace: Optional[str] = field( + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) + namespace: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Namespace"}, ) - version: Optional[str] = field( + version: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Version"}, ) @@ -236,7 +364,7 @@ class IntegratorProjectsResponse: Response for Get Integrator projects """ - value: Optional[IntegratorProjectArray] = None + value: Optional[IntegratorProjectArray] = dataclass_field(default=None, kw_only=True) @dataclass @@ -245,17 +373,24 @@ class IntegratorProject: Response for Get Integrator project by name """ - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) - modification_date: Optional[str] = field( + modification_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ModificationDate"}, ) - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) - version: Optional[str] = field( + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) + version: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Version"}, ) @@ -266,7 +401,7 @@ class ExtractsResponse: Response for Get extracts """ - value: Optional[IntegratorComponentArray] = None + value: Optional[IntegratorComponentArray] = dataclass_field(default=None, kw_only=True) @dataclass @@ -275,16 +410,26 @@ class IntegratorComponent: Response for Get extract by Name """ - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) - modification_date: Optional[str] = field( + modification_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ModificationDate"}, ) - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Type"}, + ) @dataclass @@ -293,7 +438,12 @@ class ExtractRowsResponse: Response for Get extract rows """ - value: Optional[IntegratorExtractComponentRowArray] = None + value: Optional[ + IntegratorExtractComponentRowArray + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -302,7 +452,7 @@ class JobsResponse: Response for Get jobs """ - value: Optional[IntegratorComponentArray] = None + value: Optional[IntegratorComponentArray] = dataclass_field(default=None, kw_only=True) @dataclass @@ -311,22 +461,25 @@ class IntegratorRunResult: Response for Run job """ - errors: Optional[int] = None - execution_type: Optional[str] = field( + errors: Optional[int] = dataclass_field(default=None, kw_only=True) + execution_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "executionType"}, ) - id: Optional[int] = None - start_date: Optional[str] = field( + id: Optional[int] = dataclass_field(default=None, kw_only=True) + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) - status: Optional[str] = None - trace_available: Optional[bool] = field( + status: Optional[str] = dataclass_field(default=None, kw_only=True) + trace_available: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "traceAvailable"}, ) - warnings: Optional[int] = None + warnings: Optional[int] = dataclass_field(default=None, kw_only=True) @dataclass @@ -335,7 +488,7 @@ class LoadsResponse: Response for Get loads """ - value: Optional[IntegratorComponentArray] = None + value: Optional[IntegratorComponentArray] = dataclass_field(default=None, kw_only=True) @dataclass @@ -344,7 +497,7 @@ class TransformsResponse: Response for Get transforms """ - value: Optional[IntegratorComponentArray] = None + value: Optional[IntegratorComponentArray] = dataclass_field(default=None, kw_only=True) @dataclass @@ -353,7 +506,12 @@ class TransformRowsResponse: Response for Get transform Rows """ - value: Optional[IntegratorTransformComponentRowArray] = None + value: Optional[ + IntegratorTransformComponentRowArray + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -362,7 +520,7 @@ class GetCubeCellResultSchemaResponse: Response for Get Cube Cell Result Schema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -375,7 +533,7 @@ class GetExtractRowsResultSchemaResponse: Response for Get Extract Rows Result Schema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -388,7 +546,7 @@ class GetTransformRowsResultSchemaResponse: Response for Get Transform Rows Result Schema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -401,7 +559,7 @@ class GetViewCellResultSchemaResponse: Response for Get View Cell Result Schema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -414,26 +572,26 @@ class Cell: Definition: Cell """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) """ -CellArray = List["Cell"] +CellArray = List["Cell | Mapping[str, Any]"] -CubeArray = List["Cube"] +CubeArray = List["Cube | Mapping[str, Any]"] -DatabaseArray = List["Database"] +DatabaseArray = List["Database | Mapping[str, Any]"] -DimensionArray = List["Dimension"] +DimensionArray = List["Dimension | Mapping[str, Any]"] -ElementArray = List["Element"] +ElementArray = List["Element | Mapping[str, Any]"] @dataclass @@ -442,10 +600,10 @@ class Error: Definition: Error """ - error: Optional[str] = None + error: Optional[str] = dataclass_field(default=None, kw_only=True) -IntegratorComponentArray = List["IntegratorComponent"] +IntegratorComponentArray = List["IntegratorComponent | Mapping[str, Any]"] @dataclass @@ -454,20 +612,20 @@ class IntegratorExtractComponentRow: Definition: IntegratorExtractComponentRow """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) """ -IntegratorExtractComponentRowArray = List["IntegratorExtractComponentRow"] +IntegratorExtractComponentRowArray = List["IntegratorExtractComponentRow | Mapping[str, Any]"] -IntegratorProjectArray = List["IntegratorProject"] +IntegratorProjectArray = List["IntegratorProject | Mapping[str, Any]"] -IntegratorProjectGroupArray = List["IntegratorProjectGroup"] +IntegratorProjectGroupArray = List["IntegratorProjectGroup | Mapping[str, Any]"] @dataclass @@ -476,17 +634,19 @@ class IntegratorTransformComponentRow: Definition: IntegratorTransformComponentRow """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) """ -IntegratorTransformComponentRowArray = List["IntegratorTransformComponentRow"] +IntegratorTransformComponentRowArray = List[ + "IntegratorTransformComponentRow | Mapping[str, Any]" +] -ViewArray = List["View"] +ViewArray = List["View | Mapping[str, Any]"] @dataclass @@ -495,14 +655,14 @@ class ViewCell: Definition: ViewCell """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) """ -ViewCellArray = List["ViewCell"] +ViewCellArray = List["ViewCell | Mapping[str, Any]"] # Client Class @@ -513,16 +673,16 @@ class JedoxodatahubClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -533,8 +693,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -542,8 +702,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -555,7 +715,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -570,23 +730,89 @@ def __init__( def connector_name(self) -> str: return "jedoxodatahub" - async def databases_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_databases( self, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get databases Get a list of databases found in the server. System and config databases are excluded from the list, but can be requested by providing the ID. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Databases`. + + Args: + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Databases" query_params = [] @@ -607,29 +833,50 @@ async def databases_async( query_params.append(f"$filter={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def database_by_id_async( + return ItemPaged(get_next, extract_data) + + def database_by_id( self, database_id: int, *, @@ -642,13 +889,28 @@ async def database_by_id_async( Get database by id Get the database with the given ID. + + Swagger operation ID: `DatabaseById`. + + Args: + database_id: Numeric ID of the database. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/Databases({quote(str(database_id), safe='')})" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -662,6 +924,7 @@ async def database_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -669,24 +932,52 @@ async def database_by_id_async( return json.loads(response.text) - async def cubes_async( + def list_cubes( self, database_id: int, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get cubes Get a list of cubes in the given database. To prevent issues with the URL encodings, Attribute cubes will be renamed, e.g. \\#_Years to ATT_Years. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Cubes`. + + Args: + database_id: Numeric ID of the database. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -710,29 +1001,50 @@ async def cubes_async( query_params.append(f"$filter={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def cube_by_id_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def cube_by_id( self, database_id: int, cube_id: int, @@ -748,6 +1060,22 @@ async def cube_by_id_async( Get the cube with the given ID in the given database. To prevent issues with the URL encodings, Attribute cubes will be renamed, e.g. \\#_Years to ATT_Years. + + Swagger operation ID: `CubeById`. + + Args: + database_id: Numeric ID of the database. + cube_id: Numeric ID of the cube. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -755,7 +1083,7 @@ async def cube_by_id_async( f"/Cubes({quote(str(cube_id), safe='')})" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -769,6 +1097,7 @@ async def cube_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -776,10 +1105,11 @@ async def cube_by_id_async( return json.loads(response.text) - async def cube_cells_async( + def list_cube_cells( self, database_id: int, cube_id: int, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, @@ -787,18 +1117,60 @@ async def cube_cells_async( userules: Optional[bool] = None, zerosupression: Optional[bool] = None, disablepaging: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get cube cells Get the cells from a cube. This returns the cells' values and element names. If the cell has a string value, the value is instead stored in the stringValue field. Element names are stored in dynamic properties. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `CubeCells`. + + Args: + database_id: Numeric ID of the database. + cube_id: Numeric ID of the cube. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + > Currently the /Cells functions only support basic operations. + Complex formulas might return an invalid result. For complex + filtering, please use Views. + baseonly: If set to true, the result will only contain base + elements. If set to false, it will also contain consolidated + elements. + userules: If set to true, rules will be applied to the resulting + cells. + zerosupression: If set to true, numeric cells with a value of 0 and + empty string cells will be removed from the result. + disablepaging: If set to true, the service will return the entire + result instead of a single page. With this option set to true, + the response might take multiple minutes depending on the + cube's size. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -844,44 +1216,93 @@ async def cube_cells_async( query_params.append(f"disablepaging={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def dimensions_async( + return ItemPaged(get_next, extract_data) + + def list_dimensions( self, database_id: int, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get dimensions Get a list of dimensions in the given database. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Dimensions`. + + Args: + database_id: Numeric ID of the database. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -905,29 +1326,50 @@ async def dimensions_async( query_params.append(f"$filter={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def dimension_by_id_async( + return ItemPaged(get_next, extract_data) + + def dimension_by_id( self, database_id: int, dimension_id: int, @@ -941,6 +1383,22 @@ async def dimension_by_id_async( Get dimension by ID Get the dimension with the given ID in the given database. + + Swagger operation ID: `DimensionById`. + + Args: + database_id: Numeric ID of the database. + dimension_id: Numeric ID of the dimension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -948,7 +1406,7 @@ async def dimension_by_id_async( f"/Dimensions({quote(str(dimension_id), safe='')})" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -962,6 +1420,7 @@ async def dimension_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -969,23 +1428,52 @@ async def dimension_by_id_async( return json.loads(response.text) - async def elements_async( + def list_elements( self, database_id: int, dimension_id: int, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get elements Get a list of elements in the given dimension. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Elements`. + + Args: + database_id: Numeric ID of the database. + dimension_id: Numeric ID of the dimension. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1011,29 +1499,50 @@ async def elements_async( query_params.append(f"$filter={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def element_by_id_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def element_by_id( self, database_id: int, dimension_id: int, @@ -1048,6 +1557,23 @@ async def element_by_id_async( Get element by ID Returns the element with the given ID in the given dimension. + + Swagger operation ID: `ElementById`. + + Args: + database_id: Numeric ID of the database. + dimension_id: Numeric ID of the dimension. + element_id: Numeric ID of the element. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1056,7 +1582,7 @@ async def element_by_id_async( f"/Elements({quote(str(element_id), safe='')})" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1070,6 +1596,7 @@ async def element_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1077,22 +1604,50 @@ async def element_by_id_async( return json.loads(response.text) - async def views_async( + def list_views( self, database_id: int, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get stored views Get a list of stored views in the given database. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Views`. + + Args: + database_id: Numeric ID of the database. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1116,29 +1671,50 @@ async def views_async( query_params.append(f"$filter={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def view_by_id_async( + return ItemPaged(get_next, extract_data) + + def view_by_id( self, database_id: int, view_id: str, @@ -1152,6 +1728,22 @@ async def view_by_id_async( Get stored view by ID Get the view with the given ID in the given database. + + Swagger operation ID: `ViewById`. + + Args: + database_id: Numeric ID of the database. + view_id: UUID of the view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1159,7 +1751,7 @@ async def view_by_id_async( f"/Views({quote(str(view_id), safe='')})" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1173,6 +1765,7 @@ async def view_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1180,10 +1773,11 @@ async def view_by_id_async( return json.loads(response.text) - async def view_cells_async( + def list_view_cells( self, database_id: int, view_id: str, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, @@ -1191,18 +1785,59 @@ async def view_cells_async( userules: Optional[bool] = None, zerosupression: Optional[bool] = None, disablepaging: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get stored view cells Get all cells from a view. This returns the cells' values and element names. If the cell has a string value, the value is instead stored in the stringValue field. Element names are stored in dynamic properties. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ViewCells`. + + Args: + database_id: Numeric ID of the database. + view_id: UUID of the view. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + > Currently the /Cells functions only support basic operations. + Complex formulas might return an invalid result. + baseonly: If set to true, the result will only contain base + elements. If set to false, it will also contain consolidated + elements. + userules: If set to true, rules will be applied to the resulting + cells. + zerosupression: If set to true, numeric cells with a value of 0 and + empty string cells will be removed from the result. + disablepaging: If set to true, the service will return the entire + result instead of a single page. With this option set to true, + the response might take multiple minutes depending on the + view's size. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1248,44 +1883,92 @@ async def view_cells_async( query_params.append(f"disablepaging={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def integrator_project_groups_async( + def list_integrator_project_groups( self, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Integrator project groups Get a list of integrator project groups found in the server. - """ + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `IntegratorProjectGroups`. + + Args: + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. + """ request_url = f"{self._connection_runtime_url}/Integrator" query_params = [] if top is not None: @@ -1305,29 +1988,50 @@ async def integrator_project_groups_async( query_params.append(f"$filter={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def integrator_projects_by_id_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def integrator_projects_by_id( self, group_identifier: str, *, @@ -1340,13 +2044,28 @@ async def integrator_projects_by_id_async( Get Integrator project group by identifier Get the project group with the given ID. + + Swagger operation ID: `IntegratorProjectsById`. + + Args: + group_identifier: The identifier of the Integrator project group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/Integrator('{quote(str(group_identifier), safe='')}')" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1360,6 +2079,7 @@ async def integrator_projects_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1367,22 +2087,50 @@ async def integrator_projects_by_id_async( return json.loads(response.text) - async def integrator_projects_async( + def list_integrator_projects( self, group_identifier: str, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Integrator projects Get a list of integrator projects found in the server. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `IntegratorProjects`. + + Args: + group_identifier: The identifier of the Integrator project group. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1406,29 +2154,50 @@ async def integrator_projects_async( query_params.append(f"$filter={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def integrator_projects_by_name_async( + return ItemPaged(get_next, extract_data) + + def integrator_projects_by_name( self, group_identifier: str, project_name: str, @@ -1442,6 +2211,22 @@ async def integrator_projects_by_name_async( Get Integrator project by name Get the integrator project with the given name. + + Swagger operation ID: `IntegratorProjectsByName`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1449,7 +2234,7 @@ async def integrator_projects_by_name_async( f"/Projects('{quote(str(project_name), safe='')}')" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1463,6 +2248,7 @@ async def integrator_projects_by_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1470,23 +2256,52 @@ async def integrator_projects_by_name_async( return json.loads(response.text) - async def extracts_async( + def list_extracts( self, group_identifier: str, project_name: str, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get extracts Get a list of extracts in the given integrator project. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Extracts`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1512,29 +2327,50 @@ async def extracts_async( query_params.append(f"$filter={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def extract_by_name_async( + return ItemPaged(get_next, extract_data) + + def extract_by_name( self, group_identifier: str, project_name: str, @@ -1549,6 +2385,23 @@ async def extract_by_name_async( Get extract by Name Get the extract with the given name in the given integrator project. + + Swagger operation ID: `ExtractByName`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + extract_name: The name of the extract. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1557,7 +2410,7 @@ async def extract_by_name_async( f"/Extracts('{quote(str(extract_name), safe='')}')" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1571,6 +2424,7 @@ async def extract_by_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1578,25 +2432,55 @@ async def extract_by_name_async( return json.loads(response.text) - async def extract_rows_async( + def list_extract_rows( self, group_identifier: str, project_name: str, extract_name: str, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get extract rows Stream the rows of the extract with the given name in the given integrator project. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ExtractRows`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + extract_name: The name of the extract. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1623,45 +2507,95 @@ async def extract_rows_async( query_params.append(f"$filter={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def jobs_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_jobs( self, group_identifier: str, project_name: str, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get jobs Get a list of jobs in the given integrator project. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Jobs`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1687,29 +2621,50 @@ async def jobs_async( query_params.append(f"$filter={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def job_by_name_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def job_by_name( self, group_identifier: str, project_name: str, @@ -1724,6 +2679,23 @@ async def job_by_name_async( Get job by name Get the jobs with the given name in the given integrator project. + + Swagger operation ID: `JobByName`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + job_name: The name of the job. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1732,7 +2704,7 @@ async def job_by_name_async( f"/Jobs('{quote(str(job_name), safe='')}')" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1746,6 +2718,7 @@ async def job_by_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1753,7 +2726,7 @@ async def job_by_name_async( return json.loads(response.text) - async def run_job_async( + def run_job( self, group_identifier: str, project_name: str, @@ -1769,6 +2742,23 @@ async def run_job_async( Run the job with the given name in the given integrator project. The execution will be added to the queue. + + Swagger operation ID: `RunJob`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + job_name: The name of the job. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1778,7 +2768,7 @@ async def run_job_async( f"/Run" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1792,6 +2782,7 @@ async def run_job_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1799,7 +2790,7 @@ async def run_job_async( return json.loads(response.text) - async def run_job_with_variables_async( + def run_job_with_variables( self, group_identifier: str, project_name: str, @@ -1816,6 +2807,27 @@ async def run_job_with_variables_async( Run the job with the given name in the given integrator project. The execution will be added to the queue. + + Swagger operation ID: `RunJobWithVariables`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + job_name: The name of the job. + variables: Variable names and values separated by an equal sign. If + a variable is omitted, the default value will be used. Multiple + variables must be separated by commas. Example: + Variables='SourceDB=Demo,TargetDB=Biker'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1827,7 +2839,7 @@ async def run_job_with_variables_async( f"')" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1841,6 +2853,7 @@ async def run_job_with_variables_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1848,23 +2861,52 @@ async def run_job_with_variables_async( return json.loads(response.text) - async def loads_async( + def list_loads( self, group_identifier: str, project_name: str, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get loads Get a list of loads in the given integrator project. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Loads`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1890,29 +2932,50 @@ async def loads_async( query_params.append(f"$filter={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def load_by_name_async( + return ItemPaged(get_next, extract_data) + + def load_by_name( self, group_identifier: str, project_name: str, @@ -1927,6 +2990,23 @@ async def load_by_name_async( Get load by name Get the transform with the given name in the given integrator project. + + Swagger operation ID: `LoadByName`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + load_name: The name of the load. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1935,7 +3015,7 @@ async def load_by_name_async( f"/Loads('{quote(str(load_name), safe='')}')" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1949,6 +3029,7 @@ async def load_by_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1956,7 +3037,7 @@ async def load_by_name_async( return json.loads(response.text) - async def run_load_async( + def run_load( self, group_identifier: str, project_name: str, @@ -1972,6 +3053,23 @@ async def run_load_async( Run the load with the given name in the given integrator project. The execution will be added to the queue. + + Swagger operation ID: `RunLoad`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + load_name: The name of the load. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1981,7 +3079,7 @@ async def run_load_async( f"/Run()" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1995,6 +3093,7 @@ async def run_load_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2002,7 +3101,7 @@ async def run_load_async( return json.loads(response.text) - async def run_load_with_variables_async( + def run_load_with_variables( self, group_identifier: str, project_name: str, @@ -2019,6 +3118,27 @@ async def run_load_with_variables_async( Run the load with the given name in the given integrator project. The execution will be added to the queue. + + Swagger operation ID: `RunLoadWithVariables`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + load_name: The name of the load. + variables: Variable names and values separated by an equal sign. If + a variable is omitted, the default value will be used. Multiple + variables must be separated by commas. Example: + Variables='SourceDB=Demo,TargetDB=Biker'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2030,7 +3150,7 @@ async def run_load_with_variables_async( f"')" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2044,6 +3164,7 @@ async def run_load_with_variables_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2051,23 +3172,52 @@ async def run_load_with_variables_async( return json.loads(response.text) - async def transforms_async( + def list_transforms( self, group_identifier: str, project_name: str, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get transforms Get a list of transforms in the given integrator project. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Transforms`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2093,29 +3243,50 @@ async def transforms_async( query_params.append(f"$filter={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def transform_by_name_async( + def transform_by_name( self, group_identifier: str, project_name: str, @@ -2130,6 +3301,23 @@ async def transform_by_name_async( Get transform by name Get the transform with the given name in the given integrator project. + + Swagger operation ID: `TransformByName`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + transform_name: The name of the transform. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2138,7 +3326,7 @@ async def transform_by_name_async( f"/Transforms('{quote(str(transform_name), safe='')}')" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2152,6 +3340,7 @@ async def transform_by_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2159,25 +3348,55 @@ async def transform_by_name_async( return json.loads(response.text) - async def transform_rows_async( + def list_transform_rows( self, group_identifier: str, project_name: str, transform_name: str, + *, top: Optional[int] = None, skip: Optional[int] = None, filter: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get transform Rows Stream the rows of the transform with the given name in the given integrator project. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `TransformRows`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the Integrator project. + transform_name: The name of the transform. + top: Limits the number of items returned by the given number. The + service returns the number of available items up to but not + greater than the specified value n. + skip: Excludes the first n items of the queried collection from the + result. The service returns items starting at position n+1. + filter: The $filter system query option restricts the set of items + returned. For a list of available operations and functions see + the [OData + Documentation](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Ref356810738). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2204,29 +3423,50 @@ async def transform_rows_async( query_params.append(f"$filter={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def get_cube_cell_result_schema_async( + return ItemPaged(get_next, extract_data) + + def get_cube_cell_result_schema( self, database_id: int, cube_id: int, @@ -2241,6 +3481,22 @@ async def get_cube_cell_result_schema_async( Service request for getting the schema used for the result of cube cells. + + Swagger operation ID: `GetCubeCellResultSchema`. + + Args: + database_id: The identifier of the Olap database. + cube_id: The identifier of the Olap cube. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2254,7 +3510,7 @@ async def get_cube_cell_result_schema_async( f"/cells" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2268,6 +3524,7 @@ async def get_cube_cell_result_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2275,7 +3532,7 @@ async def get_cube_cell_result_schema_async( return json.loads(response.text) - async def get_extract_rows_result_schema_async( + def get_extract_rows_result_schema( self, group_identifier: str, project_name: str, @@ -2291,6 +3548,23 @@ async def get_extract_rows_result_schema_async( Service request for getting the schema used for the result of extract rows. + + Swagger operation ID: `GetExtractRowsResultSchema`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the project. + extract_name: The name of the extract. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2305,7 +3579,7 @@ async def get_extract_rows_result_schema_async( f"/rows" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2319,6 +3593,7 @@ async def get_extract_rows_result_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2326,7 +3601,7 @@ async def get_extract_rows_result_schema_async( return json.loads(response.text) - async def get_transform_rows_result_schema_async( + def get_transform_rows_result_schema( self, group_identifier: str, project_name: str, @@ -2342,6 +3617,23 @@ async def get_transform_rows_result_schema_async( Service request for getting the schema used for the result of transform rows. + + Swagger operation ID: `GetTransformRowsResultSchema`. + + Args: + group_identifier: The identifier of the Integrator project group. + project_name: The name of the project. + transform_name: The name of the transform. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2356,7 +3648,7 @@ async def get_transform_rows_result_schema_async( f"/rows" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2370,6 +3662,7 @@ async def get_transform_rows_result_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2377,7 +3670,7 @@ async def get_transform_rows_result_schema_async( return json.loads(response.text) - async def get_view_cell_result_schema_async( + def get_view_cell_result_schema( self, database_id: int, view_id: str, @@ -2392,6 +3685,22 @@ async def get_view_cell_result_schema_async( Service request for getting the schema used for the result of view cells. + + Swagger operation ID: `GetViewCellResultSchema`. + + Args: + database_id: The identifier of the Olap database. + view_id: The identifier of the stored view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2405,7 +3714,7 @@ async def get_view_cell_result_schema_async( f"/cells" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2419,6 +3728,7 @@ async def get_view_cell_result_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/jira.py b/src/azure/connectors/jira.py index 2ee35e1..367b4d3 100644 --- a/src/azure/connectors/jira.py +++ b/src/azure/connectors/jira.py @@ -5,21 +5,70 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "JiraClient", + "Assignee", + "CancelTaskResponse", + "Comment", + "CommentResponse", + "CreateIssueInput", + "CreateIssueRequest", + "CreateIssueResponse", + "CreateProjectCategoryInput", + "CreateProjectCategoryResponse", + "CreateProjectInput", + "CreateProjectResponse", + "Creator", + "EditIssueInput", + "EditIssueResponse", + "FilterArray", + "FullIssue", + "GetCurrentUserResponse", + "GetTaskResponse", + "GetUserResponse", + "IssueTypes", + "ListFiltersResponse", + "ListIssuesResponse", + "ListIssuesResponseDatacenter", + "ListProjectsResponse", + "ListTransitionsResponse", + "MCPQueryRequest", + "MCPQueryResponse", + "PartialIssue", + "PriorityList", + "Project", + "ProjectArray", + "Reporter", + "Sites", + "StatusList", + "Transition", + "TransitionInput", + "TransitionStatus", + "UpdateIssueRequest", + "UpdateProjectInput", + "UpdateProjectResponse", + "UpdateTransitionResponse", + "User", + "UserList", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -32,8 +81,9 @@ class ListIssuesResponse: Response for Get list of issues """ - next_page_token: Optional[str] = field( + next_page_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextPageToken"}, ) """ @@ -41,12 +91,18 @@ class ListIssuesResponse: the 'Next page token' input of a subsequent call to fetch the next page. Absent on the last page. """ - is_last: Optional[bool] = field( + is_last: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isLast"}, ) """Indicates whether this is the last page of results.""" - issues: Optional[List[FullIssue]] = None + issues: Optional[ + List[FullIssue | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -55,17 +111,24 @@ class ListIssuesResponseDatacenter: Response for Get list of issues (Datacenter) """ - start_at: Optional[int] = field( + start_at: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startAt"}, ) """The index of the first item to return in a page of results""" - max_results: Optional[int] = field( + max_results: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "maxResults"}, ) """The maximum number of items to return per page""" - issues: Optional[List[FullIssue]] = None + issues: Optional[ + List[FullIssue | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -74,7 +137,12 @@ class ListTransitionsResponse: Response for Get list of Transitions """ - transitions: Optional[List[Transition]] = None + transitions: Optional[ + List[Transition | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -83,7 +151,7 @@ class UpdateTransitionResponse: Response for Performs an issue transition """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -96,7 +164,7 @@ class GetCurrentUserResponse: Response for Get current user """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -109,13 +177,13 @@ class FullIssue: Response for When a new issue is created (Datacenter) """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique id of the issue.""" - key: Optional[str] = None + key: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique key of the issue.""" - self: Optional[str] = None + self: Optional[str] = dataclass_field(default=None, kw_only=True) """Browse to the issue using this URL.""" - fields: Optional[Dict[str, Any]] = None + fields: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -124,12 +192,12 @@ class MCPQueryResponse: Response for Jira MCP Server """ - jsonrpc: Optional[str] = None - id: Optional[str] = None - method: Optional[str] = None - params: Optional[Dict[str, Any]] = None - result: Optional[Dict[str, Any]] = None - error: Optional[Dict[str, Any]] = None + jsonrpc: Optional[str] = dataclass_field(default=None, kw_only=True) + id: Optional[str] = dataclass_field(default=None, kw_only=True) + method: Optional[str] = dataclass_field(default=None, kw_only=True) + params: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + result: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + error: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -138,11 +206,11 @@ class CommentResponse: Response for Add comment """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique id of the comment.""" - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """Body of the comment.""" - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" @@ -152,7 +220,7 @@ class CancelTaskResponse: Response for Cancel Task """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -165,7 +233,7 @@ class CreateIssueInput: Create a new issue """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -178,9 +246,9 @@ class CreateIssueResponse: Response for Create a new issue """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the issue.""" - key: Optional[str] = None + key: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique key of the issue.""" @@ -190,21 +258,19 @@ class CreateProjectInput: Create a new project """ - key: Optional[str] = None + key: str """The unique key, starts with a capital letter.""" - name: Optional[str] = None + name: str """Title of the project.""" - project_type_key: Optional[str] = field( - default=None, + project_type_key: str = dataclass_field( metadata={"wire_name": "projectTypeKey"}, ) """Project type key.""" - lead_account_id: Optional[str] = field( - default=None, + lead_account_id: str = dataclass_field( metadata={"wire_name": "leadAccountId"}, ) """Id of Project lead.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Verbose description of the project.""" @@ -214,9 +280,9 @@ class CreateProjectResponse: Response for Create a new project """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique id of the project.""" - key: Optional[str] = None + key: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique key of the project.""" @@ -226,9 +292,9 @@ class CreateProjectCategoryInput: Create Project Category """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description""" @@ -238,7 +304,7 @@ class CreateProjectCategoryResponse: Response for Create Project Category """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -251,27 +317,28 @@ class EditIssueInput: Edit Issue """ - transition: Optional[Dict[str, Any]] = None + transition: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Transition""" - fields: Optional[Dict[str, Any]] = None + fields: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """ List of issue screen fields to update, specifying the sub-field to update and its value for each field. This field provides a straightforward option when setting a sub-field. When multiple sub-fields or other operations are required, use update. Fields included in here cannot be included in update. """ - update: Optional[Dict[str, Any]] = None + update: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """ A Map containing the field field name and a list of operations to perform on the issue screen field. Note that fields included in here cannot be included in fields. """ - history_metadata: Optional[Dict[str, Any]] = field( + history_metadata: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "historyMetadata"}, ) """History meta data""" - properties: Optional[List[Dict[str, Any]]] = None + properties: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Properties""" @@ -281,7 +348,7 @@ class EditIssueResponse: Response for Edit Issue """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -294,7 +361,7 @@ class GetTaskResponse: Response for Get Task """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -307,7 +374,7 @@ class GetUserResponse: Response for Get User """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -320,12 +387,13 @@ class ListFiltersResponse: Response for Get list of Filters """ - next_page: Optional[str] = field( + next_page: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextPage"}, ) """Next page of filters""" - values: Optional[FilterArray] = None + values: Optional[FilterArray] = dataclass_field(default=None, kw_only=True) @dataclass @@ -334,12 +402,13 @@ class ListProjectsResponse: Response for Get projects """ - next_page: Optional[str] = field( + next_page: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextPage"}, ) """Next page of projects""" - values: Optional[ProjectArray] = None + values: Optional[ProjectArray] = dataclass_field(default=None, kw_only=True) UserList = List[Dict[str, Any]] @@ -351,58 +420,67 @@ class UpdateProjectInput: Update Project """ - key: Optional[str] = None + key: Optional[str] = dataclass_field(default=None, kw_only=True) """Key""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name""" - project_type_key: Optional[str] = field( + project_type_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "projectTypeKey"}, ) """Project Type Key""" - project_template_key: Optional[str] = field( + project_template_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "projectTemplateKey"}, ) """Project Template Key""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description""" - lead: Optional[str] = None + lead: Optional[str] = dataclass_field(default=None, kw_only=True) """Lead""" - lead_account_id: Optional[str] = field( + lead_account_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "leadAccountId"}, ) """Lead Account ID""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """URL""" - assignee_type: Optional[str] = field( + assignee_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assigneeType"}, ) """Assignee Type""" - avatar_id: Optional[str] = field( + avatar_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "avatarId"}, ) """Avatar ID""" - issue_security_scheme: Optional[str] = field( + issue_security_scheme: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "issueSecurityScheme"}, ) """Issue Security Scheme""" - permission_scheme: Optional[str] = field( + permission_scheme: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "permissionScheme"}, ) """Permission Scheme""" - notification_scheme: Optional[str] = field( + notification_scheme: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notificationScheme"}, ) """Notification Scheme""" - category_id: Optional[str] = field( + category_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "categoryId"}, ) """Category ID""" @@ -414,7 +492,7 @@ class UpdateProjectResponse: Response for Update Project """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -430,14 +508,15 @@ class Project: Definition: Project """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique Id of the project.""" - key: Optional[str] = None + key: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique key of the project.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the project.""" - project_type_key: Optional[str] = field( + project_type_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "projectTypeKey"}, ) """The unique key of the project type.""" @@ -452,11 +531,11 @@ class PartialIssue: Definition: PartialIssue """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique Id of the Issue.""" - key: Optional[str] = None + key: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique key of the issue.""" - fields: Optional[Dict[str, Any]] = None + fields: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -465,20 +544,23 @@ class Creator: Definition: Creator """ - account_id: Optional[str] = field( + account_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "accountId"}, ) """Person who created the issue.""" - key: Optional[str] = None + key: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique key of the person who created the issue.""" - email_address: Optional[str] = field( + email_address: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "emailAddress"}, ) """Email of the person who created the issue.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the person who created the issue.""" @@ -490,20 +572,23 @@ class Assignee: Definition: Assignee """ - account_id: Optional[str] = field( + account_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "accountId"}, ) """Person whom the issue is assigned to.""" - key: Optional[str] = None + key: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique key of the person whom the issue is assigned to.""" - email_address: Optional[str] = field( + email_address: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "emailAddress"}, ) """Email of the person whom the issue is assigned to.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the person whom the issue is assigned to.""" @@ -515,20 +600,23 @@ class User: Definition: User """ - account_id: Optional[str] = field( + account_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "accountId"}, ) """Id of the Jira user.""" - key: Optional[str] = None + key: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique key of the Jira user.""" - email_address: Optional[str] = field( + email_address: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "emailAddress"}, ) """Email of the Jira user.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the Jira user.""" @@ -540,20 +628,23 @@ class Reporter: Definition: Reporter """ - account_id: Optional[str] = field( + account_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountId"}, ) """Person who reported the issue.""" - key: Optional[str] = None + key: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique key of the person who reported the issue.""" - email_address: Optional[str] = field( + email_address: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "emailAddress"}, ) """Email of the person who reported the issue.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the person who reported the issue.""" @@ -568,7 +659,7 @@ class CreateIssueRequest: Definition: CreateIssueRequest """ - fields: Optional[Dict[str, Any]] = None + fields: Dict[str, Any] @dataclass @@ -577,7 +668,7 @@ class UpdateIssueRequest: Definition: UpdateIssueRequest """ - fields: Optional[Dict[str, Any]] = None + fields: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) StatusList = List[Dict[str, Any]] @@ -592,7 +683,7 @@ class Comment: Definition: Comment """ - body: Optional[str] = None + body: str """Body of the comment.""" @@ -602,12 +693,12 @@ class Transition: Definition: Transition """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID of the transition""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the transition""" - to: Optional[TransitionStatus] = None - fields: Optional[Dict[str, Any]] = None + to: Optional[TransitionStatus | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + fields: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Fields required for this transition""" @@ -617,9 +708,9 @@ class TransitionStatus: Definition: TransitionStatus """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID of the status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the status""" @@ -629,13 +720,14 @@ class TransitionInput: Definition: TransitionInput """ - fields: Optional[Dict[str, Any]] = None - history_metadata: Optional[Dict[str, Any]] = field( + fields: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + history_metadata: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "historyMetadata"}, ) - transition: Optional[Dict[str, Any]] = None - update: Optional[Dict[str, Any]] = None + transition: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + update: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -644,14 +736,15 @@ class MCPQueryRequest: Definition: MCPQueryRequest """ - jsonrpc: Optional[str] = None - id: Optional[str] = None - method: Optional[str] = None - params: Optional[Dict[str, Any]] = None - result: Optional[Dict[str, Any]] = None - error: Optional[Dict[str, Any]] = None - callback_endpoint: Optional[str] = field( + jsonrpc: Optional[str] = dataclass_field(default=None, kw_only=True) + id: Optional[str] = dataclass_field(default=None, kw_only=True) + method: Optional[str] = dataclass_field(default=None, kw_only=True) + params: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + result: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + error: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + callback_endpoint: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "callbackEndpoint"}, ) @@ -664,16 +757,16 @@ class JiraClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -684,8 +777,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -693,8 +786,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -706,7 +799,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -721,59 +814,161 @@ def __init__( def connector_name(self) -> str: return "jira" - async def list_resources_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_resources( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get list of Resources This operation returns a list of resources accessible to user. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListResources`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/oauth/token/accessible-resources" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def list_issues_async( + def list_issues( self, + *, jql: Optional[str] = None, fields: Optional[str] = None, - next_page_token: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get list of issues This operation returns a list of issues using JQL. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListIssues`. + + Args: + jql: The JQL query used to search for issues. If left blank, + returns all issues created in the last 10 years. + fields: Optional comma-separated list of Jira field IDs or keys to + return, for example summary,status,attachment. For custom + fields, use the field ID, such as customfield_10042. Also + supports *all, *navigable, and exclusions such as + *all,-attachment. If omitted, all fields are returned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/2/search" query_params = [] @@ -788,72 +983,127 @@ async def list_issues_async( if isinstance(fields, bool): value = value.lower() query_params.append(f"fields={quote(value, safe='')}") - if next_page_token is not None: - value = str(next_page_token) - if isinstance(next_page_token, bool): - value = value.lower() - query_params.append(f"nextPageToken={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("issues", []): + yield item + + return None, items() - async def list_issues_datacenter_async( + return ItemPaged(get_next, extract_data) + + def list_issues_datacenter( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get list of issues (Datacenter) This operation returns a list of issues using JQL. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListIssues_Datacenter`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/datacenter/search" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("issues", []): + yield item + + return None, items() - async def list_transitions_async( + return ItemPaged(get_next, extract_data) + + def list_transitions( self, issue_id_or_key: str, *, @@ -861,42 +1111,83 @@ async def list_transitions_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get list of Transitions Returns a list of the transitions possible for this issue by the current user + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTransitions`. + + Args: + issue_id_or_key: ID or key of the issue to retrieve transitions + for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/3/issue/{quote(str(issue_id_or_key), safe='')}/transitions" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("transitions", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def update_transition_async( + def update_transition( self, - input: TransitionInput, + input: TransitionInput | Mapping[str, Any], issue_id_or_key: str, *, timeout: Optional[float] = None, @@ -908,13 +1199,30 @@ async def update_transition_async( Performs an issue transition Transitions an issue to a new status. + + Swagger operation ID: `UpdateTransition`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + issue_id_or_key: ID or key of the issue to be transitioned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/3/issue/{quote(str(issue_id_or_key), safe='')}/transitions" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -928,6 +1236,7 @@ async def update_transition_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -935,10 +1244,10 @@ async def update_transition_async( return json.loads(response.text) - async def get_current_user_async( + def get_current_user( self, - expand: Optional[str] = None, *, + expand: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -948,6 +1257,26 @@ async def get_current_user_async( Get current user This operation returns details for the current user + + Swagger operation ID: `GetCurrentUser`. + + Args: + expand: Use expand to include additional information about users in + the response. This parameter accepts a comma-separated list. + Expand options include: * `groups` includes all groups and + nested groups to which the user belongs. * `applicationRoles` + includes details of all the applications to which the user has + access. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/3/myself" query_params = [] @@ -959,7 +1288,7 @@ async def get_current_user_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -973,6 +1302,7 @@ async def get_current_user_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -980,11 +1310,11 @@ async def get_current_user_async( return json.loads(response.text) - async def mcp_jira_issue_management_async( + def mcp_jira_issue_management( self, - input: MCPQueryRequest, - session_id: Optional[str] = None, + input: MCPQueryRequest | Mapping[str, Any], *, + session_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -994,6 +1324,23 @@ async def mcp_jira_issue_management_async( Jira MCP Server Jira MCP Server + + Swagger operation ID: `mcp_JiraIssueManagement`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + session_id: sessionId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/mcp/JiraIssueManagement" query_params = [] @@ -1005,7 +1352,7 @@ async def mcp_jira_issue_management_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1019,6 +1366,7 @@ async def mcp_jira_issue_management_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1026,9 +1374,9 @@ async def mcp_jira_issue_management_async( return json.loads(response.text) - async def add_comment_async( + def add_comment( self, - input: Comment, + input: Comment | Mapping[str, Any], issue_key: str, *, timeout: Optional[float] = None, @@ -1040,13 +1388,30 @@ async def add_comment_async( Add comment This operation is used to add a comment to an existing Jira issue. + + Swagger operation ID: `AddComment_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + issue_key: Unique Key of the issue to add a comment to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v2/issue/{quote(str(issue_key), safe='')}/comment" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1060,6 +1425,7 @@ async def add_comment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1067,7 +1433,7 @@ async def add_comment_async( return json.loads(response.text) - async def cancel_task_async( + def cancel_task( self, task_id: str, *, @@ -1081,13 +1447,28 @@ async def cancel_task_async( Cancels a task. Permissions required: either of: Administer Jira or Creator of the task. + + Swagger operation ID: `CancelTask_V2`. + + Args: + task_id: The ID of the task. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v2/task/{quote(str(task_id), safe='')}/cancel" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1101,6 +1482,7 @@ async def cancel_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1108,9 +1490,9 @@ async def cancel_task_async( return json.loads(response.text) - async def create_issue_async( + def create_issue( self, - input: CreateIssueInput, + input: CreateIssueInput | Mapping[str, Any], project_key: str, issue_type_ids: str, *, @@ -1123,6 +1505,24 @@ async def create_issue_async( Create a new issue This operation is used to create a new issue. + + Swagger operation ID: `CreateIssue_V3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + project_key: Pick a project to create the issue in. + issue_type_ids: Pick an issue type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v3/issue" query_params = [] @@ -1137,7 +1537,7 @@ async def create_issue_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1151,6 +1551,7 @@ async def create_issue_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1158,9 +1559,9 @@ async def create_issue_async( return json.loads(response.text) - async def create_project_async( + def create_project( self, - input: CreateProjectInput, + input: CreateProjectInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1171,10 +1572,26 @@ async def create_project_async( Create a new project This operation is used to create a new Jira project. + + Swagger operation ID: `CreateProject_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/project" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1188,6 +1605,7 @@ async def create_project_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1195,9 +1613,9 @@ async def create_project_async( return json.loads(response.text) - async def create_project_category_async( + def create_project_category( self, - input: CreateProjectCategoryInput, + input: CreateProjectCategoryInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1209,10 +1627,26 @@ async def create_project_category_async( Creates a project category. Permissions required: Administer Jira (global permissions) + + Swagger operation ID: `CreateProjectCategory_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/projectCategory" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1226,6 +1660,7 @@ async def create_project_category_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1233,11 +1668,11 @@ async def create_project_category_async( return json.loads(response.text) - async def delete_project_async( + def delete_project( self, project_id_or_key: str, - enable_undo: Optional[bool] = None, *, + enable_undo: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1248,6 +1683,23 @@ async def delete_project_async( Deletes a project. Permissions required: Administer Jira (global permissions) + + Swagger operation ID: `DeleteProject_V2`. + + Args: + project_id_or_key: The project ID or project key (case sensitive). + enable_undo: Whether this project is placed in the Jira recycle bin + where it will be available for restoration. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1262,7 +1714,7 @@ async def delete_project_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1276,16 +1728,17 @@ async def delete_project_async( request_url, response.status, response.text, + response=response, ) - async def edit_issue_async( + def edit_issue( self, - input: EditIssueInput, + input: EditIssueInput | Mapping[str, Any], issue_id_or_key: str, + *, notify_users: Optional[bool] = None, override_screen_security: Optional[bool] = None, override_editable_flag: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1297,6 +1750,28 @@ async def edit_issue_async( Edits an issue. A transition may be applied and issue properties updated as part of the edit. The edits to the issue's fields are defined using update and fields. + + Swagger operation ID: `EditIssue_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + issue_id_or_key: Provide the Issue ID or Key for the issue you wish + to edit. + notify_users: Do you want to notify users? + override_screen_security: Do you want to override the screen + security? + override_editable_flag: Do you want to override the editable flag? + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1321,7 +1796,7 @@ async def edit_issue_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1335,6 +1810,7 @@ async def edit_issue_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1342,43 +1818,82 @@ async def edit_issue_async( return json.loads(response.text) - async def get_all_project_categories_async( + def list_all_project_categories( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get All Project Categories Returns all project categories. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAllProjectCategories_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/projectCategory" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def get_issue_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_issue( self, issue_key: str, *, @@ -1392,13 +1907,28 @@ async def get_issue_async( This operation is used to retrieve the issue object for a given issue Key. + + Swagger operation ID: `GetIssue_V2`. + + Args: + issue_key: Unique Key of the issue. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v2/issue/{quote(str(issue_key), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1412,6 +1942,7 @@ async def get_issue_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1419,7 +1950,7 @@ async def get_issue_async( return json.loads(response.text) - async def get_task_async( + def get_task( self, task_id: str, *, @@ -1433,13 +1964,28 @@ async def get_task_async( Returns the status of a long-running asynchronous task. When a task has finished, this operation returns the JSON blob applicable to the task. + + Swagger operation ID: `GetTask_V2`. + + Args: + task_id: The ID of the task. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v2/task/{quote(str(task_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1453,6 +1999,7 @@ async def get_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1460,11 +2007,11 @@ async def get_task_async( return json.loads(response.text) - async def get_user_async( + def get_user( self, account_id: str, - expand: Optional[str] = None, *, + expand: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1474,6 +2021,29 @@ async def get_user_async( Get User Returns a user. Permissions required: Browse users and groups. + + Swagger operation ID: `GetUser_V2`. + + Args: + account_id: The account ID of the user, which uniquely identifies + the user across all Atlassian products. For example, + *5b10ac8d82e05b22cc7d4ef5*. Required. + expand: Use expand to include additional information about users in + the response. This parameter accepts a comma-separated list. + Expand options include: * `groups` includes all groups and + nested groups to which the user belongs. * `applicationRoles` + includes details of all the applications to which the user has + access. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/user" query_params = [] @@ -1489,7 +2059,7 @@ async def get_user_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1503,6 +2073,7 @@ async def get_user_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1510,80 +2081,170 @@ async def get_user_async( return json.loads(response.text) - async def list_filters_async( + def list_filters( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get list of Filters This operation returns a list of Filters accessible to user. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListFilters_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/filter/search" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextPage") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None ) - if not response.text: - return None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("values", []): + yield item - return json.loads(response.text) + return continuation_token, items() - async def list_projects_async( + return ItemPaged(get_next, extract_data) + + def list_projects( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get projects This operation is used to retrieve a list of projects for your Jira instance. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListProjects_V3`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/project/search" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + next_link = page.get("nextPage") + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None ) - if not response.text: - return None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("values", []): + yield item - return json.loads(response.text) + return continuation_token, items() - async def list_project_users_async( + return ItemPaged(get_next, extract_data) + + def list_project_users( self, project_key: str, *, @@ -1591,12 +2252,31 @@ async def list_project_users_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List users by project This operation is used to retrieve a list of all users associated with a project. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListProjectUsers_V2`. + + Args: + project_key: Unique key of the project. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v2/user/permission/search" @@ -1608,29 +2288,50 @@ async def list_project_users_async( query_params.append(f"projectKey={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def remove_project_category_async( + return ItemPaged(get_next, extract_data) + + def remove_project_category( self, id: int, *, @@ -1644,13 +2345,28 @@ async def remove_project_category_async( Deletes a project category. Permissions required: Administer Jira (global permissions) + + Swagger operation ID: `RemoveProjectCategory_V2`. + + Args: + id: ID of the project category to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v2/projectCategory/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1664,11 +2380,12 @@ async def remove_project_category_async( request_url, response.status, response.text, + response=response, ) - async def update_project_async( + def update_project( self, - input: UpdateProjectInput, + input: UpdateProjectInput | Mapping[str, Any], project_id_or_key: str, *, timeout: Optional[float] = None, @@ -1680,13 +2397,31 @@ async def update_project_async( Update Project Updates the project details of a project. + + Swagger operation ID: `UpdateProject_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + project_id_or_key: Provide the project ID or Key you want to + update1. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v2/project/{quote(str(project_id_or_key), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1700,6 +2435,7 @@ async def update_project_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1707,7 +2443,7 @@ async def update_project_async( return json.loads(response.text) - async def list_issue_types_async( + def list_issue_types( self, project_key: str, *, @@ -1715,12 +2451,31 @@ async def list_issue_types_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get issue types This operation is used to retrieve a list of issue types for a given project. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListIssueTypes_V2`. + + Args: + project_key: Project. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v2/types/issue/createmeta" @@ -1732,29 +2487,50 @@ async def list_issue_types_async( query_params.append(f"projectKey={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def list_issue_types_fields_async( + return ItemPaged(get_next, extract_data) + + def list_issue_types_fields( self, project_key: str, issuetype_ids: str, @@ -1763,12 +2539,32 @@ async def list_issue_types_fields_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get issue types fields This operation is used to retrieve a list of fields for a specific issue type. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListIssueTypesFields_V2`. + + Args: + project_key: Project. + issuetype_ids: Issue Types. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v3/issue/createmeta" query_params = [] @@ -1782,27 +2578,48 @@ async def list_issue_types_fields_async( query_params.append(f"issuetypeIds={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/keyvault.py b/src/azure/connectors/keyvault.py index 9744abd..97f384f 100644 --- a/src/azure/connectors/keyvault.py +++ b/src/azure/connectors/keyvault.py @@ -5,21 +5,35 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "KeyvaultClient", + "KeyDecryptInput", + "KeyDecryptOutput", + "KeyEncryptInput", + "KeyEncryptOutput", + "KeyMetadata", + "KeyMetadataCollection", + "Secret", + "SecretMetadata", + "SecretMetadataCollection", +] + # Type Definitions @@ -29,10 +43,16 @@ class KeyMetadataCollection: Response for List keys """ - value: Optional[List[KeyMetadata]] = None + value: Optional[ + List[KeyMetadata | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The keys""" - continuation_token: Optional[str] = field( + continuation_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "continuationToken"}, ) """Continuation token""" @@ -44,42 +64,49 @@ class KeyMetadata: Response for Get key metadata """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the key""" - version: Optional[str] = None + version: Optional[str] = dataclass_field(default=None, kw_only=True) """Version of the key""" - is_enabled: Optional[bool] = field( + is_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEnabled"}, ) """A flag indicating whether the key is enabled""" - created_time: Optional[str] = field( + created_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdTime"}, ) """Time when the key was created""" - last_updated_time: Optional[str] = field( + last_updated_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastUpdatedTime"}, ) """Time when the key was last updated""" - validity_start_time: Optional[str] = field( + validity_start_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "validityStartTime"}, ) """Time when the key validity starts.""" - validity_end_time: Optional[str] = field( + validity_end_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "validityEndTime"}, ) """Time when the key validity ends.""" - allowed_operations: Optional[List[str]] = field( + allowed_operations: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowedOperations"}, ) """Operations allowed using the key""" - key_type: Optional[str] = field( + key_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "keyType"}, ) """Type of the key""" @@ -91,8 +118,9 @@ class KeyEncryptOutput: Response for Encrypt data with key """ - encrypted_data: Optional[str] = field( + encrypted_data: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "encryptedData"}, ) """Encrypted data""" @@ -104,8 +132,9 @@ class KeyDecryptOutput: Response for Decrypt data with key """ - raw_data: Optional[str] = field( + raw_data: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "rawData"}, ) """Raw data""" @@ -117,10 +146,16 @@ class SecretMetadataCollection: Response for List secrets """ - value: Optional[List[SecretMetadata]] = None + value: Optional[ + List[SecretMetadata | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The secrets""" - continuation_token: Optional[str] = field( + continuation_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "continuationToken"}, ) """Continuation token""" @@ -132,37 +167,43 @@ class SecretMetadata: Response for Get secret metadata """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the secret""" - version: Optional[str] = None + version: Optional[str] = dataclass_field(default=None, kw_only=True) """Version of the secret""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentType"}, ) """Content type of the secret""" - is_enabled: Optional[bool] = field( + is_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEnabled"}, ) """A flag indicating whether the secret is enabled""" - created_time: Optional[str] = field( + created_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdTime"}, ) """Time when the secret was created""" - last_updated_time: Optional[str] = field( + last_updated_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastUpdatedTime"}, ) """Time when the secret was last updated""" - validity_start_time: Optional[str] = field( + validity_start_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "validityStartTime"}, ) """Time when the secret validity starts.""" - validity_end_time: Optional[str] = field( + validity_end_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "validityEndTime"}, ) """Time when the secret validity ends.""" @@ -174,39 +215,45 @@ class Secret: Response for Get secret """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Value of the secret""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the secret""" - version: Optional[str] = None + version: Optional[str] = dataclass_field(default=None, kw_only=True) """Version of the secret""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentType"}, ) """Content type of the secret""" - is_enabled: Optional[bool] = field( + is_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEnabled"}, ) """A flag indicating whether the secret is enabled""" - created_time: Optional[str] = field( + created_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdTime"}, ) """Time when the secret was created""" - last_updated_time: Optional[str] = field( + last_updated_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastUpdatedTime"}, ) """Time when the secret was last updated""" - validity_start_time: Optional[str] = field( + validity_start_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "validityStartTime"}, ) """Time when the secret validity starts.""" - validity_end_time: Optional[str] = field( + validity_end_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "validityEndTime"}, ) """Time when the secret validity ends.""" @@ -218,12 +265,9 @@ class KeyEncryptInput: Definition: KeyEncryptInput """ - algorithm: Optional[str] = None + algorithm: str """Algorithm to use for encrypting the data""" - raw_data: Optional[str] = field( - default=None, - metadata={"wire_name": "rawData"}, - ) + raw_data: str = dataclass_field(metadata={"wire_name": "rawData"}) """Data to encrypt""" @@ -233,10 +277,9 @@ class KeyDecryptInput: Definition: KeyDecryptInput """ - algorithm: Optional[str] = None + algorithm: str """Algorithm to use for decrypting the data""" - encrypted_data: Optional[str] = field( - default=None, + encrypted_data: str = dataclass_field( metadata={"wire_name": "encryptedData"}, ) """Data to decrypt""" @@ -250,16 +293,16 @@ class KeyvaultClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -270,8 +313,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -279,8 +322,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -292,7 +335,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -307,43 +350,121 @@ def __init__( def connector_name(self) -> str: return "keyvault" - async def list_keys_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_keys( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List keys List keys. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListKeys`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/keys" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def list_key_versions_async( + return ItemPaged(get_next, extract_data) + + def list_key_versions( self, key_name: str, *, @@ -351,39 +472,79 @@ async def list_key_versions_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List key versions List versions of a key. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListKeyVersions`. + + Args: + key_name: Name of the key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/keys/{quote(str(key_name), safe='')}/versions" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def get_key_metadata_async( + return ItemPaged(get_next, extract_data) + + def get_key_metadata( self, key_name: str, *, @@ -396,13 +557,28 @@ async def get_key_metadata_async( Get key metadata Gets metadata of a key. + + Swagger operation ID: `GetKeyMetadata`. + + Args: + key_name: Name of the key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/keys/{quote(str(key_name), safe='')}/metadata" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -416,6 +592,7 @@ async def get_key_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -423,7 +600,7 @@ async def get_key_metadata_async( return json.loads(response.text) - async def get_key_version_metadata_async( + def get_key_version_metadata( self, key_name: str, key_version: str, @@ -437,6 +614,22 @@ async def get_key_version_metadata_async( Get key version metadata Gets metadata of a version of a key. + + Swagger operation ID: `GetKeyVersionMetadata`. + + Args: + key_name: Name of the key. + key_version: Version of the key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -447,7 +640,7 @@ async def get_key_version_metadata_async( f"/metadata" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -461,6 +654,7 @@ async def get_key_version_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -468,9 +662,9 @@ async def get_key_version_metadata_async( return json.loads(response.text) - async def encrypt_data_async( + def encrypt_data( self, - input: KeyEncryptInput, + input: KeyEncryptInput | Mapping[str, Any], key_name: str, *, timeout: Optional[float] = None, @@ -482,13 +676,30 @@ async def encrypt_data_async( Encrypt data with key Encrypt data using the latest version of a key. + + Swagger operation ID: `EncryptData`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + key_name: Name of the key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/keys/{quote(str(key_name), safe='')}/encrypt" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -502,6 +713,7 @@ async def encrypt_data_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -509,9 +721,9 @@ async def encrypt_data_async( return json.loads(response.text) - async def encrypt_data_with_version_async( + def encrypt_data_with_version( self, - input: KeyEncryptInput, + input: KeyEncryptInput | Mapping[str, Any], key_name: str, key_version: str, *, @@ -524,6 +736,24 @@ async def encrypt_data_with_version_async( Encrypt data with key version Encrypt data using a specific version of a key. + + Swagger operation ID: `EncryptDataWithVersion`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + key_name: Name of the key. + key_version: Version of the key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -534,7 +764,7 @@ async def encrypt_data_with_version_async( f"/encrypt" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -548,6 +778,7 @@ async def encrypt_data_with_version_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -555,9 +786,9 @@ async def encrypt_data_with_version_async( return json.loads(response.text) - async def decrypt_data_async( + def decrypt_data( self, - input: KeyDecryptInput, + input: KeyDecryptInput | Mapping[str, Any], key_name: str, *, timeout: Optional[float] = None, @@ -571,13 +802,30 @@ async def decrypt_data_async( Decrypt data using the latest version of a key. Output of this operation is typically classified as secret and can be visible in the run history. + + Swagger operation ID: `DecryptData`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + key_name: Name of the key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/keys/{quote(str(key_name), safe='')}/decrypt" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -591,6 +839,7 @@ async def decrypt_data_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -598,9 +847,9 @@ async def decrypt_data_async( return json.loads(response.text) - async def decrypt_data_with_version_async( + def decrypt_data_with_version( self, - input: KeyDecryptInput, + input: KeyDecryptInput | Mapping[str, Any], key_name: str, key_version: str, *, @@ -615,6 +864,24 @@ async def decrypt_data_with_version_async( Decrypt data using a specific version of a key. Output of this operation is typically classified as secret and can be visible in the run history. + + Swagger operation ID: `DecryptDataWithVersion`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + key_name: Name of the key. + key_version: Version of the key. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -625,7 +892,7 @@ async def decrypt_data_with_version_async( f"/decrypt" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -639,6 +906,7 @@ async def decrypt_data_with_version_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -646,43 +914,82 @@ async def decrypt_data_with_version_async( return json.loads(response.text) - async def list_secrets_async( + def list_secrets( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List secrets List secrets. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListSecrets`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/secrets" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def list_secret_versions_async( + return ItemPaged(get_next, extract_data) + + def list_secret_versions( self, secret_name: str, *, @@ -690,39 +997,79 @@ async def list_secret_versions_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List secret versions List versions of a secret. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListSecretVersions`. + + Args: + secret_name: Name of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/secrets/{quote(str(secret_name), safe='')}/versions" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_secret_metadata_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_secret_metadata( self, secret_name: str, *, @@ -735,13 +1082,28 @@ async def get_secret_metadata_async( Get secret metadata Gets metadata of a secret. + + Swagger operation ID: `GetSecretMetadata`. + + Args: + secret_name: Name of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/secrets/{quote(str(secret_name), safe='')}/metadata" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -755,6 +1117,7 @@ async def get_secret_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -762,7 +1125,7 @@ async def get_secret_metadata_async( return json.loads(response.text) - async def get_secret_version_metadata_async( + def get_secret_version_metadata( self, secret_name: str, secret_version: str, @@ -776,6 +1139,22 @@ async def get_secret_version_metadata_async( Get secret version metadata Gets metadata of a version of a secret. + + Swagger operation ID: `GetSecretVersionMetadata`. + + Args: + secret_name: Name of the secret. + secret_version: Version of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -786,7 +1165,7 @@ async def get_secret_version_metadata_async( f"/metadata" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -800,6 +1179,7 @@ async def get_secret_version_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -807,7 +1187,7 @@ async def get_secret_version_metadata_async( return json.loads(response.text) - async def get_secret_async( + def get_secret( self, secret_name: str, *, @@ -821,13 +1201,28 @@ async def get_secret_async( Gets a secret. Output of this operation is typically classified as secret and can be visible in the run history. + + Swagger operation ID: `GetSecret`. + + Args: + secret_name: Name of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/secrets/{quote(str(secret_name), safe='')}/value" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -841,6 +1236,7 @@ async def get_secret_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -848,7 +1244,7 @@ async def get_secret_async( return json.loads(response.text) - async def get_secret_version_async( + def get_secret_version( self, secret_name: str, secret_version: str, @@ -863,6 +1259,22 @@ async def get_secret_version_async( Gets a version of a secret. Output of this operation is typically classified as secret and can be visible in the run history. + + Swagger operation ID: `GetSecretVersion`. + + Args: + secret_name: Name of the secret. + secret_version: Version of the secret. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -873,7 +1285,7 @@ async def get_secret_version_async( f"/value" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -887,6 +1299,7 @@ async def get_secret_version_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/kusto.py b/src/azure/connectors/kusto.py index d3017d6..0e81d70 100644 --- a/src/azure/connectors/kusto.py +++ b/src/azure/connectors/kusto.py @@ -5,21 +5,41 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, Dict, List, Literal, Any, Mapping from urllib.parse import quote import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.polling import LROPoller +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorPollingMethod, ) +__all__ = [ + "KustoClient", + "AsyncCommandResult", + "ChartType", + "ClusterName", + "CommandAndVisualizeSchema", + "ControlCommandAndListSchema", + "DatabaseName", + "MCPQueryRequest", + "MCPQueryResponse", + "ObjectEntity", + "Query", + "QueryAndListSchema", + "QueryAndVisualizeSchema", + "Row", + "Table", + "VisualizeResults", +] + # Type Definitions @@ -29,7 +49,12 @@ class Table: Response for Run KQL query """ - value: Optional[List[Row]] = None + value: Optional[ + List[Row | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -38,25 +63,29 @@ class VisualizeResults: Response for Run KQL query and render a chart """ - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """The body of the result in base64 encoding.""" - body_html: Optional[str] = field( + body_html: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "bodyHtml"}, ) """The body of the result in html encoding.""" - attachment_content: Optional[str] = field( + attachment_content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "attachmentContent"}, ) """The content of the attachment.""" - attachment_name: Optional[str] = field( + attachment_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "attachmentName"}, ) """The name of the attachment file.""" - kusto_deep_link: Optional[str] = field( + kusto_deep_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "kustoDeepLink"}, ) """Links to run the query in Kusto tools, for instance in KustoExplorer.""" @@ -68,12 +97,13 @@ class AsyncCommandResult: Response for Run async control command """ - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """The state of the command.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status of the command.""" - operation_id: Optional[str] = field( + operation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "operationId"}, ) """The operation ID of the control command""" @@ -85,12 +115,12 @@ class MCPQueryResponse: Response for Kusto Query MCP Server """ - jsonrpc: Optional[str] = None - id: Optional[str] = None - method: Optional[str] = None - params: Optional[Dict[str, Any]] = None - result: Optional[Dict[str, Any]] = None - error: Optional[Dict[str, Any]] = None + jsonrpc: Optional[str] = dataclass_field(default=None, kw_only=True) + id: Optional[str] = dataclass_field(default=None, kw_only=True) + method: Optional[str] = dataclass_field(default=None, kw_only=True) + params: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + result: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + error: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -99,7 +129,7 @@ class ObjectEntity: Response for Query schema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -112,7 +142,7 @@ class Row: Definition: Row """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -125,11 +155,10 @@ class QueryAndVisualizeSchema: Definition: QueryAndVisualizeSchema """ - cluster: Optional[ClusterName] = None - db: Optional[DatabaseName] = None - csl: Optional[Query] = None - chart_type: Optional[ChartType] = field( - default=None, + cluster: ClusterName + db: DatabaseName + csl: Query + chart_type: ChartType = dataclass_field( metadata={"wire_name": "chartType"}, ) @@ -140,12 +169,11 @@ class CommandAndVisualizeSchema: Definition: CommandAndVisualizeSchema """ - cluster: Optional[ClusterName] = None - db: Optional[DatabaseName] = None - csl: Optional[str] = None + cluster: ClusterName + db: DatabaseName + csl: str """Specify the control command you would like to run""" - chart_type: Optional[ChartType] = field( - default=None, + chart_type: ChartType = dataclass_field( metadata={"wire_name": "chartType"}, ) @@ -156,9 +184,9 @@ class QueryAndListSchema: Definition: QueryAndListSchema """ - cluster: Optional[ClusterName] = None - db: Optional[DatabaseName] = None - csl: Optional[Query] = None + cluster: ClusterName + db: DatabaseName + csl: Query @dataclass @@ -167,9 +195,9 @@ class ControlCommandAndListSchema: Definition: ControlCommandAndListSchema """ - cluster: Optional[ClusterName] = None - db: Optional[DatabaseName] = None - csl: Optional[str] = None + cluster: ClusterName + db: DatabaseName + csl: str """Specify the show control command you would like to run""" @@ -191,14 +219,15 @@ class MCPQueryRequest: Definition: MCPQueryRequest """ - jsonrpc: Optional[str] = None - id: Optional[str] = None - method: Optional[str] = None - params: Optional[Dict[str, Any]] = None - result: Optional[Dict[str, Any]] = None - error: Optional[Dict[str, Any]] = None - callback_endpoint: Optional[str] = field( + jsonrpc: Optional[str] = dataclass_field(default=None, kw_only=True) + id: Optional[str] = dataclass_field(default=None, kw_only=True) + method: Optional[str] = dataclass_field(default=None, kw_only=True) + params: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + result: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + error: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + callback_endpoint: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "callbackEndpoint"}, ) @@ -211,16 +240,16 @@ class KustoClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -231,8 +260,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -240,8 +269,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -253,7 +282,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -268,24 +297,43 @@ def __init__( def connector_name(self) -> str: return "kusto" - async def list_kusto_results_async( + def begin_list_kusto_results( self, - input: QueryAndListSchema, + input: QueryAndListSchema | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Run KQL query Runs the KQL query and returns the result as a set of rows which can be iterated over in the following connectors e.g TableName | take 10. + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `listKustoResultsPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/ListKustoResults/false" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -299,34 +347,67 @@ async def list_kusto_results_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def list_kusto_show_command_results_async( + def begin_list_kusto_show_command_results( self, - input: ControlCommandAndListSchema, + input: ControlCommandAndListSchema | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Run show control command Runs the show control command and returns the result as a set of rows which can be iterated over in the following connectors e.g .show table TableName policy caching. + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `listKustoShowCommandResultsPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/ListKustoShowCommandResults" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -340,33 +421,66 @@ async def list_kusto_show_command_results_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def run_kusto_query_and_visualize_results_async( + def begin_run_kusto_query_and_visualize_results( self, - input: QueryAndVisualizeSchema, + input: QueryAndVisualizeSchema | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Run KQL query and render a chart Runs the KQL query and returns result as a chart of your choice e.g TableName | where Timestamp > ago(1h) | project timestamp, value. + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `runKustoQueryAndVisualizeResultsPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/RunKustoAndVisualizeResults/false" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -380,33 +494,66 @@ async def run_kusto_query_and_visualize_results_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def run_kusto_command_and_visualize_results_async( + def begin_run_kusto_command_and_visualize_results( self, - input: CommandAndVisualizeSchema, + input: CommandAndVisualizeSchema | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Run control command and render a chart Runs the control command and returns the result as a chart of your choice e.g .clear table TableName data. + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `runKustoCommandAndVisualizeResultsPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/RunKustoAndVisualizeResults/true" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -420,34 +567,67 @@ async def run_kusto_command_and_visualize_results_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def run_async_control_command_and_wait_async( + def begin_run_async_control_command_and_wait( self, - input: ControlCommandAndListSchema, + input: ControlCommandAndListSchema | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Run async control command Runs control command in async mode and returns its ID, state and status on completion. Command can run for maximum 1 hour. The 'async' keyword is mandatory e.g .set-or-append async TargetTable <| SourceTable. + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `runAsyncControlCommandAndWait`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/RunAsyncControlCommandAndWait" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -461,18 +641,32 @@ async def run_async_control_command_and_wait_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def mcp_kusto_query_management_async( + def mcp_kusto_query_management( self, - input: MCPQueryRequest, - session_id: Optional[str] = None, + input: MCPQueryRequest | Mapping[str, Any], *, + session_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -482,6 +676,23 @@ async def mcp_kusto_query_management_async( Kusto Query MCP Server This MCP server runs Kusto queries and manages the results. + + Swagger operation ID: `mcp_KustoQueryManagement`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + session_id: sessionId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/mcp/KustoQueryManagement" @@ -495,7 +706,7 @@ async def mcp_kusto_query_management_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -509,6 +720,7 @@ async def mcp_kusto_query_management_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -516,9 +728,9 @@ async def mcp_kusto_query_management_async( return json.loads(response.text) - async def list_kusto_results_schema_async( + def list_kusto_results_schema( self, - input: QueryAndListSchema, + input: QueryAndListSchema | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -529,10 +741,26 @@ async def list_kusto_results_schema_async( Query schema Gets the schema for a query + + Swagger operation ID: `listKustoResultsSchemaPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/ListKustoResultsSchema" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -546,6 +774,7 @@ async def list_kusto_results_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/mailchimp.py b/src/azure/connectors/mailchimp.py index f0b9310..1ac4cb8 100644 --- a/src/azure/connectors/mailchimp.py +++ b/src/azure/connectors/mailchimp.py @@ -5,21 +5,64 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "MailchimpClient", + "ABSplitOpts", + "AddUserResponseModel", + "CampaignDefaults", + "CampaignResponseModel", + "Capsule", + "Contact", + "CreateNewListResponseModel", + "DailySend", + "DeliveryStatus", + "FirstAndLastName", + "GetAddMembersBatchResponseModel", + "GetAllMembersResponseModel", + "GetCampaignsResponse", + "GetListsResponseModel", + "GetMembersResponseModel", + "Highrise", + "LastNote", + "Link", + "Location", + "MemberResponseModel", + "NewCampaignRequest", + "NewListRequest", + "NewMemberInListRequest", + "NewMembersInListRequest", + "ObjectEntity", + "RSSOpts", + "Recipient", + "ReportSummary", + "Salesforce", + "Schedule", + "SegmentOpts", + "Settings", + "SocialCard", + "Stats", + "Tracking", + "UpdateMemberInListRequest", + "VariateSettings", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +72,12 @@ class GetCampaignsResponse: Response for List campaigns """ - campaigns: Optional[List[CampaignResponseModel]] = None + campaigns: Optional[ + List[CampaignResponseModel | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """An array of objects, each representing a campaign""" @@ -39,9 +87,14 @@ class GetListsResponseModel: Response for Get all the lists """ - lists: Optional[List[CreateNewListResponseModel]] = None + lists: Optional[ + List[CreateNewListResponseModel | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """An array of objects, each representing a list""" - total_items: Optional[int] = None + total_items: Optional[int] = dataclass_field(default=None, kw_only=True) """The total number of items matching the query regardless of pagination""" @@ -51,46 +104,47 @@ class CreateNewListResponseModel: Response for New List """ - id: Optional[str] = None + id: str """A string that uniquely identifies this list""" - name: Optional[str] = None + name: str """The name of the list""" - contact: Optional[Contact] = None - permission_reminder: Optional[str] = None + contact: Contact | Mapping[str, Any] + permission_reminder: str """The permission reminder for the list""" - use_archive_bar: Optional[bool] = None + use_archive_bar: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether campaigns for this list use the Archive Bar in archives by default """ - campaign_defaults: Optional[CampaignDefaults] = None - notify_on_subscribe: Optional[str] = None + campaign_defaults: CampaignDefaults | Mapping[str, Any] + notify_on_subscribe: Optional[str] = dataclass_field(default=None, kw_only=True) """The email address to send subscribe notifications to""" - notify_on_unsubscribe: Optional[str] = None + notify_on_unsubscribe: Optional[str] = dataclass_field(default=None, kw_only=True) """The email address to send unsubscribe notifications to""" - date_created: Optional[str] = None + date_created: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time that this list was created""" - list_rating: Optional[int] = None + list_rating: Optional[int] = dataclass_field(default=None, kw_only=True) """An auto-generated activity score for the list (0-5)""" - email_type_option: Optional[bool] = None + email_type_option: bool """ Whether the list supports multiple formats for emails.When set to true, subscribers can choose whether they want to receive HTML or plain-text emails.When set to false, subscribers will receive HTML emails, with a plain-text alternative backup """ - subscribe_url_short: Optional[str] = None + subscribe_url_short: Optional[str] = dataclass_field(default=None, kw_only=True) """Our EepURL shortened version of this list's subscribe form""" - subscribe_url_long: Optional[str] = None + subscribe_url_long: Optional[str] = dataclass_field(default=None, kw_only=True) """The full version of this list's subscribe form (host will vary)""" - beamer_address: Optional[str] = None + beamer_address: Optional[str] = dataclass_field(default=None, kw_only=True) """The list's Email Beamer address""" - visibility: Optional[str] = None + visibility: Optional[str] = dataclass_field(default=None, kw_only=True) """Whether this list is public or private""" - modules: Optional[List[str]] = None + modules: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Any list-specific modules installed for this list""" - stats: Optional[Stats] = None - links: Optional[List[Link]] = field( + stats: Optional[Stats | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + links: Optional[List[Link | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) """A list of link types and descriptions for the API schema documents""" @@ -102,14 +156,14 @@ class GetAddMembersBatchResponseModel: Response for Subscribe or unsubscribe list members """ - total_created: Optional[int] = None + total_created: Optional[int] = dataclass_field(default=None, kw_only=True) """Total number of members that were added to the list""" - total_updated: Optional[int] = None + total_updated: Optional[int] = dataclass_field(default=None, kw_only=True) """ The total number of an existing list members whose subscription status was updated """ - error_count: Optional[int] = None + error_count: Optional[int] = dataclass_field(default=None, kw_only=True) """ The number email addresses that could not be added to the list or updated """ @@ -121,11 +175,16 @@ class GetAllMembersResponseModel: Response for Show list members """ - members: Optional[List[MemberResponseModel]] = None + members: Optional[ + List[MemberResponseModel | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """An array of objects, each representing a specific list member""" - list_id: Optional[str] = None + list_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The list id""" - total_items: Optional[int] = None + total_items: Optional[int] = dataclass_field(default=None, kw_only=True) """The total number of items matching the query regardless of pagination""" @@ -135,47 +194,53 @@ class MemberResponseModel: Response for Add member to list """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ The MD5 hash of the lowercase version of the list member's email address """ - email_address: Optional[str] = None + email_address: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address for a subscriber""" - unique_email_id: Optional[str] = None + unique_email_id: Optional[str] = dataclass_field(default=None, kw_only=True) """An identifier for the address across all of MailChimp""" - email_type: Optional[str] = None + email_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Type of email this member asked to get ('html' or 'text').""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Subscriber's current status. Possible Values: subscribed, unsubscribed, cleaned, pending """ - merge_fields: Optional[FirstAndLastName] = None - stats: Optional[Stats] = None - ip_signup: Optional[str] = None + merge_fields: Optional[ + FirstAndLastName | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + stats: Optional[Stats | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + ip_signup: Optional[str] = dataclass_field(default=None, kw_only=True) """IP address the subscriber signed up from""" - timestamp_signup: Optional[str] = None + timestamp_signup: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time the subscriber signed up for the list""" - ip_opt: Optional[str] = None + ip_opt: Optional[str] = dataclass_field(default=None, kw_only=True) """The IP address the subscriber used to confirm their opt-in status""" - timestamp_opt: Optional[str] = None + timestamp_opt: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time the subscribe confirmed their opt-in status""" - member_rating: Optional[int] = None + member_rating: Optional[int] = dataclass_field(default=None, kw_only=True) """Star rating for this member, between 1 and 5""" - last_changed: Optional[str] = None + last_changed: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time the member's info was last changed""" - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """If set/detected, the subscriber's language""" - vip: Optional[bool] = None + vip: Optional[bool] = dataclass_field(default=None, kw_only=True) """VIP status for subscriber""" - email_client: Optional[str] = None + email_client: Optional[str] = dataclass_field(default=None, kw_only=True) """The list member's email client""" - location: Optional[Location] = None - last_note: Optional[LastNote] = None - list_id: Optional[str] = None + location: Optional[Location | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + last_note: Optional[LastNote | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + list_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The list id""" - links: Optional[List[Link]] = field( + links: Optional[List[Link | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) """A list of link types and descriptions for the API schema documents""" @@ -187,11 +252,16 @@ class GetMembersResponseModel: Response for When a Member has been added to a list """ - members: Optional[List[AddUserResponseModel]] = None + members: Optional[ + List[AddUserResponseModel | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """An array of objects, each representing a specific list member""" - list_id: Optional[str] = None + list_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The list id""" - total_items: Optional[int] = None + total_items: Optional[int] = dataclass_field(default=None, kw_only=True) """The total number of items matching the query regardless of pagination""" @@ -201,40 +271,75 @@ class CampaignResponseModel: Response for New Campaign """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """A string that uniquely identifies this campaign""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """ There are four types of campaigns you can create in MailChimp. A/B Split campaigns have been deprecated and variate campaigns should be used instead """ - create_time: Optional[str] = None + create_time: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time the campaign was created""" - archive_url: Optional[str] = None + archive_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The link to the campaign's archive version""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The current status of the campaign.""" - emails_sent: Optional[int] = None + emails_sent: Optional[int] = dataclass_field(default=None, kw_only=True) """The total number of emails sent for this campaign""" - send_time: Optional[str] = None + send_time: Optional[str] = dataclass_field(default=None, kw_only=True) """The time and date a campaign was sent""" - content_type: Optional[str] = None + content_type: Optional[str] = dataclass_field(default=None, kw_only=True) """ How the campaign's content is put together ('template', 'drag_and_drop', 'html', 'url') """ - recipient: Optional[List[Recipient]] = None + recipient: Optional[ + List[Recipient | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List settings for the campaign""" - settings: Optional[Settings] = None - variate_settings: Optional[VariateSettings] = None - tracking: Optional[Tracking] = None - rss_opts: Optional[RSSOpts] = None - ab_split_opts: Optional[ABSplitOpts] = None - social_card: Optional[SocialCard] = None - report_summary: Optional[ReportSummary] = None - delivery_status: Optional[DeliveryStatus] = None - links: Optional[List[Link]] = field( + settings: Optional[Settings | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + variate_settings: Optional[ + VariateSettings | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + tracking: Optional[Tracking | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + rss_opts: Optional[RSSOpts | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + ab_split_opts: Optional[ + ABSplitOpts | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + social_card: Optional[ + SocialCard | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + report_summary: Optional[ + ReportSummary | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, + ) + delivery_status: Optional[ + DeliveryStatus | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + links: Optional[List[Link | Mapping[str, Any]]] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) """A list of link types and descriptions for the API schema documents""" @@ -246,9 +351,14 @@ class Recipient: Definition: Recipient """ - list_id: Optional[str] = None + list_id: str """The unique list id""" - segment_opts: Optional[SegmentOpts] = None + segment_opts: Optional[ + SegmentOpts | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -257,7 +367,7 @@ class VariateSettings: Definition: Variate_Settings """ - winner_criteria: Optional[str] = None + winner_criteria: Optional[str] = dataclass_field(default=None, kw_only=True) """ The combination that performs the best. This may be determined automatically by click rate, open rate, or total revenue-or you may choose @@ -266,35 +376,35 @@ class VariateSettings: Multivariate Campaigns with 'manual' as the winner_criteria, the winner must be chosen in the MailChimp web application """ - wait_time: Optional[int] = None + wait_time: Optional[int] = dataclass_field(default=None, kw_only=True) """ The number of minutes to wait before choosing the winning campaign. The value of wait_time must be greater than 0 and in whole hours, specified in minutes """ - test_size: Optional[int] = None + test_size: Optional[int] = dataclass_field(default=None, kw_only=True) """ The percentage of recipients to send the test combinations to, must be a value between 10 and 100 """ - subject_lines: Optional[List[str]] = None + subject_lines: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ The possible subject lines to test. If no subject lines are provided, settings.subject_line will be used """ - send_times: Optional[List[str]] = None + send_times: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ The possible send times to test. The times provided should be in the format YYYY-MM-DD HH:MM:SS. If send_times are provided to test, the test_size will be set to 100% and winner_criteria will be ignored """ - from_names: Optional[List[str]] = None + from_names: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ The possible from names. The number of from_names provided must match the number of reply_to_addresses. If no from_names are provided, settings.from_name will be used """ - reply_to_addresses: Optional[List[str]] = None + reply_to_addresses: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ The possible from names. The number of from_names provided must match the number of reply_to_addresses. If no from_names are provided, @@ -308,32 +418,37 @@ class Tracking: Definition: Tracking """ - opens: Optional[bool] = None + opens: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether to track opens. Defaults to true. Cannot be set to false for variate campaigns """ - html_clicks: Optional[bool] = None + html_clicks: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether to track clicks in the HTML version of the campaign. Defaults to true. Cannot be set to false for variate campaigns """ - text_clicks: Optional[bool] = None + text_clicks: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether to track clicks in the plain-text version of the campaign. Defaults to true. Cannot be set to false for variate campaigns """ - goal_tracking: Optional[bool] = None + goal_tracking: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to enable Goal tracking""" - ecomm360: Optional[bool] = None + ecomm360: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to enable eCommerce360 tracking""" - google_analytics: Optional[str] = None + google_analytics: Optional[str] = dataclass_field(default=None, kw_only=True) """The custom slug for Google Analytics tracking (max of 50 bytes)""" - clicktale: Optional[str] = None + clicktale: Optional[str] = dataclass_field(default=None, kw_only=True) """The custom slug for ClickTale tracking (max of 50 bytes)""" - salesforce: Optional[Salesforce] = None - highrise: Optional[Highrise] = None - capsule: Optional[Capsule] = None + salesforce: Optional[ + Salesforce | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + highrise: Optional[Highrise | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + capsule: Optional[Capsule | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -342,16 +457,16 @@ class RSSOpts: Definition: RSS_Opts """ - feed_url: Optional[str] = None + feed_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The URL for the RSS feed""" - frequency: Optional[str] = None + frequency: Optional[str] = dataclass_field(default=None, kw_only=True) """The frequency of the RSS Campaign""" - constrain_rss_img: Optional[str] = None + constrain_rss_img: Optional[str] = dataclass_field(default=None, kw_only=True) """ Whether to add CSS to images in the RSS feed to constrain their width in campaigns """ - schedule: Optional[Schedule] = None + schedule: Optional[Schedule | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -360,11 +475,11 @@ class SocialCard: Definition: Social_Card """ - image_url: Optional[str] = None + image_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The url for the header image for the card""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """A short summary of the campaign to display""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title for the card. Typically the subject line of the campaign""" @@ -374,10 +489,11 @@ class SegmentOpts: Definition: Segment_Opts """ - saved_segment_id: Optional[int] = None + saved_segment_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The id for an existing saved segment""" - match_: Optional[str] = field( + match_: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "match"}, ) """Segment match type: Possible Values: any, all""" @@ -389,9 +505,9 @@ class Salesforce: Definition: Salesforce """ - campaign: Optional[bool] = None + campaign: Optional[bool] = dataclass_field(default=None, kw_only=True) """Create a campaign in a connected Salesforce account""" - notes: Optional[bool] = None + notes: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Update contact notes for a campaign based on subscriber email addresses """ @@ -403,9 +519,9 @@ class Highrise: Definition: Highrise """ - campaign: Optional[bool] = None + campaign: Optional[bool] = dataclass_field(default=None, kw_only=True) """Create a campaign in a connected Highrise account""" - notes: Optional[bool] = None + notes: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Update contact notes for a campaign based on subscriber email addresses """ @@ -417,7 +533,7 @@ class Capsule: Definition: Capsule """ - notes: Optional[bool] = None + notes: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Update contact notes for a campaign based on subscriber email addresses """ @@ -429,15 +545,20 @@ class Schedule: Definition: Schedule """ - hour: Optional[int] = None + hour: Optional[int] = dataclass_field(default=None, kw_only=True) """ The hour to send the campaign in local time. Acceptable hours are 0-23. For example, '4' would be 4am in your account's default time zone """ - daily_send: Optional[DailySend] = None - weekly_send_day: Optional[str] = None + daily_send: Optional[ + DailySend | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + weekly_send_day: Optional[str] = dataclass_field(default=None, kw_only=True) """The day of the week to send a weekly RSS Campaign""" - monthly_send_date: Optional[float] = None + monthly_send_date: Optional[float] = dataclass_field(default=None, kw_only=True) """ The day of the month to send a monthly RSS Campaign. Acceptable days are 1-32, where '0' is always the last day of a month. Months with fewer than @@ -453,19 +574,19 @@ class DailySend: Definition: Daily_Send """ - sunday: Optional[bool] = None + sunday: Optional[bool] = dataclass_field(default=None, kw_only=True) """Sends the daily RSS Campaign on Sundays""" - monday: Optional[bool] = None + monday: Optional[bool] = dataclass_field(default=None, kw_only=True) """Sends the daily RSS Campaign on Mondays""" - tuesday: Optional[bool] = None + tuesday: Optional[bool] = dataclass_field(default=None, kw_only=True) """Sends the daily RSS Campaign on Tuesdays""" - wednesday: Optional[bool] = None + wednesday: Optional[bool] = dataclass_field(default=None, kw_only=True) """Sends the daily RSS Campaign on Wednesdays""" - thursday: Optional[bool] = None + thursday: Optional[bool] = dataclass_field(default=None, kw_only=True) """Sends the daily RSS Campaign on Thursdays""" - friday: Optional[bool] = None + friday: Optional[bool] = dataclass_field(default=None, kw_only=True) """Sends the daily RSS Campaign on Fridays""" - saturday: Optional[bool] = None + saturday: Optional[bool] = dataclass_field(default=None, kw_only=True) """Sends the daily RSS Campaign on Saturdays""" @@ -475,34 +596,34 @@ class Settings: Definition: Settings """ - subject_line: Optional[str] = None + subject_line: str """The subject line for the campaign""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the campaign""" - from_name: Optional[str] = None + from_name: str """The 'from' name on the campaign (not an email address)""" - reply_to: Optional[str] = None + reply_to: str """The reply-to email address for the campaign""" - use_conversation: Optional[bool] = None + use_conversation: Optional[bool] = dataclass_field(default=None, kw_only=True) """Use MailChimp Conversation feature to manage out-of-office replies""" - to_name: Optional[str] = None + to_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The campaign's custom 'To' name. Typically the first name merge field""" - folder_id: Optional[str] = None + folder_id: Optional[str] = dataclass_field(default=None, kw_only=True) """If the campaign is listed in a folder, the id for that folder""" - authenticate: Optional[bool] = None + authenticate: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether MailChimp authenticated the campaign. Defaults to true""" - auto_footer: Optional[bool] = None + auto_footer: Optional[bool] = dataclass_field(default=None, kw_only=True) """Automatically append MailChimp's default footer to the campaign""" - inline_css: Optional[bool] = None + inline_css: Optional[bool] = dataclass_field(default=None, kw_only=True) """Automatically inline the CSS included with the campaign content""" - auto_tweet: Optional[bool] = None + auto_tweet: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Automatically tweet a link to the campaign archive page when the campaign is sent """ - auto_fb_post: Optional[List[int]] = None + auto_fb_post: Optional[List[int]] = dataclass_field(default=None, kw_only=True) """An array of Facebook page ids to auto-post to""" - fb_comments: Optional[bool] = None + fb_comments: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Allows Facebook comments on the campaign (also force-enables the Campaign Archive toolbar). Defaults to true @@ -515,44 +636,44 @@ class ABSplitOpts: Definition: AB_Split_Opts """ - split_test: Optional[str] = None + split_test: Optional[str] = dataclass_field(default=None, kw_only=True) """The type of AB split to run""" - pick_winner: Optional[str] = None + pick_winner: Optional[str] = dataclass_field(default=None, kw_only=True) """ How we should evaluate a winner. Based on 'opens', 'clicks', or 'manual' """ - wait_units: Optional[str] = None + wait_units: Optional[str] = dataclass_field(default=None, kw_only=True) """ How unit of time for measuring the winner ('hours' or 'days'). This cannot be changed after a campaign is sent """ - wait_time: Optional[int] = None + wait_time: Optional[int] = dataclass_field(default=None, kw_only=True) """ The amount of time to wait before picking a winner. This cannot be changed after a campaign is sent """ - split_size: Optional[int] = None + split_size: Optional[int] = dataclass_field(default=None, kw_only=True) """ The size of the split groups. Campaigns split based on 'schedule' are forced to have a 50/50 split. Valid split integers are between 1-50 """ - from_name_a: Optional[str] = None + from_name_a: Optional[str] = dataclass_field(default=None, kw_only=True) """For campaigns split on 'From Name', the name for Group A""" - from_name_b: Optional[str] = None + from_name_b: Optional[str] = dataclass_field(default=None, kw_only=True) """For campaigns split on 'From Name', the name for Group B""" - reply_email_a: Optional[str] = None + reply_email_a: Optional[str] = dataclass_field(default=None, kw_only=True) """For campaigns split on 'From Name', the reply-to address for Group A""" - reply_email_b: Optional[str] = None + reply_email_b: Optional[str] = dataclass_field(default=None, kw_only=True) """For campaigns split on 'From Name', the reply-to address for Group B""" - subject_a: Optional[str] = None + subject_a: Optional[str] = dataclass_field(default=None, kw_only=True) """For campaigns split on 'Subject Line', the subject line for Group A""" - subject_b: Optional[str] = None + subject_b: Optional[str] = dataclass_field(default=None, kw_only=True) """For campaigns split on 'Subject Line', the subject line for Group B""" - send_time_a: Optional[str] = None + send_time_a: Optional[str] = dataclass_field(default=None, kw_only=True) """The send time for Group A""" - send_time_b: Optional[str] = None + send_time_b: Optional[str] = dataclass_field(default=None, kw_only=True) """The send time for Group B""" - send_time_winner: Optional[str] = None + send_time_winner: Optional[str] = dataclass_field(default=None, kw_only=True) """The send time for the winning version""" @@ -562,20 +683,20 @@ class ReportSummary: Definition: Report_Summary """ - opens: Optional[int] = None + opens: Optional[int] = dataclass_field(default=None, kw_only=True) """The total number of opens for a campaign""" - unique_opens: Optional[int] = None + unique_opens: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of unique opens""" - open_rate: Optional[float] = None + open_rate: Optional[float] = dataclass_field(default=None, kw_only=True) """ The number of unique opens divided by the total number of successful deliveries """ - clicks: Optional[int] = None + clicks: Optional[int] = dataclass_field(default=None, kw_only=True) """The total number of clicks for an campaign""" - subscriber_clicks: Optional[float] = None + subscriber_clicks: Optional[float] = dataclass_field(default=None, kw_only=True) """The number of unique clicks""" - click_rate: Optional[float] = None + click_rate: Optional[float] = dataclass_field(default=None, kw_only=True) """ The number of unique clicks divided by the total number of successful deliveries @@ -588,17 +709,17 @@ class DeliveryStatus: Definition: Delivery_Status """ - enabled: Optional[bool] = None + enabled: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether Campaign Delivery Status is enabled for this account and campaign """ - can_cancel: Optional[bool] = None + can_cancel: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether a campaign send can be canceled""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The current state of a campaign delivery""" - emails_sent: Optional[int] = None + emails_sent: Optional[int] = dataclass_field(default=None, kw_only=True) """The total number of emails confirmed sent for this campaign so far""" - emails_canceled: Optional[int] = None + emails_canceled: Optional[int] = dataclass_field(default=None, kw_only=True) """The total number of emails canceled for this campaign""" @@ -608,27 +729,28 @@ class Link: Definition: Link """ - rel: Optional[str] = None + rel: Optional[str] = dataclass_field(default=None, kw_only=True) """As with an HTML 'rel' attribute, this describes the type of link""" - href: Optional[str] = None + href: Optional[str] = dataclass_field(default=None, kw_only=True) """ This property contains a fully-qualified URL that can be called to retrieve the linked resource or perform the linked action """ - method: Optional[str] = None + method: Optional[str] = dataclass_field(default=None, kw_only=True) """ The HTTP method that should be used when accessing the URL defined in 'href'. (GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD) """ - target_schema: Optional[str] = field( + target_schema: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "targetSchema"}, ) """ For GETs, this is a URL representing the schema that the response should conform to """ - schema: Optional[str] = None + schema: Optional[str] = dataclass_field(default=None, kw_only=True) """ For HTTP methods that can receive bodies (POST and PUT), this is a URL representing the schema that the body should conform to @@ -641,18 +763,28 @@ class NewCampaignRequest: Definition: NewCampaignRequest """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """ There are four types of campaigns you can create in MailChimp. A/B Split campaigns have been deprecated and variate campaigns should be used instead. Possible Values: regular, plaintext, absplit, rss, variate """ - recipients: Optional[Recipient] = None - settings: Optional[Settings] = None - variate_settings: Optional[VariateSettings] = None - tracking: Optional[Tracking] = None - rss_opts: Optional[RSSOpts] = None - social_card: Optional[SocialCard] = None + recipients: Recipient | Mapping[str, Any] + settings: Settings | Mapping[str, Any] + variate_settings: Optional[ + VariateSettings | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + tracking: Optional[Tracking | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + rss_opts: Optional[RSSOpts | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + social_card: Optional[ + SocialCard | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -661,27 +793,27 @@ class NewListRequest: Definition: NewListRequest """ - name: Optional[str] = None + name: str """The name of the list""" - contact: Optional[Contact] = None - permission_reminder: Optional[str] = None + contact: Contact | Mapping[str, Any] + permission_reminder: str """Text to remind people how they signed up to this list""" - use_archive_bar: Optional[bool] = None + use_archive_bar: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether campaigns for this list use the Archive Bar in archives by default """ - campaign_defaults: Optional[CampaignDefaults] = None - notify_on_subscribe: Optional[str] = None + campaign_defaults: CampaignDefaults | Mapping[str, Any] + notify_on_subscribe: Optional[str] = dataclass_field(default=None, kw_only=True) """The email address to send subscribe notifications to""" - notify_on_unsubscribe: Optional[str] = None + notify_on_unsubscribe: Optional[str] = dataclass_field(default=None, kw_only=True) """The email address to send unsubscribe notifications to""" - email_type_option: Optional[bool] = None + email_type_option: bool """ When set to true, subscribers can choose whether they want to receive HTML or plain-text emails. When set to false, subscribers will receive HTML emails, with a plain-text alternative backup """ - visibility: Optional[str] = None + visibility: Optional[str] = dataclass_field(default=None, kw_only=True) """Whether this list is public or private""" @@ -691,21 +823,21 @@ class Contact: Definition: Contact """ - company: Optional[str] = None + company: str """The company name for the list""" - address1: Optional[str] = None + address1: str """The street address for the list contact""" - address2: Optional[str] = None + address2: Optional[str] = dataclass_field(default=None, kw_only=True) """The street address for the list contact""" - city: Optional[str] = None + city: str """The city for the list contact""" - state: Optional[str] = None + state: str """The state for the list contact""" - zip: Optional[str] = None + zip: str """The postal or zip code for the list contact""" - country: Optional[str] = None + country: str """A two-character ISO3166 country code. Defaults to US if invalid""" - phone: Optional[str] = None + phone: str """The phone number for the list contact""" @@ -715,13 +847,13 @@ class CampaignDefaults: Definition: Campaign_Defaults """ - from_name: Optional[str] = None + from_name: str """The default from name for campaigns sent to this list""" - from_email: Optional[str] = None + from_email: str """The default from email for campaigns sent to this list""" - subject: Optional[str] = None + subject: str """The default subject line for campaigns sent to this list""" - language: Optional[str] = None + language: str """The default language for this list's forms""" @@ -731,62 +863,62 @@ class Stats: Definition: Stats """ - member_count: Optional[int] = None + member_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of active members in the list""" - unsubscribe_count: Optional[int] = None + unsubscribe_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of members who have unsubscribed from the list""" - cleaned_count: Optional[int] = None + cleaned_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of members cleaned from the list""" - member_count_since_send: Optional[int] = None + member_count_since_send: Optional[int] = dataclass_field(default=None, kw_only=True) """ The number of active members in the list since the last campaign was sent """ - unsubscribe_count_since_send: Optional[int] = None + unsubscribe_count_since_send: Optional[int] = dataclass_field(default=None, kw_only=True) """ The number of members who have unsubscribed since the last campaign was sent """ - cleaned_count_since_send: Optional[int] = None + cleaned_count_since_send: Optional[int] = dataclass_field(default=None, kw_only=True) """ The number of members cleaned from the list since the last campaign was sent """ - campaign_count: Optional[int] = None + campaign_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of campaigns in any status that use this list""" - campaign_last_sent: Optional[str] = None + campaign_last_sent: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time the last campaign was sent to this list""" - merge_field_count: Optional[int] = None + merge_field_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of merge vars for this list (not EMAIL, which is required)""" - avg_sub_rate: Optional[float] = None + avg_sub_rate: Optional[float] = dataclass_field(default=None, kw_only=True) """ The average number of subscriptions per month for the list(not returned if we haven't calculated it yet) """ - avg_unsub_rate: Optional[float] = None + avg_unsub_rate: Optional[float] = dataclass_field(default=None, kw_only=True) """ The average number of unsubscriptions per month for the list(not returned if we haven't calculated it yet) """ - target_sub_rate: Optional[float] = None + target_sub_rate: Optional[float] = dataclass_field(default=None, kw_only=True) """ The target number of subscriptions per month for the list to keep it growing(not returned if we haven't calculated it yet) """ - open_rate: Optional[float] = None + open_rate: Optional[float] = dataclass_field(default=None, kw_only=True) """ The average open rate(a percentage represented as a number between 0 and 100) per campaign for the list(not returned if we haven't calculated it yet) """ - click_rate: Optional[float] = None + click_rate: Optional[float] = dataclass_field(default=None, kw_only=True) """ The average click rate(a percentage represented as a number between 0 and 100) per campaign for the list(not returned if we haven't calculated it yet) """ - last_sub_date: Optional[str] = None + last_sub_date: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time of the last time someone subscribed to this list""" - last_unsub_date: Optional[str] = None + last_unsub_date: Optional[str] = dataclass_field(default=None, kw_only=True) """ The date and time of the last time someone unsubscribed from this list """ @@ -798,13 +930,13 @@ class NewMembersInListRequest: Definition: NewMembersInListRequest """ - members: Optional[List[NewMemberInListRequest]] = None + members: List[NewMemberInListRequest | Mapping[str, Any]] """ An array of objects, each representing an email address and the subscription status for a specific list. Up to 500 members may be added or updated with each API call. """ - update_existing: Optional[bool] = None + update_existing: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether this batch operation will change existing members' subscription status. @@ -817,20 +949,25 @@ class NewMemberInListRequest: Definition: NewMemberInListRequest """ - email_type: Optional[str] = None + email_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Type of email this member asked to get ('html' or 'text')""" - status: Optional[str] = None + status: str """ Subscriber's current status. Possible Values: subscribed, unsubscribed, cleaned, pending """ - merge_fields: Optional[FirstAndLastName] = None - language: Optional[str] = None + merge_fields: Optional[ + FirstAndLastName | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + language: Optional[str] = dataclass_field(default=None, kw_only=True) """If set/detected, the subscriber's language""" - vip: Optional[bool] = None + vip: Optional[bool] = dataclass_field(default=None, kw_only=True) """VIP status for subscriber""" - location: Optional[Location] = None - email_address: Optional[str] = None + location: Optional[Location | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + email_address: str """Email address for a subscriber""" @@ -840,13 +977,15 @@ class FirstAndLastName: Definition: FirstAndLastName """ - f_n_a_m_e: Optional[str] = field( + f_n_a_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FNAME"}, ) """First name of the subscriber""" - l_n_a_m_e: Optional[str] = field( + l_n_a_m_e: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LNAME"}, ) """Last name of the subscriber""" @@ -858,9 +997,9 @@ class Location: Definition: Location """ - latitude: Optional[float] = None + latitude: Optional[float] = dataclass_field(default=None, kw_only=True) """The location latitude""" - longitude: Optional[float] = None + longitude: Optional[float] = dataclass_field(default=None, kw_only=True) """The location longitude""" @@ -870,13 +1009,13 @@ class LastNote: Definition: Last_Note """ - note_id: Optional[int] = None + note_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The note id""" - created_at: Optional[str] = None + created_at: Optional[str] = dataclass_field(default=None, kw_only=True) """The date the note was created""" - created_by: Optional[str] = None + created_by: Optional[str] = dataclass_field(default=None, kw_only=True) """The author of the note""" - note: Optional[str] = None + note: Optional[str] = dataclass_field(default=None, kw_only=True) """The content of the note""" @@ -886,7 +1025,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -899,19 +1038,24 @@ class UpdateMemberInListRequest: Definition: UpdateMemberInListRequest """ - email_type: Optional[str] = None + email_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Type of email this member asked to get ('html' or 'text')""" - status: Optional[str] = None + status: str """ Subscriber's current status. Possible Values: subscribed, unsubscribed, cleaned, pending """ - merge_fields: Optional[FirstAndLastName] = None - language: Optional[str] = None + merge_fields: Optional[ + FirstAndLastName | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + language: Optional[str] = dataclass_field(default=None, kw_only=True) """If set/detected, the subscriber's language""" - vip: Optional[bool] = None + vip: Optional[bool] = dataclass_field(default=None, kw_only=True) """VIP status for subscriber""" - location: Optional[Location] = None + location: Optional[Location | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -920,47 +1064,48 @@ class AddUserResponseModel: Definition: AddUserResponseModel """ - id: Optional[str] = None + id: str """ The MD5 hash of the lowercase version of the list member's email address """ - email_address: Optional[str] = None + email_address: str """Email address for a subscriber""" - unique_email_id: Optional[str] = None + unique_email_id: Optional[str] = dataclass_field(default=None, kw_only=True) """An identifier for the address across all of MailChimp""" - email_type: Optional[str] = None + email_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Type of email this member asked to get ('html' or 'text').""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Subscriber's current status. Possible Values: subscribed, unsubscribed, cleaned, pending """ - merge_fields: Optional[FirstAndLastName] = None - stats: Optional[Stats] = None - ip_signup: Optional[str] = None + merge_fields: FirstAndLastName | Mapping[str, Any] + stats: Optional[Stats | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + ip_signup: Optional[str] = dataclass_field(default=None, kw_only=True) """IP address the subscriber signed up from""" - timestamp_signup: Optional[str] = None + timestamp_signup: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time the subscriber signed up for the list""" - ip_opt: Optional[str] = None + ip_opt: Optional[str] = dataclass_field(default=None, kw_only=True) """The IP address the subscriber used to confirm their opt-in status""" - timestamp_opt: Optional[str] = None + timestamp_opt: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time the subscribe confirmed their opt-in status""" - member_rating: Optional[int] = None + member_rating: Optional[int] = dataclass_field(default=None, kw_only=True) """Star rating for this member, between 1 and 5""" - last_changed: Optional[str] = None + last_changed: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time the member's info was last changed""" - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """If set/detected, the subscriber's language""" - vip: Optional[bool] = None + vip: Optional[bool] = dataclass_field(default=None, kw_only=True) """VIP status for subscriber""" - email_client: Optional[str] = None + email_client: Optional[str] = dataclass_field(default=None, kw_only=True) """The list member's email client""" - location: Optional[Location] = None - last_note: Optional[LastNote] = None - list_id: Optional[str] = None + location: Optional[Location | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + last_note: Optional[LastNote | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + list_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The list id""" - links: Optional[List[Link]] = field( + links: Optional[List[Link | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) """A list of link types and descriptions for the API schema documents""" @@ -974,16 +1119,16 @@ class MailchimpClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -994,8 +1139,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -1003,8 +1148,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -1016,7 +1161,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -1031,43 +1176,121 @@ def __init__( def connector_name(self) -> str: return "mailchimp" - async def get_campaigns_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_campaigns( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List campaigns This operation retrieves a list of campaigns in an account + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetCampaigns`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/campaigns" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("campaigns", []): + yield item - async def sendcampaign_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def sendcampaign( self, campaign_id: str, *, @@ -1080,13 +1303,28 @@ async def sendcampaign_async( Send Campaign Send an existing campaign + + Swagger operation ID: `sendcampaign`. + + Args: + campaign_id: The unique id for the list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/campaigns/{quote(str(campaign_id), safe='')}/actions/send" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1100,13 +1338,14 @@ async def sendcampaign_async( request_url, response.status, response.text, + response=response, ) - async def get_lists_async( + def get_lists( self, + *, count: Optional[int] = None, offset: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1116,6 +1355,24 @@ async def get_lists_async( Get all the lists Find all the lists for the current user + + Swagger operation ID: `GetLists`. + + Args: + count: The number of records to return. Default value is 10. + Maximum value is 1000. + offset: The number of records from a collection to skip. Default + value is 0. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/lists" query_params = [] @@ -1132,7 +1389,7 @@ async def get_lists_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1146,6 +1403,7 @@ async def get_lists_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1153,9 +1411,9 @@ async def get_lists_async( return json.loads(response.text) - async def newlist_async( + def newlist( self, - input: NewListRequest, + input: NewListRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1166,10 +1424,26 @@ async def newlist_async( New List Create a new list in your MailChimp account + + Swagger operation ID: `newlist`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/lists" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1183,6 +1457,7 @@ async def newlist_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1190,13 +1465,13 @@ async def newlist_async( return json.loads(response.text) - async def add_members_async( + def add_members( self, - input: NewMembersInListRequest, + input: NewMembersInListRequest | Mapping[str, Any], list_id: str, + *, skip_merge_validation: Optional[bool] = None, skip_duplicate_check: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1206,6 +1481,26 @@ async def add_members_async( Subscribe or unsubscribe list members Batch subscribe or unsubscribe list members. + + Swagger operation ID: `AddMembers`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + list_id: The unique id for the list. + skip_merge_validation: Allows member data to be accepted without + merge field values. + skip_duplicate_check: Ignores duplicates sent in the request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1225,7 +1520,7 @@ async def add_members_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1239,6 +1534,7 @@ async def add_members_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1246,12 +1542,12 @@ async def add_members_async( return json.loads(response.text) - async def get_list_members_async( + def get_list_members( self, list_id: str, + *, count: Optional[int] = None, offset: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1261,6 +1557,25 @@ async def get_list_members_async( Show list members Show all the members of a list + + Swagger operation ID: `GetListMembers`. + + Args: + list_id: The unique id for the list. + count: The number of records to return. Default value is 10. + Maximum value is 1000. + offset: The number of records from a collection to skip. Default + value is 0. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1280,7 +1595,7 @@ async def get_list_members_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1294,6 +1609,7 @@ async def get_list_members_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1301,9 +1617,9 @@ async def get_list_members_async( return json.loads(response.text) - async def addmember_async( + def addmember( self, - input: NewMemberInListRequest, + input: NewMemberInListRequest | Mapping[str, Any], list_id: str, *, timeout: Optional[float] = None, @@ -1315,13 +1631,30 @@ async def addmember_async( Add member to list Add or update a list member + + Swagger operation ID: `addmember`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + list_id: The unique id for the list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/lists/{quote(str(list_id), safe='')}/members" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1335,6 +1668,7 @@ async def addmember_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1342,9 +1676,9 @@ async def addmember_async( return json.loads(response.text) - async def newcampaign_async( + def newcampaign( self, - input: NewCampaignRequest, + input: NewCampaignRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1356,10 +1690,26 @@ async def newcampaign_async( Create a new campaign based on a Campaign Type, Recipients list and Campaign Settings (subject line, title, from_name and reply_to). + + Swagger operation ID: `newcampaignV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/campaigns" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1373,6 +1723,7 @@ async def newcampaign_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1380,7 +1731,7 @@ async def newcampaign_async( return json.loads(response.text) - async def removemember_async( + def removemember( self, list_id: str, *, @@ -1393,6 +1744,21 @@ async def removemember_async( Remove Member from list Delete a member from a list. + + Swagger operation ID: `removemember_v2`. + + Args: + list_id: The unique id for the list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1402,7 +1768,7 @@ async def removemember_async( f"/members" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1416,11 +1782,12 @@ async def removemember_async( request_url, response.status, response.text, + response=response, ) - async def updatemember_async( + def updatemember( self, - input: UpdateMemberInListRequest, + input: UpdateMemberInListRequest | Mapping[str, Any], list_id: str, *, timeout: Optional[float] = None, @@ -1432,6 +1799,23 @@ async def updatemember_async( Update member information Update information for a specific list member. + + Swagger operation ID: `updatemember_v2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + list_id: The unique id for the list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1441,7 +1825,7 @@ async def updatemember_async( f"/members" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -1455,6 +1839,7 @@ async def updatemember_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/meetingroommap.py b/src/azure/connectors/meetingroommap.py index 4cbdf09..cbed330 100644 --- a/src/azure/connectors/meetingroommap.py +++ b/src/azure/connectors/meetingroommap.py @@ -5,21 +5,35 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "MeetingroommapClient", + "AADMeetingRoom", + "AADMeetingRoomCollection", + "GetCustomLocationListByImageNameQuery", + "GetCustomLocationsByCategoriesQuery", + "GetCustomLocationsByImageNameResponse", + "GetOfficeLocationsByImageResponse", + "GetRoomWithPersonsDetailsResponse", + "GetRoomsByImageNameResponse", + "UserDetailsDTO", +] + # Type Definitions @@ -29,13 +43,15 @@ class GetCustomLocationsByImageNameResponse: Response for Get locations by image """ - custom_location_collection: Optional[List[Dict[str, Any]]] = field( + custom_location_collection: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customLocationCollection"}, ) """customLocationCollection""" - map_image: Optional[Dict[str, Any]] = field( + map_image: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mapImage"}, ) """mapImage""" @@ -47,10 +63,11 @@ class GetOfficeLocationsByImageResponse: Response for Get office locations on image """ - image: Optional[Dict[str, Any]] = None + image: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """image""" - attached_office_locations: Optional[List[Dict[str, Any]]] = field( + attached_office_locations: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "attachedOfficeLocations"}, ) """attachedOfficeLocations""" @@ -62,13 +79,15 @@ class GetRoomWithPersonsDetailsResponse: Response for Get office location details """ - office_location_map: Optional[Dict[str, Any]] = field( + office_location_map: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "officeLocationMap"}, ) """officeLocationMap""" - map_image: Optional[Dict[str, Any]] = field( + map_image: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mapImage"}, ) """mapImage""" @@ -80,7 +99,12 @@ class AADMeetingRoomCollection: Response for Get all rooms """ - rooms: Optional[List[AADMeetingRoom]] = None + rooms: Optional[ + List[AADMeetingRoom | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -89,13 +113,15 @@ class GetRoomsByImageNameResponse: Response for Get all meeting rooms by image """ - meeting_room_collection: Optional[Dict[str, Any]] = field( + meeting_room_collection: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "meetingRoomCollection"}, ) """meetingRoomCollection""" - map_image: Optional[Dict[str, Any]] = field( + map_image: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mapImage"}, ) """mapImage""" @@ -107,7 +133,7 @@ class GetCustomLocationsByCategoriesQuery: Definition: GetCustomLocationsByCategoriesQuery """ - categories: Optional[List[str]] = None + categories: Optional[List[str]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -116,12 +142,9 @@ class GetCustomLocationListByImageNameQuery: Definition: GetCustomLocationListByImageNameQuery """ - image_name: Optional[str] = field( - default=None, - metadata={"wire_name": "imageName"}, - ) + image_name: str = dataclass_field(metadata={"wire_name": "imageName"}) """The unique image name""" - categories: Optional[List[str]] = None + categories: Optional[List[str]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -130,8 +153,8 @@ class AADMeetingRoom: Definition: AADMeetingRoom """ - name: Optional[str] = None - address: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + address: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -140,11 +163,12 @@ class UserDetailsDTO: Definition: UserDetailsDTO """ - tenant_id: Optional[str] = field( + tenant_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tenantId"}, ) - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) # Client Class @@ -155,16 +179,16 @@ class MeetingroommapClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -175,8 +199,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -184,8 +208,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -197,7 +221,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -212,9 +236,48 @@ def __init__( def connector_name(self) -> str: return "meetingroommap" - async def get_custom_locations_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def get_custom_locations( self, - input: GetCustomLocationsByCategoriesQuery, + input: GetCustomLocationsByCategoriesQuery | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -225,13 +288,29 @@ async def get_custom_locations_async( Get all custom locations Get all custom locations + + Swagger operation ID: `GetCustomLocations`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/CustomLocations/GetCustomLocations" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -245,11 +324,12 @@ async def get_custom_locations_async( request_url, response.status, response.text, + response=response, ) - async def get_custom_locations_by_image_name_async( + def get_custom_locations_by_image_name( self, - input: GetCustomLocationListByImageNameQuery, + input: GetCustomLocationListByImageNameQuery | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -260,13 +340,29 @@ async def get_custom_locations_by_image_name_async( Get locations by image Get all custom locations for a given image + + Swagger operation ID: `GetCustomLocationsByImageName`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/CustomLocations/GetCustomLocationsByImageName" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -280,6 +376,7 @@ async def get_custom_locations_by_image_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -287,45 +384,84 @@ async def get_custom_locations_by_image_name_async( return json.loads(response.text) - async def get_categories_async( + def list_categories( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[str]: """ GetCategories Get custom categories + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetCategories`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[str]: An Azure Core pager over connector results. Consume + it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/api/CustomLocations/categories" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[str]: + for item in page: + yield item - async def location_details_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def location_details( self, location_id: str, *, @@ -338,13 +474,28 @@ async def location_details_async( Get location by id Get location details including image url by the location id + + Swagger operation ID: `LocationDetails`. + + Args: + location_id: Location identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/CustomLocations/{quote(str(location_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -358,22 +509,43 @@ async def location_details_async( request_url, response.status, response.text, + response=response, ) - async def search_locations_async( + def list_search_locations( self, location_name: str, - category: Optional[str] = None, *, + category: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Search location by name Search custom locations by name + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SearchLocations`. + + Args: + location_name: Search string for location. + category: Optional category filter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -390,33 +562,54 @@ async def search_locations_async( query_params.append(f"Category={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_custom_location_image_async( + def get_custom_location_image( self, location_id: str, - large: Optional[bool] = None, *, + large: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -426,6 +619,22 @@ async def get_custom_location_image_async( Get image for location Get image for specific custom location + + Swagger operation ID: `GetCustomLocationImage`. + + Args: + location_id: Unique identifier for location. + large: Large image returned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -443,7 +652,7 @@ async def get_custom_location_image_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -457,51 +666,91 @@ async def get_custom_location_image_async( request_url, response.status, response.text, + response=response, ) return response.content - async def images_async( + def list_images( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get all images Get list of all floorplans/images + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Images`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/MapImage/thumbnails" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def get_meeting_room_image_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_meeting_room_image( self, room_name: str, - large: Optional[bool] = None, *, + large: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -511,6 +760,22 @@ async def get_meeting_room_image_async( Get image for meeting room Get image for a specific meeting room + + Swagger operation ID: `GetMeetingRoomImage`. + + Args: + room_name: The name of the room to get image for. + large: Large image. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -525,7 +790,7 @@ async def get_meeting_room_image_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -539,11 +804,12 @@ async def get_meeting_room_image_async( request_url, response.status, response.text, + response=response, ) return response.content - async def next_meetings_async( + def next_meetings( self, meeting_count: int, *, @@ -556,6 +822,21 @@ async def next_meetings_async( Get next meetings Get the next meetings for the current user + + Swagger operation ID: `NextMeetings`. + + Args: + meeting_count: Count of meetings. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -566,7 +847,7 @@ async def next_meetings_async( f"/roomdetails" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -580,9 +861,10 @@ async def next_meetings_async( request_url, response.status, response.text, + response=response, ) - async def get_meeting_room_details_async( + def get_meeting_room_details( self, room_name: str, *, @@ -595,13 +877,28 @@ async def get_meeting_room_details_async( Get meetingroom details Get meetingroom details + + Swagger operation ID: `GetMeetingRoomDetails`. + + Args: + room_name: The room name to get details for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/MapImage/roomdetails_v2/{quote(str(room_name), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -615,9 +912,10 @@ async def get_meeting_room_details_async( request_url, response.status, response.text, + response=response, ) - async def get_office_locations_async( + def get_office_locations( self, *, timeout: Optional[float] = None, @@ -629,10 +927,24 @@ async def get_office_locations_async( Get all office locations Get all office locations + + Swagger operation ID: `GetOfficeLocations`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/officelocations" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -646,9 +958,10 @@ async def get_office_locations_async( request_url, response.status, response.text, + response=response, ) - async def search_coworkers_async( + def list_search_coworkers( self, person_search: str, *, @@ -656,11 +969,30 @@ async def search_coworkers_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Search coworker Search coworker by name/email + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SearchCoworkers`. + + Args: + person_search: Search string. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -669,29 +1001,50 @@ async def search_coworkers_async( f"/searchCoworkers" f"/{quote(str(person_search), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_office_locations_by_image_async( + def get_office_locations_by_image( self, image_name: str, *, @@ -704,6 +1057,21 @@ async def get_office_locations_by_image_async( Get office locations on image Get all office locations mapped to a specific image + + Swagger operation ID: `GetOfficeLocationsByImage`. + + Args: + image_name: The image identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -713,7 +1081,7 @@ async def get_office_locations_by_image_async( f"/{quote(str(image_name), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -727,6 +1095,7 @@ async def get_office_locations_by_image_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -734,11 +1103,11 @@ async def get_office_locations_by_image_async( return json.loads(response.text) - async def get_room_with_persons_details_async( + def get_room_with_persons_details( self, office_location_name: str, - inlude_user_info: Optional[bool] = None, *, + inlude_user_info: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -749,6 +1118,22 @@ async def get_room_with_persons_details_async( Get office location details including list of people for that office location + + Swagger operation ID: `GetRoomWithPersonsDetails`. + + Args: + office_location_name: The office location name. + inlude_user_info: Flag to indicate if user info should be included. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -766,7 +1151,7 @@ async def get_room_with_persons_details_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -780,6 +1165,7 @@ async def get_room_with_persons_details_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -787,11 +1173,11 @@ async def get_room_with_persons_details_async( return json.loads(response.text) - async def get_office_location_image_async( + def get_office_location_image( self, office_location_name: str, - large: Optional[bool] = None, *, + large: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -801,6 +1187,22 @@ async def get_office_location_image_async( Get image of office location Get image of specific office location + + Swagger operation ID: `GetOfficeLocationImage`. + + Args: + office_location_name: Office location identifier. + large: Image size. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -818,7 +1220,7 @@ async def get_office_location_image_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -832,47 +1234,87 @@ async def get_office_location_image_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_rooms_async( + def list_rooms( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get all rooms Get all rooms (defined in Azure AD as meeting rooms) + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetRooms`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/rooms" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("rooms", []): + yield item + + return None, items() - async def search_meeting_rooms_async( + return ItemPaged(get_next, extract_data) + + def list_search_meeting_rooms( self, name: str, *, @@ -880,75 +1322,154 @@ async def search_meeting_rooms_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Search for meeting room Get rooms by name search (from Azure AD meeting rooms) + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SearchMeetingRooms`. + + Args: + name: Search string. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/rooms/findbyname/{quote(str(name), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("rooms", []): + yield item - async def room_lists_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_room_lists( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get meeting rooms lists Get meeting rooms lists as defined in Azure AD + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `RoomLists`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/rooms/lists" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("rooms", []): + yield item + + return None, items() - async def rooms_by_list_address_async( + return ItemPaged(get_next, extract_data) + + def list_rooms_by_list_address( self, meeting_room_list_address: str, *, @@ -956,39 +1477,79 @@ async def rooms_by_list_address_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get meeting rooms by list Get all meeting rooms from specific list name + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `RoomsByListAddress`. + + Args: + meeting_room_list_address: Name of list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/rooms/{quote(str(meeting_room_list_address), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("rooms", []): + yield item + + return None, items() - async def get_rooms_by_image_name_async( + return ItemPaged(get_next, extract_data) + + def get_rooms_by_image_name( self, image_name: str, *, @@ -1001,13 +1562,28 @@ async def get_rooms_by_image_name_async( Get all meeting rooms by image Get all meeting rooms mapped to a specific image + + Swagger operation ID: `GetRoomsByImageName`. + + Args: + image_name: The unique image name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/rooms/GetRoomsByImageName/{quote(str(image_name), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1021,6 +1597,7 @@ async def get_rooms_by_image_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/microsoftbookings.py b/src/azure/connectors/microsoftbookings.py index 8b1f5da..f777d1a 100644 --- a/src/azure/connectors/microsoftbookings.py +++ b/src/azure/connectors/microsoftbookings.py @@ -5,20 +5,38 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "MicrosoftbookingsClient", + "AppointmentData", + "CancelAppointmentInput", + "CreateAppointmentInput", + "CustomQuestion", + "CustomerData", + "DeleteWebhookResponse", + "ListMailboxResponse", + "MailboxEntity", + "StaffMemberData", + "UpdateAppointmentInput", + "WebhookResponse", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -28,7 +46,7 @@ class CreateAppointmentInput: When a appointment is Created """ - webhook: Optional[Dict[str, Any]] = None + webhook: Dict[str, Any] @dataclass @@ -37,8 +55,9 @@ class WebhookResponse: Response for When a appointment is Created """ - webhook_id: Optional[str] = field( + webhook_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webhookId"}, ) """Webhook ID.""" @@ -50,7 +69,7 @@ class UpdateAppointmentInput: When an appointment is Updated """ - webhook: Optional[Dict[str, Any]] = None + webhook: Dict[str, Any] @dataclass @@ -59,7 +78,7 @@ class CancelAppointmentInput: When an appointment is Cancelled """ - webhook: Optional[Dict[str, Any]] = None + webhook: Dict[str, Any] @dataclass @@ -68,7 +87,12 @@ class ListMailboxResponse: Response for List Booking Businesses where user is an admin """ - mailboxes: Optional[List[MailboxEntity]] = None + mailboxes: Optional[ + List[MailboxEntity | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """All mailbox entities.""" @@ -81,12 +105,13 @@ class MailboxEntity: Definition: MailboxEntity """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Mailbox Display name.""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """SMTP of the Booking mailbox.""" @@ -96,128 +121,158 @@ class AppointmentData: Definition: AppointmentData """ - additional_info: Optional[str] = field( + additional_info: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AdditionalInfo"}, ) """Additional Info about the booking.""" - customer_email: Optional[str] = field( + customer_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomerEmail"}, ) """Customer Email address in case of 1:1 bookings.""" - customer_id: Optional[str] = field( + customer_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomerId"}, ) """Customer Id in case of 1:1 bookings.""" - customer_location: Optional[Dict[str, Any]] = field( + customer_location: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomerLocation"}, ) """Location of customer in 1:1 booking""" - customer_name: Optional[str] = field( + customer_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomerName"}, ) """Customer Name for 1:1 booking.""" - customer_notes: Optional[str] = field( + customer_notes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomerNotes"}, ) """Customer Notes for 1:1 booking.""" - custom_question_answers: Optional[List[CustomQuestion]] = field( + custom_question_answers: Optional[ + List[CustomQuestion | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomQuestionAnswers"}, ) """All the custom questions and answers for 1:1 booking.""" - customer_phone: Optional[str] = field( + customer_phone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomerPhone"}, ) """Customer phone for 1:1 booking.""" - customer_time_zone: Optional[str] = field( + customer_time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomerTimeZone"}, ) """Customer Time Zone for 1:1 booking.""" - customers: Optional[List[CustomerData]] = field( + customers: Optional[List[CustomerData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Customers"}, ) """List of customers in the 1:N booking""" - duration: Optional[int] = field( + duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Duration"}, ) """Duration of the appointment""" - end_time: Optional[str] = field( + end_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EndTime"}, ) """End Time of the appointment.""" - filled_attendees_count: Optional[int] = field( + filled_attendees_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FilledAttendeesCount"}, ) """Number of attendees who have booked this appoinment slot.""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """ [Deprecated] - use selfServiceAppointmentId as unique identifier for the bookings appointment. """ - is_s_m_s_notifications_enabled: Optional[bool] = field( + is_s_m_s_notifications_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsSMSNotificationsEnabled"}, ) """Field to check if SMS notification is enabled for the appointment.""" - join_web_u_r_l: Optional[str] = field( + join_web_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JoinWebURL"}, ) """URL for joining this online appointment.""" - max_attendees_count: Optional[int] = field( + max_attendees_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MaxAttendeesCount"}, ) """Max number of attendees allowed in this appoinment.""" - self_service_appointment_id: Optional[str] = field( + self_service_appointment_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SelfServiceAppointmentId"}, ) """Appointment id for the booking appointment.""" - service_id: Optional[str] = field( + service_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ServiceId"}, ) """Unique Service Identifier.""" - service_name: Optional[str] = field( + service_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ServiceName"}, ) """Name of the bookings service.""" - service_notes: Optional[str] = field( + service_notes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ServiceNotes"}, ) """Service level notes for the staff and admin.""" - staff_members: Optional[List[StaffMemberData]] = field( + staff_members: Optional[List[StaffMemberData | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StaffMembers"}, ) """List of staff members""" - start_time: Optional[str] = field( + start_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartTime"}, ) """Start Time of the appointment.""" - tracking_data: Optional[str] = field( + tracking_data: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TrackingData"}, ) """Campaign tracking Data.""" - cancel_reason: Optional[str] = field( + cancel_reason: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CancelReason"}, ) """Reason for cancellation of this booking appointment""" @@ -229,26 +284,45 @@ class CustomerData: Definition: CustomerData """ - email: Optional[str] = field(default=None, metadata={"wire_name": "Email"}) + email: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Email"}, + ) """Email of the customer in the group booking.""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Unique ID of the customer in the group booking.""" - location: Optional[Dict[str, Any]] = field( + location: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location of customer in a group booking.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Display Name of the customer in the group booking.""" - notes: Optional[str] = field(default=None, metadata={"wire_name": "Notes"}) + notes: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Notes"}, + ) """Notes of the customer in the group booking.""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TimeZone"}, ) """Timezone of the customer in the group booking.""" - answers: Optional[List[CustomQuestion]] = field( + answers: Optional[List[CustomQuestion | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Answers"}, ) """All the custom questions and answers.""" @@ -260,17 +334,23 @@ class StaffMemberData: Definition: StaffMemberData """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Display Name of the staff assigned for this appointment.""" - email_address: Optional[str] = field( + email_address: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmailAddress"}, ) """Email Address of the staff assigned to this appointment.""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Unique Staff identifier.""" @@ -280,33 +360,39 @@ class CustomQuestion: Definition: CustomQuestion """ - answer: Optional[str] = field( + answer: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Answer"}, ) """Answer to this custom question.""" - answer_options: Optional[List[str]] = field( + answer_options: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AnswerOptions"}, ) """All the answer options.""" - is_required: Optional[bool] = field( + is_required: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsRequired"}, ) """Tells if answering this question is mandatory.""" - question: Optional[str] = field( + question: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Question"}, ) """Question to be answered.""" - question_id: Optional[str] = field( + question_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "QuestionID"}, ) """Unique Identifier of the Question to be answered.""" - selected_options: Optional[List[int]] = field( + selected_options: Optional[List[int]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SelectedOptions"}, ) """All the selected answer options.""" @@ -320,16 +406,16 @@ class MicrosoftbookingsClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -340,8 +426,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -349,8 +435,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -362,7 +448,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -377,45 +463,123 @@ def __init__( def connector_name(self) -> str: return "microsoftbookings" - async def list_bookings_business_user_as_admin_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_bookings_business_user_as_admin( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List Booking Businesses where user is an admin Operation used to list all mailboxes for which the accessing user is an Administrator. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListBookingsBusinessUserAsAdmin`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/BookingsService/api/V1/bookingBusinessesUserAsAdmin" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("mailboxes", []): + yield item - if not response.text: - return None + return None, items() - return json.loads(response.text) + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/microsoftforms.py b/src/azure/connectors/microsoftforms.py index d0636cd..3a1170f 100644 --- a/src/azure/connectors/microsoftforms.py +++ b/src/azure/connectors/microsoftforms.py @@ -5,21 +5,33 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "MicrosoftformsClient", + "FormsList", + "GetFormDetailsByIdResult", + "GetFormResponseByIdResult", + "NewResponses", + "WebhookPayload", + "WebhookRequestBody", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +41,7 @@ class GetFormResponseByIdResult: Response for Get response details """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -42,22 +54,25 @@ class GetFormDetailsByIdResult: Response for Get form details """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of the form.""" - modified_date: Optional[str] = field( + modified_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "modifiedDate"}, ) """Datetime when form was last modified.""" - created_date: Optional[str] = field( + created_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDate"}, ) """Datetime when form was created.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status of the form.""" - created_by: Optional[str] = field( + created_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdBy"}, ) """User who created the form.""" @@ -72,17 +87,13 @@ class WebhookRequestBody: Definition: WebhookRequestBody """ - event_type: Optional[str] = field( - default=None, - metadata={"wire_name": "eventType"}, - ) + event_type: str = dataclass_field(metadata={"wire_name": "eventType"}) """Webhook event""" - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "notificationUrl"}, ) """Webhook callback url""" - source: Optional[str] = None + source: str """Source of webhook registration""" @@ -92,7 +103,7 @@ class WebhookPayload: Definition: WebhookPayload """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) NewResponses = List[Dict[str, Any]] @@ -106,16 +117,16 @@ class MicrosoftformsClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -126,8 +137,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -135,8 +146,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -148,7 +159,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -163,7 +174,46 @@ def __init__( def connector_name(self) -> str: return "microsoftforms" - async def get_form_response_by_id_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def get_form_response_by_id( self, form_id: str, response_id: int, @@ -177,6 +227,22 @@ async def get_form_response_by_id_async( Get response details This action retrieves a form response + + Swagger operation ID: `GetFormResponseById`. + + Args: + form_id: Unique identifier of the form. + response_id: Unique identifier of the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -190,7 +256,7 @@ async def get_form_response_by_id_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -204,6 +270,7 @@ async def get_form_response_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -211,7 +278,7 @@ async def get_form_response_by_id_async( return json.loads(response.text) - async def get_form_details_by_id_async( + def get_form_details_by_id( self, form_id: str, *, @@ -224,6 +291,21 @@ async def get_form_details_by_id_async( Get form details This action retrieves the details of a form + + Swagger operation ID: `GetFormDetailsById`. + + Args: + form_id: Unique identifier of the form. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -239,7 +321,7 @@ async def get_form_details_by_id_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -253,6 +335,7 @@ async def get_form_details_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -260,43 +343,82 @@ async def get_form_details_by_id_async( return json.loads(response.text) - async def list_forms_async( + def list_forms( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List forms This operation returns a list of forms in your account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListForms`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/formapi/api/forms" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_questions_async( + def get_questions( self, form_id: str, *, @@ -309,13 +431,28 @@ async def get_questions_async( Get questions Get questions definition in a form. + + Swagger operation ID: `GetQuestions`. + + Args: + form_id: Unique id of the form. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/formapi/api/forms('{quote(str(form_id), safe='')}')/questions" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -329,6 +466,7 @@ async def get_questions_async( request_url, response.status, response.text, + response=response, ) diff --git a/src/azure/connectors/monday.py b/src/azure/connectors/monday.py index bd5e040..5e344f8 100644 --- a/src/azure/connectors/monday.py +++ b/src/azure/connectors/monday.py @@ -5,21 +5,91 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "MondayClient", + "CreateBoardInput", + "CreateBoardResponse", + "CreateColumnInput", + "CreateColumnResponse", + "CreateGroupInput", + "CreateGroupResponse", + "CreateItemInput", + "CreateItemResponse", + "CreateNotificationInput", + "CreateNotificationResponse", + "CreateSubitemInput", + "CreateSubitemResponse", + "CreateUpdateInput", + "CreateUpdateResponse", + "CreateWorkspaceInput", + "CreateWorkspaceResponse", + "DuplicateBoardInput", + "DuplicateBoardResponse", + "DynamicGetColumnNamesForUpdateWebhook", + "DynamicGetColumnNamesForWebhook", + "DynamicGetGetItemsSchema", + "DynamicGetSubitemColumnNamesForWebhook", + "DynamicResponseGetListSchema", + "DynamicResponseGetListSchemaGet", + "DynamicResponseGetSingleColumnSchema", + "FieldBoard", + "FieldColumnsToUpdateSingleColumn", + "FieldWorkspace", + "GetColumnNamesSchemaForColumnChangesWebhookResponse", + "GetColumnNamesSchemaForItemNameChangeWebhookResponse", + "GetColumnNamesSchemaForSubitemNameChangeWebhookResponse", + "GetColumnNamesSchemaForUpdateWebhookResponse", + "GetColumnNamesSchemaForWebhookResponse", + "GetColumnNamesSchemaResponse", + "GetSchemaForGetItemsActionResponse", + "GetSingleColumnSchemaResponse", + "GetSubitemColumnNamesForGetSubitems", + "GetSubitemColumnNamesResponse", + "GetSubitemSchemaResponse", + "GetTagsResponse", + "GetUsersResponse", + "GetWorkspacesResponse", + "MoveItemToGroupInput", + "MoveItemToGroupResponse", + "UpdateItemColumnInput", + "UpdateItemColumnResponse", + "UpdateMultipleItemColumnsInput", + "UpdateMultipleItemColumnsResponse", + "WebhookAnyColumnChangesInput", + "WebhookAnyColumnChangesResponse", + "WebhookChangeNameInput", + "WebhookChangeNameResponse", + "WebhookChangeSubitemNameInput", + "WebhookChangeSubitemNameResponse", + "WebhookColumnChangesInput", + "WebhookColumnChangesResponse", + "WebhookCreateItemInput", + "WebhookCreateItemResponse", + "WebhookCreateSubitemInput", + "WebhookCreateSubitemResponse", + "WebhookCreateUpdateInput", + "WebhookCreateUpdateResponse", + "WebhookSubitemColumnChangesInput", + "WebhookSubitemColumnChangesResponse", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,20 +99,11 @@ class WebhookCreateItemInput: When an item is created """ - workspace_id: Optional[str] = field( - default=None, - metadata={"wire_name": "workspaceId"}, - ) + workspace_id: str = dataclass_field(metadata={"wire_name": "workspaceId"}) """Select a workspace from the drop-down or specify a workspace ID.""" - board_id: Optional[str] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) + board_id: str = dataclass_field(metadata={"wire_name": "boardId"}) """Select a board from the drop-down or specify a board ID.""" - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) """Specify the callback URL""" @@ -52,7 +113,7 @@ class WebhookCreateItemResponse: Response for When an item is created """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -65,20 +126,11 @@ class WebhookCreateUpdateInput: When a new update is posted """ - workspace_id: Optional[str] = field( - default=None, - metadata={"wire_name": "workspaceId"}, - ) + workspace_id: str = dataclass_field(metadata={"wire_name": "workspaceId"}) """Select a workspace from the drop-down or specify a workspace ID.""" - board_id: Optional[str] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) + board_id: str = dataclass_field(metadata={"wire_name": "boardId"}) """Select a board from the drop-down or specify a board ID.""" - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) """Specify the callback URL.""" @@ -88,7 +140,7 @@ class WebhookCreateUpdateResponse: Response for When a new update is posted """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -101,20 +153,11 @@ class WebhookChangeNameInput: When an item's name changes """ - workspace_id: Optional[str] = field( - default=None, - metadata={"wire_name": "workspaceId"}, - ) + workspace_id: str = dataclass_field(metadata={"wire_name": "workspaceId"}) """Select a workspace from the drop-down or specify a workspace ID.""" - board_id: Optional[str] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) + board_id: str = dataclass_field(metadata={"wire_name": "boardId"}) """Select a board from the drop-down or specify a board ID.""" - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) """Specify the callback URL.""" @@ -124,7 +167,7 @@ class WebhookChangeNameResponse: Response for When an item's name changes """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -137,20 +180,11 @@ class WebhookChangeSubitemNameInput: When a subitem's name changes """ - workspace_id: Optional[str] = field( - default=None, - metadata={"wire_name": "workspaceId"}, - ) + workspace_id: str = dataclass_field(metadata={"wire_name": "workspaceId"}) """Select a workspace from the drop-down or specify a workspace ID.""" - board_id: Optional[str] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) + board_id: str = dataclass_field(metadata={"wire_name": "boardId"}) """Select a board from the drop-down or specify a board ID.""" - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) """Specify the callback URL.""" @@ -160,7 +194,7 @@ class WebhookChangeSubitemNameResponse: Response for When a subitem's name changes """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -173,20 +207,11 @@ class WebhookCreateSubitemInput: When a subitem is created """ - workspace_id: Optional[str] = field( - default=None, - metadata={"wire_name": "workspaceId"}, - ) + workspace_id: str = dataclass_field(metadata={"wire_name": "workspaceId"}) """Select a workspace from the drop-down or specify a workspace ID.""" - board_id: Optional[str] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) + board_id: str = dataclass_field(metadata={"wire_name": "boardId"}) """Select a board from the drop-down or specify a board ID.""" - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) """Specify the callback URL.""" @@ -196,7 +221,7 @@ class WebhookCreateSubitemResponse: Response for When a subitem is created """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -209,25 +234,13 @@ class WebhookColumnChangesInput: When a column changes """ - workspace_id: Optional[str] = field( - default=None, - metadata={"wire_name": "workspaceId"}, - ) + workspace_id: str = dataclass_field(metadata={"wire_name": "workspaceId"}) """Select a workspace from the drop-down or specify a workspace ID.""" - board_id: Optional[str] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) + board_id: str = dataclass_field(metadata={"wire_name": "boardId"}) """Select a board from the drop-down or specify a board ID.""" - column_id: Optional[str] = field( - default=None, - metadata={"wire_name": "columnId"}, - ) + column_id: str = dataclass_field(metadata={"wire_name": "columnId"}) """Select a column from the drop-down.""" - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) """Specify the callback URL.""" @@ -237,7 +250,7 @@ class WebhookColumnChangesResponse: Response for When a column changes """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -250,20 +263,11 @@ class WebhookAnyColumnChangesInput: When any column changes """ - workspace_id: Optional[str] = field( - default=None, - metadata={"wire_name": "workspaceId"}, - ) + workspace_id: str = dataclass_field(metadata={"wire_name": "workspaceId"}) """Select a workspace from the drop-down or specify a workspace ID.""" - board_id: Optional[str] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) + board_id: str = dataclass_field(metadata={"wire_name": "boardId"}) """Select a board from the drop-down or specify a board ID.""" - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) """Specify the callback URL.""" @@ -273,7 +277,7 @@ class WebhookAnyColumnChangesResponse: Response for When any column changes """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -286,20 +290,11 @@ class WebhookSubitemColumnChangesInput: When any subitem column changes """ - workspace_id: Optional[str] = field( - default=None, - metadata={"wire_name": "workspaceId"}, - ) + workspace_id: str = dataclass_field(metadata={"wire_name": "workspaceId"}) """Select a workspace from the drop-down or specify a workspace ID.""" - board_id: Optional[str] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) + board_id: str = dataclass_field(metadata={"wire_name": "boardId"}) """Select a board from the drop-down or specify a board ID.""" - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) """Specify the callback URL.""" @@ -309,7 +304,7 @@ class WebhookSubitemColumnChangesResponse: Response for When any subitem column changes """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -322,26 +317,17 @@ class CreateItemInput: Create an item """ - workspace_id: Optional[FieldWorkspace] = field( - default=None, + workspace_id: FieldWorkspace = dataclass_field( metadata={"wire_name": "workspaceId"}, ) - board_id: Optional[FieldBoard] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) - group_id: Optional[str] = field( - default=None, - metadata={"wire_name": "groupId"}, - ) + board_id: FieldBoard = dataclass_field(metadata={"wire_name": "boardId"}) + group_id: str = dataclass_field(metadata={"wire_name": "groupId"}) """Select a group from the drop-down or specify a group ID.""" - item_name: Optional[str] = field( - default=None, - metadata={"wire_name": "itemName"}, - ) + item_name: str = dataclass_field(metadata={"wire_name": "itemName"}) """Specify the name of the item you want to create.""" - column_values: Optional[DynamicResponseGetListSchema] = field( + column_values: Optional[DynamicResponseGetListSchema | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "columnValues"}, ) @@ -352,7 +338,7 @@ class CreateItemResponse: Response for Create an item """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -361,38 +347,37 @@ class DuplicateBoardInput: Duplicate a board """ - source_workspace_id: Optional[str] = field( - default=None, + source_workspace_id: str = dataclass_field( metadata={"wire_name": "sourceWorkspaceId"}, ) """Select the workspace for the board you want to duplicate.""" - source_board_id: Optional[str] = field( - default=None, + source_board_id: str = dataclass_field( metadata={"wire_name": "sourceBoardId"}, ) """Select the board to duplicate.""" - duplicated_board_name: Optional[str] = field( + duplicated_board_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "duplicatedBoardName"}, ) """Specify the name of the duplicated board.""" - duplication_type: Optional[str] = field( - default=None, + duplication_type: str = dataclass_field( metadata={"wire_name": "duplicationType"}, ) """Select the duplication type from the drop-down.""" - destination_workspace_id: Optional[str] = field( + destination_workspace_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "destinationWorkspaceId"}, ) """Select the destination workspace for the duplicated board.""" - destination_folder: Optional[str] = field( + destination_folder: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "destinationFolder"}, ) """Select the destination folder for the duplicated board.""" - keep_board_subscribers: Optional[bool] = field( - default=None, + keep_board_subscribers: bool = dataclass_field( metadata={"wire_name": "keepBoardSubscribers"}, ) """Select whether to keep board subscribers.""" @@ -404,7 +389,7 @@ class DuplicateBoardResponse: Response for Duplicate a board """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the duplicated board""" @@ -414,15 +399,9 @@ class CreateBoardInput: Create a board """ - workspace_id: Optional[str] = field( - default=None, - metadata={"wire_name": "workspaceId"}, - ) + workspace_id: str = dataclass_field(metadata={"wire_name": "workspaceId"}) """Specify the ID of a monday.com workspace.""" - board_name: Optional[str] = field( - default=None, - metadata={"wire_name": "boardName"}, - ) + board_name: str = dataclass_field(metadata={"wire_name": "boardName"}) """Specify the desired name of the board you want to create.""" @@ -432,7 +411,7 @@ class CreateBoardResponse: Response for Create a board """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -441,22 +420,15 @@ class CreateColumnInput: Create a column """ - workspace_id: Optional[FieldWorkspace] = field( - default=None, + workspace_id: FieldWorkspace = dataclass_field( metadata={"wire_name": "workspaceId"}, ) - board_id: Optional[FieldBoard] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) - title: Optional[str] = None + board_id: FieldBoard = dataclass_field(metadata={"wire_name": "boardId"}) + title: str """Specify the title of the column you want to create.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Specify the description of the column you want to create.""" - column_type: Optional[str] = field( - default=None, - metadata={"wire_name": "columnType"}, - ) + column_type: str = dataclass_field(metadata={"wire_name": "columnType"}) """Select a column type from the drop-down.""" @@ -466,7 +438,7 @@ class CreateColumnResponse: Response for Create a column """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -475,18 +447,11 @@ class CreateGroupInput: Create a group """ - workspace_id: Optional[FieldWorkspace] = field( - default=None, + workspace_id: FieldWorkspace = dataclass_field( metadata={"wire_name": "workspaceId"}, ) - board_id: Optional[FieldBoard] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) - group_name: Optional[str] = field( - default=None, - metadata={"wire_name": "groupName"}, - ) + board_id: FieldBoard = dataclass_field(metadata={"wire_name": "boardId"}) + group_name: str = dataclass_field(metadata={"wire_name": "groupName"}) """Specify your desired group name.""" @@ -496,7 +461,7 @@ class CreateGroupResponse: Response for Create a group """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -505,27 +470,16 @@ class UpdateItemColumnInput: Update an item's column value """ - workspace_id: Optional[str] = field( - default=None, - metadata={"wire_name": "workspaceId"}, - ) + workspace_id: str = dataclass_field(metadata={"wire_name": "workspaceId"}) """Select the workspace the item belongs to from the drop-down.""" - board_id: Optional[str] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) + board_id: str = dataclass_field(metadata={"wire_name": "boardId"}) """Select the board the item belongs to from the drop-down.""" - column_id: Optional[FieldColumnsToUpdateSingleColumn] = field( - default=None, + column_id: FieldColumnsToUpdateSingleColumn = dataclass_field( metadata={"wire_name": "columnId"}, ) - item_id: Optional[str] = field( - default=None, - metadata={"wire_name": "itemId"}, - ) + item_id: str = dataclass_field(metadata={"wire_name": "itemId"}) """Specify the ID of the item to update.""" - column_values: Optional[DynamicResponseGetSingleColumnSchema] = field( - default=None, + column_values: DynamicResponseGetSingleColumnSchema | Mapping[str, Any] = dataclass_field( metadata={"wire_name": "columnValues"}, ) @@ -536,7 +490,7 @@ class UpdateItemColumnResponse: Response for Update an item's column value """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -545,30 +499,23 @@ class UpdateMultipleItemColumnsInput: Update multiple item column values """ - workspace_id: Optional[str] = field( - default=None, - metadata={"wire_name": "workspaceId"}, - ) + workspace_id: str = dataclass_field(metadata={"wire_name": "workspaceId"}) """Select the workspace the item belongs to from the drop-down.""" - board_id: Optional[str] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) + board_id: str = dataclass_field(metadata={"wire_name": "boardId"}) """Select the board the item belongs to from the drop-down.""" - item_id: Optional[str] = field( - default=None, - metadata={"wire_name": "itemId"}, - ) + item_id: str = dataclass_field(metadata={"wire_name": "itemId"}) """Specify the ID of the item to update.""" - item_name: Optional[str] = field( + item_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "itemName"}, ) """ Specify a new name for the item. Leave blank to keep the current name. """ - column_values: Optional[DynamicResponseGetListSchema] = field( + column_values: Optional[DynamicResponseGetListSchema | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "columnValues"}, ) @@ -579,7 +526,7 @@ class UpdateMultipleItemColumnsResponse: Response for Update multiple item column values """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -588,23 +535,13 @@ class MoveItemToGroupInput: Move an item to a group """ - workspace_id: Optional[FieldWorkspace] = field( - default=None, + workspace_id: FieldWorkspace = dataclass_field( metadata={"wire_name": "workspaceId"}, ) - board_id: Optional[FieldBoard] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) - group_id: Optional[str] = field( - default=None, - metadata={"wire_name": "groupId"}, - ) + board_id: FieldBoard = dataclass_field(metadata={"wire_name": "boardId"}) + group_id: str = dataclass_field(metadata={"wire_name": "groupId"}) """Select the group to move the item to from the drop-down.""" - item_id: Optional[str] = field( - default=None, - metadata={"wire_name": "itemId"}, - ) + item_id: str = dataclass_field(metadata={"wire_name": "itemId"}) """Specify the ID of the item to move.""" @@ -614,7 +551,7 @@ class MoveItemToGroupResponse: Response for Move an item to a group """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -623,17 +560,11 @@ class CreateNotificationInput: Create a notification """ - user_id: Optional[str] = field( - default=None, - metadata={"wire_name": "userId"}, - ) + user_id: str = dataclass_field(metadata={"wire_name": "userId"}) """Select a user from the drop-down or specify a user ID.""" - target_id: Optional[str] = field( - default=None, - metadata={"wire_name": "targetId"}, - ) + target_id: str = dataclass_field(metadata={"wire_name": "targetId"}) """Specify a board ID or item ID the notification will go to.""" - text: Optional[str] = None + text: str """Specify the notification text.""" @@ -643,7 +574,7 @@ class CreateNotificationResponse: Response for Create a notification """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Data""" @@ -653,27 +584,20 @@ class CreateSubitemInput: Create a subitem """ - workspace_id: Optional[FieldWorkspace] = field( - default=None, + workspace_id: FieldWorkspace = dataclass_field( metadata={"wire_name": "workspaceId"}, ) - board_id: Optional[str] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) + board_id: str = dataclass_field(metadata={"wire_name": "boardId"}) """Select a board from the drop-down or specify a board ID.""" - parent_item_id: Optional[str] = field( - default=None, + parent_item_id: str = dataclass_field( metadata={"wire_name": "parentItemId"}, ) """Select a parent item from the drop-down or specify a parent item ID.""" - item_name: Optional[str] = field( - default=None, - metadata={"wire_name": "itemName"}, - ) + item_name: str = dataclass_field(metadata={"wire_name": "itemName"}) """Specify a name for the subitem.""" - column_values: Optional[DynamicResponseGetListSchema] = field( + column_values: Optional[DynamicResponseGetListSchema | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "columnValues"}, ) @@ -684,7 +608,7 @@ class CreateSubitemResponse: Response for Create a subitem """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -693,7 +617,7 @@ class GetSubitemColumnNamesForGetSubitems: Response for Get subitems """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -706,25 +630,15 @@ class CreateUpdateInput: Create an update """ - workspace_id: Optional[FieldWorkspace] = field( - default=None, + workspace_id: FieldWorkspace = dataclass_field( metadata={"wire_name": "workspaceId"}, ) - board_id: Optional[FieldBoard] = field( - default=None, - metadata={"wire_name": "boardId"}, - ) - group_id: Optional[str] = field( - default=None, - metadata={"wire_name": "groupId"}, - ) + board_id: FieldBoard = dataclass_field(metadata={"wire_name": "boardId"}) + group_id: str = dataclass_field(metadata={"wire_name": "groupId"}) """Select a group from the drop-down or specify a group ID.""" - item_id: Optional[str] = field( - default=None, - metadata={"wire_name": "itemId"}, - ) + item_id: str = dataclass_field(metadata={"wire_name": "itemId"}) """Select an item from the drop-down or specify an item ID.""" - body: Optional[str] = None + body: str """Specify text for the update.""" @@ -734,7 +648,7 @@ class CreateUpdateResponse: Response for Create an update """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -743,7 +657,7 @@ class DynamicResponseGetListSchemaGet: Response for Get an item by ID """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -756,9 +670,9 @@ class CreateWorkspaceInput: Create a workspace """ - name: Optional[str] = None + name: str """Specify a name for the new workspace.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Specify a description for the new workspace.""" @@ -768,7 +682,7 @@ class CreateWorkspaceResponse: Response for Create a workspace """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -777,7 +691,7 @@ class DynamicGetGetItemsSchema: Response for Get items """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -790,7 +704,7 @@ class GetTagsResponse: Response for Get tags """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -799,7 +713,7 @@ class GetUsersResponse: Response for Get users """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -808,7 +722,7 @@ class GetWorkspacesResponse: Response for Get workspaces """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -818,7 +732,7 @@ class GetColumnNamesSchemaResponse: Response for Get column names for a board ID """ - schema: Optional[Dict[str, Any]] = None + schema: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Schema of the requested schema type""" @@ -828,7 +742,7 @@ class GetSingleColumnSchemaResponse: Response for Gets single column schema for a board ID """ - schema: Optional[Dict[str, Any]] = None + schema: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Schema of the requested schema type""" @@ -838,7 +752,7 @@ class GetColumnNamesSchemaForWebhookResponse: Response for Get column names for a board ID for a webhook """ - schema: Optional[Dict[str, Any]] = None + schema: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Schema of the requested schema type""" @@ -848,7 +762,7 @@ class GetSchemaForGetItemsActionResponse: Response for Get column names for a board ID for a webhook """ - schema: Optional[Dict[str, Any]] = None + schema: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Schema of the requested schema type""" @@ -858,7 +772,7 @@ class GetColumnNamesSchemaForUpdateWebhookResponse: Response for Get column names for a board ID for an update webhook """ - schema: Optional[Dict[str, Any]] = None + schema: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Schema of the requested schema type""" @@ -868,7 +782,7 @@ class GetSubitemColumnNamesResponse: Response for Get subitem column names """ - schema: Optional[Dict[str, Any]] = None + schema: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Schema of the requested schema type""" @@ -878,7 +792,7 @@ class GetSubitemSchemaResponse: Response for Get subitem column names """ - schema: Optional[Dict[str, Any]] = None + schema: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Schema of the requested schema type""" @@ -888,7 +802,7 @@ class GetColumnNamesSchemaForItemNameChangeWebhookResponse: Response for Get column names schema for column changes """ - schema: Optional[Dict[str, Any]] = None + schema: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Schema of the requested schema type""" @@ -898,7 +812,7 @@ class GetColumnNamesSchemaForSubitemNameChangeWebhookResponse: Response for Get column names schema for column changes """ - schema: Optional[Dict[str, Any]] = None + schema: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Schema of the requested schema type""" @@ -908,7 +822,7 @@ class GetColumnNamesSchemaForColumnChangesWebhookResponse: Response for Get column names schema for column changes """ - schema: Optional[Dict[str, Any]] = None + schema: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Schema of the requested schema type""" @@ -918,7 +832,7 @@ class DynamicResponseGetListSchema: Definition: DynamicResponseGetListSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -931,7 +845,7 @@ class DynamicResponseGetSingleColumnSchema: Definition: DynamicResponseGetSingleColumnSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -944,7 +858,7 @@ class DynamicGetColumnNamesForWebhook: Definition: DynamicGetColumnNamesForWebhook """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -957,7 +871,7 @@ class DynamicGetColumnNamesForUpdateWebhook: Definition: DynamicGetColumnNamesForUpdateWebhook """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -970,7 +884,7 @@ class DynamicGetSubitemColumnNamesForWebhook: Definition: DynamicGetSubitemColumnNamesForWebhook """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -994,16 +908,16 @@ class MondayClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -1014,8 +928,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -1023,8 +937,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -1036,7 +950,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -1051,9 +965,48 @@ def __init__( def connector_name(self) -> str: return "monday" - async def create_item_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def create_item( self, - input: CreateItemInput, + input: CreateItemInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1064,13 +1017,29 @@ async def create_item_async( Create an item Creates an item in the selected monday.com board and group. + + Swagger operation ID: `CreateItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/executePowerAutomateAction/CreateItem" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1084,6 +1053,7 @@ async def create_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1091,9 +1061,9 @@ async def create_item_async( return json.loads(response.text) - async def duplicate_board_async( + def duplicate_board( self, - input: DuplicateBoardInput, + input: DuplicateBoardInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1104,13 +1074,29 @@ async def duplicate_board_async( Duplicate a board Duplicates a board in monday.com. + + Swagger operation ID: `DuplicateBoard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/executePowerAutomateAction/DuplicateBoard" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1124,6 +1110,7 @@ async def duplicate_board_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1131,9 +1118,9 @@ async def duplicate_board_async( return json.loads(response.text) - async def create_board_async( + def create_board( self, - input: CreateBoardInput, + input: CreateBoardInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1144,13 +1131,29 @@ async def create_board_async( Create a board Creates a board in monday.com. + + Swagger operation ID: `CreateBoard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/executePowerAutomateAction/CreateBoard" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1164,6 +1167,7 @@ async def create_board_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1171,9 +1175,9 @@ async def create_board_async( return json.loads(response.text) - async def create_column_async( + def create_column( self, - input: CreateColumnInput, + input: CreateColumnInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1184,13 +1188,29 @@ async def create_column_async( Create a column Creates a column in monday.com for the specified board. + + Swagger operation ID: `CreateColumn`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/executePowerAutomateAction/CreateColumn" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1204,6 +1224,7 @@ async def create_column_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1211,9 +1232,9 @@ async def create_column_async( return json.loads(response.text) - async def create_group_async( + def create_group( self, - input: CreateGroupInput, + input: CreateGroupInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1224,13 +1245,29 @@ async def create_group_async( Create a group Creates a group in monday.com for the specified board. + + Swagger operation ID: `CreateGroup`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/executePowerAutomateAction/CreateGroup" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1244,6 +1281,7 @@ async def create_group_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1251,9 +1289,9 @@ async def create_group_async( return json.loads(response.text) - async def update_item_column_async( + def update_item_column( self, - input: UpdateItemColumnInput, + input: UpdateItemColumnInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1265,13 +1303,29 @@ async def update_item_column_async( Updates a single item's column. If the value is blank, the column value will be cleared. + + Swagger operation ID: `UpdateItemColumn`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/executePowerAutomateAction/UpdateItemColumn" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1285,6 +1339,7 @@ async def update_item_column_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1292,9 +1347,9 @@ async def update_item_column_async( return json.loads(response.text) - async def update_multiple_item_columns_async( + def update_multiple_item_columns( self, - input: UpdateMultipleItemColumnsInput, + input: UpdateMultipleItemColumnsInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1306,13 +1361,29 @@ async def update_multiple_item_columns_async( Updates multiple item columns. Leave the column value blank to keep the current value. + + Swagger operation ID: `UpdateMultipleItemColumns`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/executePowerAutomateAction/UpdateMultipleItemColumns" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1326,6 +1397,7 @@ async def update_multiple_item_columns_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1333,9 +1405,9 @@ async def update_multiple_item_columns_async( return json.loads(response.text) - async def move_item_to_group_async( + def move_item_to_group( self, - input: MoveItemToGroupInput, + input: MoveItemToGroupInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1346,13 +1418,29 @@ async def move_item_to_group_async( Move an item to a group Moves an item to another group on the same board. + + Swagger operation ID: `MoveItemToGroup`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/executePowerAutomateAction/MoveItemToGroup" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1366,6 +1454,7 @@ async def move_item_to_group_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1373,9 +1462,9 @@ async def move_item_to_group_async( return json.loads(response.text) - async def create_notification_async( + def create_notification( self, - input: CreateNotificationInput, + input: CreateNotificationInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1387,13 +1476,29 @@ async def create_notification_async( Creates a notification in monday.com for a user for either a specific board or item. + + Swagger operation ID: `CreateNotification`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/executePowerAutomateAction/CreateNotification" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1407,6 +1512,7 @@ async def create_notification_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1414,9 +1520,9 @@ async def create_notification_async( return json.loads(response.text) - async def create_subitem_async( + def create_subitem( self, - input: CreateSubitemInput, + input: CreateSubitemInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1427,13 +1533,29 @@ async def create_subitem_async( Create a subitem Creates a subitem in monday.com for the selected board and parent item. + + Swagger operation ID: `CreateSubitem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/executePowerAutomateAction/CreateSubitem" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1447,6 +1569,7 @@ async def create_subitem_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1454,7 +1577,7 @@ async def create_subitem_async( return json.loads(response.text) - async def get_subitems_async( + def get_subitems( self, workspace_id: str, board_id: str, @@ -1469,6 +1592,25 @@ async def get_subitems_async( Get subitems Gets subitems in monday.com for a specific item in a board. + + Swagger operation ID: `GetSubitems`. + + Args: + workspace_id: Select a workspace from the drop-down or specify a + workspace ID. + board_id: Select the item's board from the drop-down or specify a + board ID. + item_id: Specify an item ID to retrieve the subitems for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/getData/getSubitems" query_params = [] @@ -1487,7 +1629,7 @@ async def get_subitems_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1501,6 +1643,7 @@ async def get_subitems_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1508,9 +1651,9 @@ async def get_subitems_async( return json.loads(response.text) - async def create_update_async( + def create_update( self, - input: CreateUpdateInput, + input: CreateUpdateInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1521,13 +1664,29 @@ async def create_update_async( Create an update Creates an update in monday.com for a specific item. + + Swagger operation ID: `CreateUpdate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/executePowerAutomateAction/CreateUpdate" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1541,6 +1700,7 @@ async def create_update_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1548,7 +1708,7 @@ async def create_update_async( return json.loads(response.text) - async def get_item_by_id_async( + def get_item_by_id( self, item_id: str, workspace_id: str, @@ -1563,6 +1723,25 @@ async def get_item_by_id_async( Get an item by ID Gets a monday.com item using the specified item ID and board. + + Swagger operation ID: `GetItemById`. + + Args: + item_id: Specify an item ID to retrieve. + workspace_id: Select the item's workspace from the drop-down or + specify a workspace ID. + board_id: Select the item's board from the drop-down or specify a + board ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/getData/getItemById" query_params = [] @@ -1581,7 +1760,7 @@ async def get_item_by_id_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1595,6 +1774,7 @@ async def get_item_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1602,9 +1782,9 @@ async def get_item_by_id_async( return json.loads(response.text) - async def create_workspace_async( + def create_workspace( self, - input: CreateWorkspaceInput, + input: CreateWorkspaceInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1616,13 +1796,29 @@ async def create_workspace_async( Creates a monday.com workspace with a user-specified name and description. + + Swagger operation ID: `CreateWorkspace_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/executePowerAutomateAction/CreateWorkspaceV2" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1636,6 +1832,7 @@ async def create_workspace_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1643,11 +1840,12 @@ async def create_workspace_async( return json.loads(response.text) - async def get_items_async( + def get_items( self, workspace_id: str, board_id: str, group_id: str, + *, filter1_column: Optional[str] = None, filter1_operator: Optional[str] = None, filter1_value: Optional[str] = None, @@ -1660,7 +1858,6 @@ async def get_items_async( filter4_column: Optional[str] = None, filter4_operator: Optional[str] = None, filter4_value: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1673,6 +1870,40 @@ async def get_items_async( by column values using the filters found under advanced options. More info on filtering can be found here: https://plugingenie.com/docs/filtering-items. + + Swagger operation ID: `GetItems_V2`. + + Args: + workspace_id: Select a workspace from the drop-down or specify a + workspace ID. + board_id: Select a board from the drop-down or specify a board ID. + group_id: Select a group from the drop-down or specify a group ID. + filter1_column: Select a column from the drop-down or specify a + column ID. + filter1_operator: Select an operator from the drop-down. + filter1_value: Specify a value (if applicable). + filter2_column: Select a column from the drop-down or specify a + column ID. + filter2_operator: Select an operator from the drop-down. + filter2_value: Specify a value (if applicable). + filter3_column: Select a column from the drop-down or specify a + column ID. + filter3_operator: Select an operator from the drop-down. + filter3_value: Specify a value (if applicable). + filter4_column: Select a column from the drop-down or specify a + column ID. + filter4_operator: Select an operator from the drop-down. + filter4_value: Specify a value (if applicable). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/getData/getItemsV2" query_params = [] @@ -1751,7 +1982,7 @@ async def get_items_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1765,6 +1996,7 @@ async def get_items_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1772,7 +2004,7 @@ async def get_items_async( return json.loads(response.text) - async def get_tags_async( + def get_tags( self, *, timeout: Optional[float] = None, @@ -1784,10 +2016,24 @@ async def get_tags_async( Get tags This operation gets monday.com tags. + + Swagger operation ID: `GetTags_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/getData/getTagsV2" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1801,6 +2047,7 @@ async def get_tags_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1808,7 +2055,7 @@ async def get_tags_async( return json.loads(response.text) - async def get_users_async( + def get_users( self, *, timeout: Optional[float] = None, @@ -1821,10 +2068,24 @@ async def get_users_async( This operation gets the name, email, and ID of users in your monday.com account. + + Swagger operation ID: `GetUsers_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/getData/getUsersV2" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1838,6 +2099,7 @@ async def get_users_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1845,7 +2107,7 @@ async def get_users_async( return json.loads(response.text) - async def get_workspaces_async( + def get_workspaces( self, *, timeout: Optional[float] = None, @@ -1857,10 +2119,24 @@ async def get_workspaces_async( Get workspaces This operation gets the workspaces from monday.com. + + Swagger operation ID: `GetWorkspaces_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/getData/getWorkspacesV2" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1874,6 +2150,7 @@ async def get_workspaces_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1881,19 +2158,38 @@ async def get_workspaces_async( return json.loads(response.text) - async def get_boards_async( + def list_boards( self, - workspace_id: Optional[str] = None, *, + workspace_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get boards This operation gets the boards from monday.com. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetBoards`. + + Args: + workspace_id: Specify the ID of the monday.com workspace. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/getData/getBoards" query_params = [] @@ -1904,29 +2200,50 @@ async def get_boards_async( query_params.append(f"workspaceId={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def get_groups_for_get_items_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_groups_for_get_items( self, board_id: str, *, @@ -1934,12 +2251,31 @@ async def get_groups_for_get_items_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get groups for the Get Items operation This operation gets the groups from monday.com, which includes the option to select all groups. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetGroupsForGetItems`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/getData/getGroupsForGetItems" @@ -1951,29 +2287,50 @@ async def get_groups_for_get_items_async( query_params.append(f"boardId={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_columns_for_item_filtering_async( + def list_columns_for_item_filtering( self, board_id: str, *, @@ -1981,11 +2338,30 @@ async def get_columns_for_item_filtering_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get columns for item filtering This operation gets the columns from monday.com for item filtering. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetColumnsForItemFiltering`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1998,43 +2374,84 @@ async def get_columns_for_item_filtering_async( query_params.append(f"boardId={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def get_column_filter_operator_async( + return ItemPaged(get_next, extract_data) + + def list_column_filter_operator( self, board_id: str, - column_id: Optional[str] = None, *, + column_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get column filter operator This operation gets the available item filter operator for the selected monday.com column. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetColumnFilterOperator`. + + Args: + board_id: Specify the ID of a monday.com board. + column_id: Specify the ID of a monday.com column. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/getData/getColumnFilterOperator" @@ -2051,32 +2468,53 @@ async def get_column_filter_operator_async( query_params.append(f"columnId={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def get_column_names_schema_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_column_names_schema( self, - board_id: Optional[str] = None, *, + board_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2086,6 +2524,21 @@ async def get_column_names_schema_async( Get column names for a board ID This operation gets the column names for a board ID. + + Swagger operation ID: `GetColumnNamesSchema`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/getSchema/getColumnNames" @@ -2099,7 +2552,7 @@ async def get_column_names_schema_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2113,6 +2566,7 @@ async def get_column_names_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2120,11 +2574,11 @@ async def get_column_names_schema_async( return json.loads(response.text) - async def get_single_column_schema_async( + def get_single_column_schema( self, + *, board_id: Optional[str] = None, column_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2134,6 +2588,22 @@ async def get_single_column_schema_async( Gets single column schema for a board ID This operation gets the single column schema for a board ID. + + Swagger operation ID: `GetSingleColumnSchema`. + + Args: + board_id: Specify the ID of a monday.com board. + column_id: Specify the ID of a monday.com column. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/getSchema/getSingleColumnSchema" @@ -2152,7 +2622,7 @@ async def get_single_column_schema_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2166,6 +2636,7 @@ async def get_single_column_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2173,10 +2644,10 @@ async def get_single_column_schema_async( return json.loads(response.text) - async def get_column_names_schema_for_webhook_async( + def get_column_names_schema_for_webhook( self, - board_id: Optional[str] = None, *, + board_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2187,6 +2658,21 @@ async def get_column_names_schema_for_webhook_async( This operation gets the column names for a board ID for a webhook (includes itemId). + + Swagger operation ID: `GetColumnNamesSchemaForWebhook`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2201,7 +2687,7 @@ async def get_column_names_schema_for_webhook_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2215,6 +2701,7 @@ async def get_column_names_schema_for_webhook_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2222,10 +2709,10 @@ async def get_column_names_schema_for_webhook_async( return json.loads(response.text) - async def get_schema_for_get_items_action_async( + def get_schema_for_get_items_action( self, - board_id: Optional[str] = None, *, + board_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2235,6 +2722,21 @@ async def get_schema_for_get_items_action_async( Get column names for a board ID for a webhook This operation gets the schema for the GetItems action. + + Swagger operation ID: `GetSchemaForGetItemsAction`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2249,7 +2751,7 @@ async def get_schema_for_get_items_action_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2263,6 +2765,7 @@ async def get_schema_for_get_items_action_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2270,10 +2773,10 @@ async def get_schema_for_get_items_action_async( return json.loads(response.text) - async def get_column_names_schema_for_update_webhook_async( + def get_column_names_schema_for_update_webhook( self, - board_id: Optional[str] = None, *, + board_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2284,6 +2787,21 @@ async def get_column_names_schema_for_update_webhook_async( This operation gets the column names for a board ID for a webhook (includes itemId). + + Swagger operation ID: `GetColumnNamesSchemaForUpdateWebhook`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2298,7 +2816,7 @@ async def get_column_names_schema_for_update_webhook_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2312,6 +2830,7 @@ async def get_column_names_schema_for_update_webhook_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2319,7 +2838,7 @@ async def get_column_names_schema_for_update_webhook_async( return json.loads(response.text) - async def get_subitem_column_names_async( + def get_subitem_column_names( self, parent_board_id: str, *, @@ -2332,6 +2851,21 @@ async def get_subitem_column_names_async( Get subitem column names Gets subitem column names in monday.com given a board ID. + + Swagger operation ID: `GetSubitemColumnNames`. + + Args: + parent_board_id: Specify the ID of the monday.com parent board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/getSchema/getSubitemColumnNames" @@ -2344,7 +2878,7 @@ async def get_subitem_column_names_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2358,6 +2892,7 @@ async def get_subitem_column_names_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2365,7 +2900,7 @@ async def get_subitem_column_names_async( return json.loads(response.text) - async def get_subitem_schema_async( + def get_subitem_schema( self, parent_board_id: str, *, @@ -2378,6 +2913,21 @@ async def get_subitem_schema_async( Get subitem column names Gets subitem schema in monday.com given a board ID. + + Swagger operation ID: `GetSubitemSchema`. + + Args: + parent_board_id: Specify the ID of the monday.com parent board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/getSchema/getSubitemSchema" @@ -2390,7 +2940,7 @@ async def get_subitem_schema_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2404,6 +2954,7 @@ async def get_subitem_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2411,10 +2962,10 @@ async def get_subitem_schema_async( return json.loads(response.text) - async def get_column_names_schema_for_item_name_change_webhook_async( + def get_column_names_schema_for_item_name_change_webhook( self, - board_id: Optional[str] = None, *, + board_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2425,6 +2976,21 @@ async def get_column_names_schema_for_item_name_change_webhook_async( This operation gets the column names for a board ID for a webhook when the item's name changes. + + Swagger operation ID: `GetColumnNamesSchemaForItemNameChangeWebhook`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2439,7 +3005,7 @@ async def get_column_names_schema_for_item_name_change_webhook_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2453,6 +3019,7 @@ async def get_column_names_schema_for_item_name_change_webhook_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2460,7 +3027,7 @@ async def get_column_names_schema_for_item_name_change_webhook_async( return json.loads(response.text) - async def get_column_names_schema_for_subitem_name_change_webhook_async( + def get_column_names_schema_for_subitem_name_change_webhook( self, parent_board_id: str, *, @@ -2474,6 +3041,22 @@ async def get_column_names_schema_for_subitem_name_change_webhook_async( This operation gets the column names for a board ID for a webhook when the subitem's name changes. + + Swagger operation ID: + `GetColumnNamesSchemaForSubitemNameChangeWebhook`. + + Args: + parent_board_id: Specify the ID of the monday.com parent board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2487,7 +3070,7 @@ async def get_column_names_schema_for_subitem_name_change_webhook_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2501,6 +3084,7 @@ async def get_column_names_schema_for_subitem_name_change_webhook_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2508,10 +3092,10 @@ async def get_column_names_schema_for_subitem_name_change_webhook_async( return json.loads(response.text) - async def get_column_names_schema_for_column_changes_webhook_async( + def get_column_names_schema_for_column_changes_webhook( self, - board_id: Optional[str] = None, *, + board_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2522,6 +3106,21 @@ async def get_column_names_schema_for_column_changes_webhook_async( This operation gets the column names for a board ID for a webhook (includes itemId). + + Swagger operation ID: `GetColumnNamesSchemaForColumnChangesWebhook`. + + Args: + board_id: Specify the ID of a monday.com board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2536,7 +3135,7 @@ async def get_column_names_schema_for_column_changes_webhook_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2550,6 +3149,7 @@ async def get_column_names_schema_for_column_changes_webhook_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/mq.py b/src/azure/connectors/mq.py index ece091e..548ab38 100644 --- a/src/azure/connectors/mq.py +++ b/src/azure/connectors/mq.py @@ -5,13 +5,12 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, Dict, List, Any, Mapping import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, @@ -19,6 +18,19 @@ ConnectorResponseHook, ) +__all__ = [ + "MqClient", + "Item", + "ItemsList", + "MultipleGetValidOptions", + "ObjectEntity", + "ProcedureMetadata", + "SendResponse", + "SendValidDataOptions", + "SendValidDataOptionsArray", + "SingleGetValidOptions", +] + # Type Definitions @@ -28,81 +40,100 @@ class Item: Response for Delete message """ - item_internal_id: Optional[str] = field( + item_internal_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ItemInternalId"}, ) - message_data: Optional[str] = field( - default=None, - metadata={"wire_name": "MessageData"}, - ) - message_id: Optional[str] = field( + message_data: str = dataclass_field(metadata={"wire_name": "MessageData"}) + message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageId"}, ) - correlation_id: Optional[str] = field( + correlation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CorrelationId"}, ) - put_date_time: Optional[str] = field( + put_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PutDateTime"}, ) - user_identifier: Optional[str] = field( + user_identifier: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UserIdentifier"}, ) - put_application_name: Optional[str] = field( + put_application_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PutApplicationName"}, ) - put_application_type: Optional[str] = field( + put_application_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PutApplicationType"}, ) - format: Optional[str] = field( + format: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Format"}, ) - accounting_token: Optional[str] = field( + accounting_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountingToken"}, ) - ccsid: Optional[int] = field(default=None, metadata={"wire_name": "Ccsid"}) - group_id: Optional[str] = field( + ccsid: Optional[int] = dataclass_field( default=None, + kw_only=True, + metadata={"wire_name": "Ccsid"}, + ) + group_id: Optional[str] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "GroupId"}, ) - logical_sequence_number: Optional[int] = field( + logical_sequence_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LogicalSequenceNumber"}, ) - message_type: Optional[str] = field( + message_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageType"}, ) - offset: Optional[int] = field( + offset: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Offset"}, ) - original_length: Optional[int] = field( + original_length: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OriginalLength"}, ) - persistence: Optional[str] = field( + persistence: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Persistence"}, ) - priority: Optional[int] = field( + priority: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Priority"}, ) - reply_to_queue: Optional[str] = field( + reply_to_queue: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyToQueue"}, ) - reply_to_queue_manager: Optional[str] = field( + reply_to_queue_manager: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyToQueueManager"}, ) @@ -113,7 +144,12 @@ class ItemsList: Response for Delete messages """ - value: Optional[List[Item]] = None + value: Optional[ + List[Item | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -122,20 +158,24 @@ class SendResponse: Response for Send message """ - item_internal_id: Optional[str] = field( + item_internal_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ItemInternalId"}, ) - message_data: Optional[str] = field( + message_data: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageData"}, ) - message_id: Optional[str] = field( + message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageId"}, ) - correlation_id: Optional[str] = field( + correlation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CorrelationId"}, ) @@ -146,9 +186,9 @@ class ProcedureMetadata: Definition: ProcedureMetadata """ - name: Optional[str] = None - title: Optional[str] = None - schema: Optional[ObjectEntity] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + title: Optional[str] = dataclass_field(default=None, kw_only=True) + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -157,7 +197,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -170,51 +210,63 @@ class SingleGetValidOptions: Definition: SingleGetValidOptions """ - queue: Optional[str] = field(default=None, metadata={"wire_name": "Queue"}) + queue: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Queue"}, + ) """When specified, overrides the queue defined in the connection.""" - message_id: Optional[str] = field( + message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageId"}, ) """Base64 string that represents a byte array with 24 bytes.""" - correlation_id: Optional[str] = field( + correlation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CorrelationId"}, ) """Base64 string that represents a byte array with 24 bytes.""" - group_id: Optional[str] = field( + group_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GroupId"}, ) """Base64 string that represents a byte array with 24 bytes.""" - message_token: Optional[str] = field( + message_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageToken"}, ) """Base64 string that represents a byte array with 16 bytes.""" - offset: Optional[float] = field( + offset: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Offset"}, ) """ Offset in bytes of the data in the physical message from the start of the logical message. """ - logical_sequence_number: Optional[float] = field( + logical_sequence_number: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LogicalSequenceNumber"}, ) """Sequence number of a logical message within a group.""" - include_info: Optional[str] = field( + include_info: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IncludeInfo"}, ) """ Indicates if additional message info should be included. Expects true or false. """ - timeout: Optional[str] = field( + timeout: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Timeout"}, ) """ @@ -229,59 +281,72 @@ class MultipleGetValidOptions: Definition: MultipleGetValidOptions """ - queue: Optional[str] = field(default=None, metadata={"wire_name": "Queue"}) + queue: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Queue"}, + ) """When specified, overrides the queue defined in the connection.""" - message_id: Optional[str] = field( + message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageId"}, ) """Base64 string that represents a byte array with 24 bytes.""" - correlation_id: Optional[str] = field( + correlation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CorrelationId"}, ) """Base64 string that represents a byte array with 24 bytes.""" - group_id: Optional[str] = field( + group_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GroupId"}, ) """Base64 string that represents a byte array with 24 bytes.""" - message_token: Optional[str] = field( + message_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageToken"}, ) """Base64 string that represents a byte array with 16 bytes.""" - offset: Optional[float] = field( + offset: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Offset"}, ) """ Offset in bytes of the data in the physical message from the start of the logical message. """ - logical_sequence_number: Optional[float] = field( + logical_sequence_number: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LogicalSequenceNumber"}, ) """Sequence number of a logical message within a group.""" - include_info: Optional[str] = field( + include_info: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IncludeInfo"}, ) """ Indicates if additional message info should be included. Expects true or false. """ - timeout: Optional[str] = field( + timeout: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Timeout"}, ) """ Wait time for a message to appear in the queue, expects an XML duration or hh:mm:ss. """ - batch_size: Optional[float] = field( + batch_size: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BatchSize"}, ) """Maximum number of messages to be retrieved from the queue.""" @@ -293,53 +358,62 @@ class SendValidDataOptions: Definition: SendValidDataOptions """ - queue: Optional[str] = field(default=None, metadata={"wire_name": "Queue"}) - """When specified, overrides the queue defined in the connection.""" - message: Optional[str] = field( + queue: Optional[str] = dataclass_field( default=None, - metadata={"wire_name": "Message"}, + kw_only=True, + metadata={"wire_name": "Queue"}, ) + """When specified, overrides the queue defined in the connection.""" + message: str = dataclass_field(metadata={"wire_name": "Message"}) """Message data""" - message_type: Optional[str] = field( + message_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageType"}, ) """Message type""" - correlation_id: Optional[str] = field( + correlation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CorrelationId"}, ) """Base64 string that represents a byte array with 24 bytes.""" - message_id: Optional[str] = field( + message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageId"}, ) """Base64 string that represents a byte array with 24 bytes.""" - reply_to_queue: Optional[str] = field( + reply_to_queue: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyToQueue"}, ) """Reply-to queue""" - reply_to_queue_manager: Optional[str] = field( + reply_to_queue_manager: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyToQueueManager"}, ) """Reply-to queue manager""" - code_char_set_id: Optional[float] = field( + code_char_set_id: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CodeCharSetId"}, ) """Character set for the message.""" - offset: Optional[float] = field( + offset: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Offset"}, ) """ Offset in bytes of the data in the physical message from the start of the logical message. """ - format: Optional[str] = field( + format: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Format"}, ) """Format field for the message.""" @@ -351,7 +425,7 @@ class SendValidDataOptionsArray: Definition: SendValidDataOptionsArray """ - messages: Optional[List[SendValidDataOptions]] = None + messages: List[SendValidDataOptions | Mapping[str, Any]] # Client Class @@ -362,16 +436,16 @@ class MqClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -382,8 +456,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -391,8 +465,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -404,7 +478,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -419,9 +493,9 @@ def __init__( def connector_name(self) -> str: return "mq" - async def delete_async( + def delete( self, - input: SingleGetValidOptions, + input: SingleGetValidOptions | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -432,10 +506,26 @@ async def delete_async( Delete message Deletes one message from the queue, by doing a destructive get. + + Swagger operation ID: `DeleteV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/delete" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -449,6 +539,7 @@ async def delete_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -456,9 +547,9 @@ async def delete_async( return json.loads(response.text) - async def delete_all_async( + def delete_all( self, - input: MultipleGetValidOptions, + input: MultipleGetValidOptions | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -469,10 +560,26 @@ async def delete_all_async( Delete messages Deletes messages from the queue, by doing a destructive get. + + Swagger operation ID: `DeleteAllV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/deleteall" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -486,6 +593,7 @@ async def delete_all_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -493,9 +601,9 @@ async def delete_all_async( return json.loads(response.text) - async def read_async( + def read( self, - input: SingleGetValidOptions, + input: SingleGetValidOptions | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -506,10 +614,26 @@ async def read_async( Browse message Browse one message from the queue. + + Swagger operation ID: `ReadV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/read" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -523,6 +647,7 @@ async def read_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -530,9 +655,9 @@ async def read_async( return json.loads(response.text) - async def read_all_async( + def read_all( self, - input: MultipleGetValidOptions, + input: MultipleGetValidOptions | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -543,10 +668,26 @@ async def read_all_async( Browse messages Browse messages in a queue. + + Swagger operation ID: `ReadAllV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/readall" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -560,6 +701,7 @@ async def read_all_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -567,9 +709,9 @@ async def read_all_async( return json.loads(response.text) - async def receive_async( + def receive( self, - input: SingleGetValidOptions, + input: SingleGetValidOptions | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -580,10 +722,26 @@ async def receive_async( Receive message Returns one message from the queue, by doing a destructive get. + + Swagger operation ID: `ReceiveV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/receive" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -597,6 +755,7 @@ async def receive_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -604,9 +763,9 @@ async def receive_async( return json.loads(response.text) - async def receive_all_async( + def receive_all( self, - input: MultipleGetValidOptions, + input: MultipleGetValidOptions | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -617,10 +776,26 @@ async def receive_all_async( Receive messages Returns messages from the queue, by doing a destructive get. + + Swagger operation ID: `ReceiveAllV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/receiveall" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -634,6 +809,7 @@ async def receive_all_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -641,9 +817,9 @@ async def receive_all_async( return json.loads(response.text) - async def send_async( + def send( self, - input: SendValidDataOptions, + input: SendValidDataOptions | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -654,10 +830,26 @@ async def send_async( Send message Send a message to a queue. + + Swagger operation ID: `SendV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/send" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -671,6 +863,7 @@ async def send_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/msgraphgroupsanduser.py b/src/azure/connectors/msgraphgroupsanduser.py index f30ba92..8bf951f 100644 --- a/src/azure/connectors/msgraphgroupsanduser.py +++ b/src/azure/connectors/msgraphgroupsanduser.py @@ -5,21 +5,34 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "MsgraphgroupsanduserClient", + "GetGroupPropertiesResponse", + "GetMemberGroupsInput", + "GetMemberGroupsResponse", + "GetMemberLicenseDetailsResponse", + "ListDirectGroupMembersResponse", + "ListGroupsByDisplayNameSearchResponse", + "ListSubscribedSkusResponse", + "ListUsersResponse", +] + # Type Definitions @@ -29,12 +42,13 @@ class ListUsersResponse: Response for List Users """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The Odata.context link.""" - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" @@ -44,17 +58,19 @@ class ListGroupsByDisplayNameSearchResponse: Response for List Groups By Display Name Search """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The Odata.context link.""" - count: Optional[int] = field( + count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.count"}, ) """@odata.count""" - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" @@ -64,12 +80,13 @@ class ListSubscribedSkusResponse: Response for List Subscribed Skus """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The Odata.context link.""" - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" @@ -79,17 +96,19 @@ class ListDirectGroupMembersResponse: Response for List Direct Group Members """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The Odata.context link.""" - count: Optional[int] = field( + count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.count"}, ) """@odata.count""" - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" @@ -99,12 +118,13 @@ class GetMemberLicenseDetailsResponse: Response for Get Member License Details """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The Odata.context link.""" - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" @@ -114,158 +134,185 @@ class GetGroupPropertiesResponse: Response for Get Group Properties """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The Odata.context link.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Object id of the group""" - deleted_date_time: Optional[str] = field( + deleted_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "deletedDateTime"}, ) """Group's deletion date time""" - classification: Optional[str] = None + classification: Optional[str] = dataclass_field(default=None, kw_only=True) """classification""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """Group's creation date time""" - creation_options: Optional[List[str]] = field( + creation_options: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "creationOptions"}, ) """Created options of the group.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """description""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Group's display name""" - expiration_date_time: Optional[str] = field( + expiration_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "expirationDateTime"}, ) """Group's expiration date time""" - group_types: Optional[List[str]] = field( + group_types: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "groupTypes"}, ) """Group types for the group.""" - is_assignable_to_role: Optional[str] = field( + is_assignable_to_role: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAssignableToRole"}, ) """Can a role be assigned to this group?""" - mail: Optional[str] = None + mail: Optional[str] = dataclass_field(default=None, kw_only=True) """Group's email""" - mail_enabled: Optional[bool] = field( + mail_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mailEnabled"}, ) """Is group email enabled?""" - mail_nickname: Optional[str] = field( + mail_nickname: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mailNickname"}, ) """Group's email nick name""" - membership_rule: Optional[str] = field( + membership_rule: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "membershipRule"}, ) """The rule that is used for membership evaluation.""" - membership_rule_processing_state: Optional[str] = field( + membership_rule_processing_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "membershipRuleProcessingState"}, ) """ The processing state of the rule that is used for membership evaluation. """ - on_premises_domain_name: Optional[str] = field( + on_premises_domain_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onPremisesDomainName"}, ) """ Contains the on-premises domainFQDN, also called dnsDomainName synchronized from the on-premises directory. """ - on_premises_last_sync_date_time: Optional[str] = field( + on_premises_last_sync_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onPremisesLastSyncDateTime"}, ) """ The time and date at which the tenant was last synced with the on-premise directory. """ - on_premises_net_bios_name: Optional[str] = field( + on_premises_net_bios_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onPremisesNetBiosName"}, ) """Name of networking service for on-premise server.""" - on_premises_sam_account_name: Optional[str] = field( + on_premises_sam_account_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onPremisesSamAccountName"}, ) """Sam account name for on-premise directory.""" - on_premises_security_identifier: Optional[str] = field( + on_premises_security_identifier: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onPremisesSecurityIdentifier"}, ) """The on-premises security identifier.""" - on_premises_sync_enabled: Optional[bool] = field( + on_premises_sync_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onPremisesSyncEnabled"}, ) """True if on-premises sync is enabled for the group.""" - preferred_data_location: Optional[str] = field( + preferred_data_location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "preferredDataLocation"}, ) """Preferred data location of the group.""" - preferred_language: Optional[str] = field( + preferred_language: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "preferredLanguage"}, ) """Preferred language as configured in Microsoft Entra ID.""" - proxy_addresses: Optional[List[str]] = field( + proxy_addresses: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "proxyAddresses"}, ) """Proxy addresses of the group.""" - renewed_date_time: Optional[str] = field( + renewed_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "renewedDateTime"}, ) """Renewed date time of the group.""" - resource_behavior_options: Optional[List[str]] = field( + resource_behavior_options: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceBehaviorOptions"}, ) """Resource behavior options of the group.""" - resource_provisioning_options: Optional[List[str]] = field( + resource_provisioning_options: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceProvisioningOptions"}, ) """Resource provisioning options of the group.""" - security_enabled: Optional[bool] = field( + security_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "securityEnabled"}, ) """Indicates if the group is security enabled.""" - security_identifier: Optional[str] = field( + security_identifier: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "securityIdentifier"}, ) """Security identifier of the group.""" - theme: Optional[str] = None + theme: Optional[str] = dataclass_field(default=None, kw_only=True) """Theme of Microsoft Entra ID group.""" - visibility: Optional[str] = None + visibility: Optional[str] = dataclass_field(default=None, kw_only=True) """Visibility of the group.""" - on_premises_provisioning_errors: Optional[List[str]] = field( + on_premises_provisioning_errors: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onPremisesProvisioningErrors"}, ) """On premise provisioning errors of the group.""" @@ -277,8 +324,7 @@ class GetMemberGroupsInput: Get Member Groups """ - security_enabled_only: Optional[bool] = field( - default=None, + security_enabled_only: bool = dataclass_field( metadata={"wire_name": "securityEnabledOnly"}, ) """Do you want to retrieve security enabled groups only?""" @@ -290,12 +336,13 @@ class GetMemberGroupsResponse: Response for Get Member Groups """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The Odata.context link.""" - value: Optional[List[str]] = None + value: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """value""" @@ -307,16 +354,16 @@ class MsgraphgroupsanduserClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -327,8 +374,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -336,8 +383,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -349,7 +396,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -364,55 +411,153 @@ def __init__( def connector_name(self) -> str: return "msgraphgroupsanduser" - async def list_users_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_users( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List Users Retrieve all users in the organization (Microsoft Entra ID Tenant) + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListUsers`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/users" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def list_groups_by_display_name_search_async( + return ItemPaged(get_next, extract_data) + + def list_groups_by_display_name_search( self, - search: Optional[str] = None, *, + search: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List Groups By Display Name Search Retrieve groups by searching group's display name + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListGroupsByDisplayNameSearch`. + + Args: + search: Search by keyword in display name of the Microsoft Entra ID + group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/groups" query_params = [] @@ -424,79 +569,160 @@ async def list_groups_by_display_name_search_async( query_params.append(f"$search={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def list_subscribed_skus_async( + return ItemPaged(get_next, extract_data) + + def list_subscribed_skus( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List Subscribed Skus Details of organization's subscribed license plan SKUs + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListSubscribedSkus`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/subscribedSkus" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def list_direct_group_members_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_direct_group_members( self, group_id: str, + *, filter: Optional[str] = None, select: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List Direct Group Members Retrieve direct members of a group with count + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListDirectGroupMembers`. + + Args: + group_id: Object ID of the Microsoft Entra ID group. + filter: Filter By. + select: Select which columns to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -516,42 +742,83 @@ async def list_direct_group_members_async( query_params.append(f"$select={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_member_license_details_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_member_license_details( self, id: str, - select: Optional[str] = None, *, + select: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Member License Details Retrieve group member(user)'s license details + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMemberLicenseDetails`. + + Args: + id: Object ID of the Microsoft Entra ID member(user). + select: Selection of data points(columns). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -565,29 +832,50 @@ async def get_member_license_details_async( query_params.append(f"$select={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_group_properties_async( + def get_group_properties( self, group_id: str, *, @@ -600,13 +888,28 @@ async def get_group_properties_async( Get Group Properties Retrieve properties and relationships of an Microsoft Entra ID group + + Swagger operation ID: `GetGroupProperties`. + + Args: + group_id: Object ID of the Microsoft Entra ID group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/groups/{quote(str(group_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -620,6 +923,7 @@ async def get_group_properties_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -627,43 +931,85 @@ async def get_group_properties_async( return json.loads(response.text) - async def get_member_groups_async( + def list_member_groups( self, - input: GetMemberGroupsInput, + input: GetMemberGroupsInput | Mapping[str, Any], member_id: str, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[str]: """ Get Member Groups Group memberships for a user (member) + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMemberGroups`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + member_id: Object ID of the Microsoft Entra ID member(user). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[str]: An Azure Core pager over connector results. Consume + it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/users/{quote(str(member_id), safe='')}/getMemberGroups" ) + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[str]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/office365.py b/src/azure/connectors/office365.py index 016fb85..7c21461 100644 --- a/src/azure/connectors/office365.py +++ b/src/azure/connectors/office365.py @@ -5,21 +5,144 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "Office365Client", + "ApprovalEmailResponse", + "ApprovalEmailSubscription", + "ApprovalMessage", + "AssignCategoryBulkInput", + "Attendee", + "AutomaticRepliesSettingClient", + "BatchItemFailureResult", + "BatchOperationResult", + "BatchResponseClientReceiveMessage", + "BatchResponseGraphClientReceiveMessage", + "BatchResponseSensitivityLabel", + "BlobDataSetsMetadata", + "CalendarEventBackend", + "CalendarEventClient", + "CalendarEventClientReceive", + "CalendarEventClientReceiveStringEnums", + "CalendarEventClientWithActionType", + "CalendarEventHtmlClient", + "CalendarEventList", + "CalendarEventListClientReceive", + "CalendarEventListWithActionType", + "CalendarGetTablesResponse", + "ClientReceiveFileAttachment", + "ClientReceiveMessage", + "ClientReceiveMessageStringEnums", + "ClientSendAttachment", + "ClientSendMessage", + "ClientSubscription", + "Contact", + "ContactResponse", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "DateTimeTimeZone", + "DirectForwardMessage", + "DraftEmailInput", + "EmailAddress", + "EmailAddressV2", + "EntityListResponseCalendarEventBackend", + "EntityListResponseCalendarEventClientReceiveStringEnums", + "EntityListResponseContactResponse", + "EntityListResponseFilePickerFile", + "EntityListResponseGraphCalendarEventClientReceive", + "EntityListResponseGraphContactFolder", + "EntityListResponseTable", + "FilePickerFile", + "FindMeetingTimesInput", + "FindMeetingTimesResponse", + "GeoCoordinates", + "GetAttachmentResponse", + "GetMailTipsInput", + "GetMailTipsResponse", + "GetRoomListsResponse", + "GetRoomsInRoomListResponse", + "GetRoomsResponse", + "GraphCalendarEventClient", + "GraphCalendarEventClientReceive", + "GraphCalendarEventClientWithActionType", + "GraphCalendarEventListClientReceive", + "GraphCalendarEventListWithActionType", + "GraphClientReceiveFileAttachment", + "GraphClientReceiveMessage", + "GraphContactFolder", + "GraphOutlookCategory", + "InternetMessageHeader", + "ItemBody", + "Location", + "LocationConstraint", + "MCPQueryRequest", + "MCPQueryResponse", + "MailTipsAutomaticReplies", + "MailTipsClientReceive", + "MarkAsReadInput", + "MeetingTimeSuggestions", + "MessageWithOptions", + "ObjectEntity", + "ObjectWithoutType", + "OptionsEmailSubscription", + "OutlookReceiveAttachment", + "OutlookReceiveMessage", + "PaginatedListResponseCalendarEventClientReceiveStringEnums", + "PassThroughNativeQuery", + "PatternedRecurrence", + "PhysicalAddress", + "Procedure", + "ReceiveMessageMetadata", + "Recipient", + "RecurrencePattern", + "RecurrenceRange", + "ReplyEmailInput", + "ReplyMessage", + "ResponseStatus", + "ResponseToEventInvite", + "SendEmailInput", + "SensitivityLabel", + "SensitivityLabelMetadata", + "SetAutomaticRepliesSettingInput", + "SetAutomaticRepliesSettingResponse", + "SharedMailboxClientSendMessage", + "SharedMailboxSendEmailInput", + "SubscriptionEvent", + "SubscriptionPayloadEntityOutlookReceiveMessage", + "SubscriptionPayloadEntitySubscriptionEvent", + "SubscriptionPayloadOutlookReceiveMessage", + "SubscriptionPayloadSubscriptionEvent", + "SubscriptionResponse", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TabularDataSetsMetadata", + "TriggerBatchResponseClientReceiveMessage", + "TriggerBatchResponseGraphClientReceiveMessage", + "TriggerBatchResponseReceiveMessageMetadata", + "UpdateEmailFlag", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,10 +152,11 @@ class GraphOutlookCategory: Response for Get Outlook category names """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the Outlook Category.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The display name of the Outlook Category.""" @@ -44,93 +168,119 @@ class OutlookReceiveMessage: Response for Draft an email message """ - internet_message_id: Optional[str] = field( + internet_message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InternetMessageId"}, ) """Internet Message Id""" - body_preview: Optional[str] = field( + body_preview: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BodyPreview"}, ) """Body preview""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Id""" - conversation_id: Optional[str] = field( + conversation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ConversationId"}, ) """Conversation Id""" - has_attachments: Optional[bool] = field( + has_attachments: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HasAttachments"}, ) """Has attachments""" - is_read: Optional[bool] = field( + is_read: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsRead"}, ) """Is read""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CreatedDateTime"}, ) """Created date and time""" - received_date_time: Optional[str] = field( + received_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDateTime"}, ) """Received date and time""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModifiedDateTime"}, ) """Last modified date and time""" - attachments: Optional[List[OutlookReceiveAttachment]] = field( + attachments: Optional[ + List[OutlookReceiveAttachment | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Attachments""" - to_recipients: Optional[List[Recipient]] = field( + to_recipients: Optional[List[Recipient | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ToRecipients"}, ) """To Recipient""" - cc_recipients: Optional[List[Recipient]] = field( + cc_recipients: Optional[List[Recipient | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CcRecipients"}, ) """Cc Recipients""" - bcc_recipients: Optional[List[Recipient]] = field( + bcc_recipients: Optional[List[Recipient | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BccRecipients"}, ) """Bcc Recipients""" - reply_to: Optional[List[Recipient]] = field( + reply_to: Optional[List[Recipient | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """The email addresses to use when replying""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Subject""" - body: Optional[ItemBody] = field( + body: Optional[ItemBody | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Body"}, ) - from_: Optional[Recipient] = field( + from_: Optional[Recipient | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "From"}, ) - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Importance""" - internet_message_headers: Optional[List[InternetMessageHeader]] = field( + internet_message_headers: Optional[ + List[InternetMessageHeader | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InternetMessageHeaders"}, ) """Internet message headers""" @@ -145,12 +295,18 @@ class BatchOperationResult: Response for Assign a category to multiple emails """ - success_count: Optional[int] = field( + success_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "successCount"}, ) """The count of messages processed successfully.""" - failures: Optional[List[BatchItemFailureResult]] = None + failures: Optional[ + List[BatchItemFailureResult | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of failed messages with errors.""" @@ -160,17 +316,19 @@ class SubscriptionResponse: Response for Send email with options """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id of the subscription""" - resource: Optional[str] = None + resource: Optional[str] = dataclass_field(default=None, kw_only=True) """Resource of the subscription request""" - notification_type: Optional[str] = field( + notification_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notificationType"}, ) """Notification Type""" - notification_url: Optional[str] = field( + notification_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notificationUrl"}, ) """Notification Url""" @@ -182,7 +340,7 @@ class ObjectWithoutType: Response for Send an HTTP request """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -195,12 +353,12 @@ class MCPQueryResponse: Response for Email Management MCP Server (deprecated) """ - jsonrpc: Optional[str] = None - id: Optional[str] = None - method: Optional[str] = None - params: Optional[Dict[str, Any]] = None - result: Optional[Dict[str, Any]] = None - error: Optional[Dict[str, Any]] = None + jsonrpc: Optional[str] = dataclass_field(default=None, kw_only=True) + id: Optional[str] = dataclass_field(default=None, kw_only=True) + method: Optional[str] = dataclass_field(default=None, kw_only=True) + params: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + result: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + error: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -209,153 +367,174 @@ class GraphCalendarEventClientReceive: Response for Get event """ - subject: Optional[str] = None + subject: Optional[str] = dataclass_field(default=None, kw_only=True) """Event subject""" - start: Optional[str] = None + start: Optional[str] = dataclass_field(default=None, kw_only=True) """Start time of the event (example: '2017-08-29T04:00:00.0000000')""" - end: Optional[str] = None + end: Optional[str] = dataclass_field(default=None, kw_only=True) """End time of the event (example: '2017-08-29T05:00:00.0000000')""" - start_with_time_zone: Optional[str] = field( + start_with_time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startWithTimeZone"}, ) """ Start time of the event with time zone (example: '2017-08-29T04:00:00.0000000+00:00') """ - end_with_time_zone: Optional[str] = field( + end_with_time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endWithTimeZone"}, ) """ End time of the event with time zone (example: '2017-08-29T05:00:00.0000000+00:00') """ - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """Body of the message associated with the event""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isHtml"}, ) """Set to true if the body is Html""" - response_type: Optional[str] = field( + response_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseType"}, ) """ The response type of the event (none, organizer, tentativelyAccepted, accepted, declined or notResponded) """ - response_time: Optional[str] = field( + response_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseTime"}, ) """The response time of the event""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The event's unique identifier""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """The date and time that the event was created""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """The date and time that the event was last modified""" - organizer: Optional[str] = None + organizer: Optional[str] = dataclass_field(default=None, kw_only=True) """The organizer of the event""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "timeZone"}, ) """Time zone of the event""" - series_master_id: Optional[str] = field( + series_master_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "seriesMasterId"}, ) """Unique identifier for Series Master event type""" - i_cal_u_id: Optional[str] = field( + i_cal_u_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "iCalUId"}, ) """ A unique identifier for an event across calendars. This ID is different for each occurrence in a recurring series """ - categories: Optional[List[str]] = None + categories: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """The categories associated with the event""" - web_link: Optional[str] = field( + web_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webLink"}, ) """The URL to open the event in Outlook Web App""" - required_attendees: Optional[str] = field( + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredAttendees"}, ) """Required attendees for the event separated by semicolons""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "optionalAttendees"}, ) """Optional attendees for the event separated by semicolons""" - resource_attendees: Optional[str] = field( + resource_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceAttendees"}, ) """Resource attendees for the event separated by semicolons""" - location: Optional[str] = None + location: Optional[str] = dataclass_field(default=None, kw_only=True) """Location of the event""" - importance: Optional[str] = None + importance: Optional[str] = dataclass_field(default=None, kw_only=True) """The importance of the event: low, normal, or high""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAllDay"}, ) """Set to true if the event lasts all day""" - recurrence: Optional[str] = None + recurrence: Optional[str] = dataclass_field(default=None, kw_only=True) """ The recurrence pattern for the event: none, daily, weekly, monthly or yearly """ - recurrence_end: Optional[str] = field( + recurrence_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recurrenceEnd"}, ) """End Date of the recurrence""" - number_of_occurences: Optional[int] = field( + number_of_occurences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "numberOfOccurences"}, ) """How many times to repeat the event""" - reminder_minutes_before_start: Optional[int] = field( + reminder_minutes_before_start: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reminderMinutesBeforeStart"}, ) """Time in minutes before event start to remind""" - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isReminderOn"}, ) """Set to true if an alert is set to remind the user of the event.""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showAs"}, ) """ Status to show during the event: free, tentative, busy, oof, workingElsewhere or unknown """ - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseRequested"}, ) """ Set to true if the sender would like a response when the event is accepted or declined """ - sensitivity: Optional[str] = None + sensitivity: Optional[str] = dataclass_field(default=None, kw_only=True) """The possible values are: normal, personal, private, confidential""" @@ -365,7 +544,12 @@ class GraphCalendarEventListClientReceive: Response for Get events """ - value: Optional[List[GraphCalendarEventClientReceive]] = None + value: Optional[ + List[GraphCalendarEventClientReceive | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of calendar items""" @@ -375,7 +559,12 @@ class GraphCalendarEventListWithActionType: Response for When an event is added, updated or deleted """ - value: Optional[List[GraphCalendarEventClientWithActionType]] = None + value: Optional[ + List[GraphCalendarEventClientWithActionType | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of calendar items""" @@ -385,7 +574,7 @@ class CalendarGetTablesResponse: Response for Get calendars """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" @@ -395,145 +584,170 @@ class ContactResponse: Response for Get contact """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's unique identifier.""" - parent_folder_id: Optional[str] = field( + parent_folder_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentFolderId"}, ) """The ID of the contact's parent folder""" - birthday: Optional[str] = None + birthday: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's birthday""" - file_as: Optional[str] = field( + file_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fileAs"}, ) """The name the contact is filed under""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The contact's display name""" - given_name: Optional[str] = field( + given_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "givenName"}, ) """The contact's given name""" - initials: Optional[str] = None + initials: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's initials""" - middle_name: Optional[str] = field( + middle_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "middleName"}, ) """The contact's middle name""" - nick_name: Optional[str] = field( + nick_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nickName"}, ) """The contact's nickname""" - surname: Optional[str] = None + surname: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's surname""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's title""" - generation: Optional[str] = None + generation: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's generation""" - email_addresses: Optional[List[EmailAddressV2]] = field( + email_addresses: Optional[List[EmailAddressV2 | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "emailAddresses"}, ) """The contact's email addresses""" - im_addresses: Optional[List[str]] = field( + im_addresses: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "imAddresses"}, ) """The contact's instant messaging (IM) addresses""" - job_title: Optional[str] = field( + job_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobTitle"}, ) """The contact's job title""" - company_name: Optional[str] = field( + company_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "companyName"}, ) """The name of the contact's company""" - department: Optional[str] = None + department: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's department""" - office_location: Optional[str] = field( + office_location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "officeLocation"}, ) """The location of the contact's office""" - profession: Optional[str] = None + profession: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's profession""" - business_home_page: Optional[str] = field( + business_home_page: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "businessHomePage"}, ) """The business home page of the contact""" - assistant_name: Optional[str] = field( + assistant_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assistantName"}, ) """The name of the contact's assistant""" - manager: Optional[str] = None + manager: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the contact's manager""" - home_phones: Optional[List[str]] = field( + home_phones: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "homePhones"}, ) """The contact's home phone numbers""" - business_phones: Optional[List[str]] = field( + business_phones: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "businessPhones"}, ) """The contact's business phone numbers""" - mobile_phone: Optional[str] = field( + mobile_phone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mobilePhone"}, ) """The contact's mobile phone number""" - home_address: Optional[PhysicalAddress] = field( + home_address: Optional[PhysicalAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "homeAddress"}, ) - business_address: Optional[PhysicalAddress] = field( + business_address: Optional[PhysicalAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "businessAddress"}, ) - other_address: Optional[PhysicalAddress] = field( + other_address: Optional[PhysicalAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "otherAddress"}, ) - yomi_company_name: Optional[str] = field( + yomi_company_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "yomiCompanyName"}, ) """The phonetic Japanese company name of the contact""" - yomi_given_name: Optional[str] = field( + yomi_given_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "yomiGivenName"}, ) """The phonetic Japanese given name (first name) of the contact""" - yomi_surname: Optional[str] = field( + yomi_surname: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "yomiSurname"}, ) """The phonetic Japanese surname (last name) of the contact""" - categories: Optional[List[str]] = None + categories: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """The categories associated with the contact""" - change_key: Optional[str] = field( + change_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "changeKey"}, ) """Identifies the version of the event object""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """The time the contact was created""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """The time the contact was modified""" @@ -545,10 +759,16 @@ class EntityListResponseContactResponse: Response for Get contacts """ - value: Optional[List[ContactResponse]] = None + value: Optional[ + List[ContactResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -560,7 +780,12 @@ class EntityListResponseGraphContactFolder: Response for Get contact folders """ - value: Optional[List[GraphContactFolder]] = None + value: Optional[ + List[GraphContactFolder | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -570,50 +795,66 @@ class FindMeetingTimesInput: Find meeting times """ - required_attendees: Optional[str] = field( + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequiredAttendees"}, ) """List of semicolon separated email addresses""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OptionalAttendees"}, ) """List of semicolon separated email addresses""" - resource_attendees: Optional[str] = field( + resource_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceAttendees"}, ) """Resource attendees for the event separated by semicolons""" - meeting_duration: Optional[int] = field( + meeting_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MeetingDuration"}, ) """Duration of the meeting in minutes""" - start: Optional[str] = field(default=None, metadata={"wire_name": "Start"}) + start: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Start"}, + ) """Start time for meeting time suggestions""" - end: Optional[str] = field(default=None, metadata={"wire_name": "End"}) + end: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "End"}, + ) """End time for meeting time suggestions""" - max_candidates: Optional[int] = field( + max_candidates: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MaxCandidates"}, ) """The maximum number of meeting suggestions to return in the response""" - minimum_attendee_percentage: Optional[str] = field( + minimum_attendee_percentage: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MinimumAttendeePercentage"}, ) """ The minimum required confidence for a time slot to be returned in the response """ - is_organizer_optional: Optional[bool] = field( + is_organizer_optional: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsOrganizerOptional"}, ) """true if the organizer doesn't have to attend. The default is false""" - activity_domain: Optional[str] = field( + activity_domain: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ActivityDomain"}, ) """Work, Personal, Unrestricted, or Unknown""" @@ -625,13 +866,15 @@ class FindMeetingTimesResponse: Response for Find meeting times """ - empty_suggestions_reason: Optional[str] = field( + empty_suggestions_reason: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "emptySuggestionsReason"}, ) """Empty Suggestions Reason""" - meeting_time_suggestions: Optional[MeetingTimeSuggestions] = field( + meeting_time_suggestions: Optional[MeetingTimeSuggestions] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "meetingTimeSuggestions"}, ) @@ -642,39 +885,47 @@ class GetAttachmentResponse: Response for Get Attachment """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id of the attachment.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of attachment.""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentType"}, ) """Content type of attachment.""" - size: Optional[int] = None + size: Optional[int] = dataclass_field(default=None, kw_only=True) """Size of attachment.""" - content_bytes: Optional[str] = field( + content_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentBytes"}, ) """Content of attachment.""" - is_inline: Optional[bool] = field( + is_inline: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isInline"}, ) """Set to true if this is an inline attachment.""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """The date and time when the attachment was last modified.""" - content_id: Optional[str] = field( + content_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentId"}, ) """Content Id""" - sensitivity_label_info: Optional[List[SensitivityLabelMetadata]] = field( + sensitivity_label_info: Optional[ + List[SensitivityLabelMetadata | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelInfo"}, ) @@ -685,75 +936,98 @@ class GraphClientReceiveMessage: Response for Get email """ - from_: Optional[str] = field(default=None, metadata={"wire_name": "from"}) + from_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "from"}, + ) """The mailbox owner and sender of the message""" - to_recipients: Optional[str] = field( + to_recipients: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "toRecipients"}, ) """The recipients for the message""" - cc_recipients: Optional[str] = field( + cc_recipients: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ccRecipients"}, ) """The Cc recipients for the message""" - bcc_recipients: Optional[str] = field( + bcc_recipients: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "bccRecipients"}, ) """The Bcc recipients for the message""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "replyTo"}, ) """The email addresses to use when replying""" - subject: Optional[str] = None + subject: Optional[str] = dataclass_field(default=None, kw_only=True) """The subject of the message""" - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """The body of the message""" - importance: Optional[str] = None + importance: Optional[str] = dataclass_field(default=None, kw_only=True) """The importance of the message (low, normal, high)""" - body_preview: Optional[str] = field( + body_preview: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "bodyPreview"}, ) """The preview of the message""" - has_attachments: Optional[bool] = field( + has_attachments: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasAttachments"}, ) """Indicates whether the message has attachments""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique identifier of the message""" - internet_message_id: Optional[str] = field( + internet_message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "internetMessageId"}, ) """The message ID in the format specified by RFC2822""" - conversation_id: Optional[str] = field( + conversation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "conversationId"}, ) """The Id of the conversation the email belongs to""" - received_date_time: Optional[str] = field( + received_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "receivedDateTime"}, ) """The date and time the message was received""" - is_read: Optional[bool] = field( + is_read: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isRead"}, ) """Indicates whether the message has been read""" - attachments: Optional[List[GraphClientReceiveFileAttachment]] = None + attachments: Optional[ + List[GraphClientReceiveFileAttachment | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The file attachments for the message""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isHtml"}, ) """Is Html?""" - sensitivity_label_info: Optional[List[SensitivityLabelMetadata]] = field( + sensitivity_label_info: Optional[ + List[SensitivityLabelMetadata | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelInfo"}, ) @@ -764,7 +1038,12 @@ class BatchResponseGraphClientReceiveMessage: Response for Get emails """ - value: Optional[List[GraphClientReceiveMessage]] = None + value: Optional[ + List[GraphClientReceiveMessage | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A list of the response objects""" @@ -774,7 +1053,12 @@ class EntityListResponseGraphCalendarEventClientReceive: Response for Get calendar view of events """ - value: Optional[List[GraphCalendarEventClientReceive]] = None + value: Optional[ + List[GraphCalendarEventClientReceive | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -784,13 +1068,11 @@ class GetMailTipsInput: Get mail tips for a mailbox """ - mail_tips_options: Optional[str] = field( - default=None, + mail_tips_options: str = dataclass_field( metadata={"wire_name": "MailTipsOptions"}, ) """Flags that represents the mailtips.""" - email_addresses: Optional[List[str]] = field( - default=None, + email_addresses: List[str] = dataclass_field( metadata={"wire_name": "EmailAddresses"}, ) """Address of the mailbox to get mail tips for.""" @@ -802,7 +1084,12 @@ class GetMailTipsResponse: Response for Get mail tips for a mailbox """ - value: Optional[List[MailTipsClientReceive]] = None + value: Optional[ + List[MailTipsClientReceive | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -811,7 +1098,7 @@ class GetRoomListsResponse: Response for Get room lists """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" @@ -821,7 +1108,7 @@ class GetRoomsResponse: Response for Get rooms """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" @@ -831,7 +1118,7 @@ class GetRoomsInRoomListResponse: Response for Get rooms in room list """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" @@ -841,10 +1128,7 @@ class MarkAsReadInput: Mark as read or unread """ - is_read: Optional[bool] = field( - default=None, - metadata={"wire_name": "isRead"}, - ) + is_read: bool = dataclass_field(metadata={"wire_name": "isRead"}) """Mark as read/unread.""" @@ -854,7 +1138,12 @@ class TriggerBatchResponseGraphClientReceiveMessage: Response for When an email is flagged """ - value: Optional[List[GraphClientReceiveMessage]] = None + value: Optional[ + List[GraphClientReceiveMessage | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A list of the response objects""" @@ -864,8 +1153,11 @@ class SetAutomaticRepliesSettingInput: Set up automatic replies """ - automatic_replies_setting: Optional[AutomaticRepliesSettingClient] = field( + automatic_replies_setting: Optional[ + AutomaticRepliesSettingClient | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "automaticRepliesSetting"}, ) @@ -876,8 +1168,11 @@ class SetAutomaticRepliesSettingResponse: Response for Set up automatic replies """ - automatic_replies_setting: Optional[AutomaticRepliesSettingClient] = field( + automatic_replies_setting: Optional[ + AutomaticRepliesSettingClient | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "automaticRepliesSetting"}, ) @@ -888,26 +1183,30 @@ class TableMetadata: Definition: TableMetadata """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Table name""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Table title""" - x_ms_permission: Optional[str] = field( + x_ms_permission: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-permission"}, ) """Table permission""" - x_ms_capabilities: Optional[TableCapabilitiesMetadata] = field( + x_ms_capabilities: Optional[TableCapabilitiesMetadata | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-capabilities"}, ) - schema: Optional[ObjectEntity] = None - referenced_entities: Optional[ObjectEntity] = field( + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + referenced_entities: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "referencedEntities"}, ) - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webUrl"}, ) """Url link""" @@ -919,30 +1218,42 @@ class TableCapabilitiesMetadata: Definition: TableCapabilitiesMetadata """ - sort_restrictions: Optional[TableSortRestrictionsMetadata] = field( + sort_restrictions: Optional[ + TableSortRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sortRestrictions"}, ) - filter_restrictions: Optional[TableFilterRestrictionsMetadata] = field( + filter_restrictions: Optional[ + TableFilterRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterRestrictions"}, ) - select_restrictions: Optional[TableSelectRestrictionsMetadata] = field( + select_restrictions: Optional[ + TableSelectRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selectRestrictions"}, ) - is_only_server_pagable: Optional[bool] = field( + is_only_server_pagable: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isOnlyServerPagable"}, ) """Server paging restrictions""" - filter_function_support: Optional[List[str]] = field( + filter_function_support: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterFunctionSupport"}, ) """List of supported filter capabilities""" - server_paging_options: Optional[List[str]] = field( + server_paging_options: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "serverPagingOptions"}, ) """List of supported server-driven paging capabilities""" @@ -954,7 +1265,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -967,15 +1278,17 @@ class TableSortRestrictionsMetadata: Definition: TableSortRestrictionsMetadata """ - sortable: Optional[bool] = None + sortable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has sortable columns""" - unsortable_properties: Optional[List[str]] = field( + unsortable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "unsortableProperties"}, ) """List of unsortable properties""" - ascending_only_properties: Optional[List[str]] = field( + ascending_only_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ascendingOnlyProperties"}, ) """List of properties which support ascending order only""" @@ -987,15 +1300,17 @@ class TableFilterRestrictionsMetadata: Definition: TableFilterRestrictionsMetadata """ - filterable: Optional[bool] = None + filterable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has filterable columns""" - non_filterable_properties: Optional[List[str]] = field( + non_filterable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nonFilterableProperties"}, ) """List of non filterable properties""" - required_properties: Optional[List[str]] = field( + required_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredProperties"}, ) """List of required properties""" @@ -1007,7 +1322,7 @@ class TableSelectRestrictionsMetadata: Definition: TableSelectRestrictionsMetadata """ - selectable: Optional[bool] = None + selectable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has selectable columns""" @@ -1017,7 +1332,12 @@ class CalendarEventList: Definition: CalendarEventList """ - value: Optional[List[CalendarEventBackend]] = None + value: Optional[ + List[CalendarEventBackend | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of calendar items""" @@ -1027,153 +1347,183 @@ class CalendarEventBackend: Definition: CalendarEventBackend """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The Event's unique identifier""" - attendees: Optional[List[Attendee]] = field( + attendees: Optional[List[Attendee | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attendees"}, ) """List of attendees for the event""" - body: Optional[ItemBody] = field( + body: Optional[ItemBody | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Body"}, ) - body_preview: Optional[str] = field( + body_preview: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BodyPreview"}, ) """The preview of the message associated with the event""" - categories: Optional[List[str]] = field( + categories: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Categories"}, ) """The categories associated with the event""" - change_key: Optional[str] = field( + change_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChangeKey"}, ) """ This property identifies the version of the event object. Every time the event is changed, ChangeKey changes as well. """ - date_time_created: Optional[str] = field( + date_time_created: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeCreated"}, ) """The date and time that the event was created""" - date_time_last_modified: Optional[str] = field( + date_time_last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeLastModified"}, ) """The date and time that the event was last modified""" - end: Optional[str] = field(default=None, metadata={"wire_name": "End"}) + end: str = dataclass_field(metadata={"wire_name": "End"}) """The end time of the event""" - end_time_zone: Optional[str] = field( + end_time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EndTimeZone"}, ) """ This property specifies the time zone of the meeting end time. The value must be as defined in Windows (example: 'Pacific Standard Time'). """ - has_attachments: Optional[bool] = field( + has_attachments: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HasAttachments"}, ) """Set to true if the event has attachments""" - i_cal_u_id: Optional[str] = field( + i_cal_u_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ICalUId"}, ) """ A unique identifier that is shared by all instances of an event across different calendars """ - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the event: Low, Normal, or High""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAllDay"}, ) """Set to true if the event lasts all day""" - is_cancelled: Optional[bool] = field( + is_cancelled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsCancelled"}, ) """Set to true if the event has been canceled""" - is_organizer: Optional[bool] = field( + is_organizer: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsOrganizer"}, ) """Set to true if the message sender is also the organizer""" - location: Optional[Location] = field( + location: Optional[Location | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) - organizer: Optional[Recipient] = field( + organizer: Optional[Recipient | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Organizer"}, ) - recurrence: Optional[PatternedRecurrence] = field( + recurrence: Optional[PatternedRecurrence | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Recurrence"}, ) - reminder: Optional[int] = field( + reminder: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reminder"}, ) """Time in minutes before event start to remind""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseRequested"}, ) """ Set to true if the sender would like a response when the event is accepted or declined """ - response_status: Optional[ResponseStatus] = field( + response_status: Optional[ResponseStatus | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseStatus"}, ) - series_master_id: Optional[str] = field( + series_master_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SeriesMasterId"}, ) """Unique identifier for Series Master event type""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowAs"}, ) """Shows as free or busy""" - start: Optional[str] = field(default=None, metadata={"wire_name": "Start"}) + start: str = dataclass_field(metadata={"wire_name": "Start"}) """The start time of the event""" - start_time_zone: Optional[str] = field( + start_time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartTimeZone"}, ) """ This property specifies the time zone of the meeting start time. The value must be as defined in Windows (example: 'Pacific Standard Time'). """ - subject: Optional[str] = field( + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) + """Event subject""" + type_: Optional[str] = dataclass_field( default=None, - metadata={"wire_name": "Subject"}, + kw_only=True, + metadata={"wire_name": "Type"}, ) - """Event subject""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) """ The event type: Single Instance, Occurrence, Exception, or Series Master """ - web_link: Optional[str] = field( + web_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebLink"}, ) """The preview of the message associated with the event""" - reason: Optional[str] = field( + reason: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reason"}, ) """ @@ -1188,13 +1538,19 @@ class Attendee: Definition: Attendee """ - status: Optional[ResponseStatus] = field( + status: Optional[ResponseStatus | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Status"}, ) - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) - email_address: Optional[EmailAddress] = field( + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Type"}, + ) + email_address: Optional[EmailAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmailAddress"}, ) @@ -1205,12 +1561,14 @@ class ItemBody: Definition: ItemBody """ - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentType"}, ) - content: Optional[str] = field( + content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Content"}, ) @@ -1221,16 +1579,19 @@ class Location: Definition: Location """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) - address: Optional[PhysicalAddress] = field( + address: Optional[PhysicalAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Address"}, ) - coordinates: Optional[GeoCoordinates] = field( + coordinates: Optional[GeoCoordinates | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Coordinates"}, ) @@ -1241,8 +1602,9 @@ class Recipient: Definition: Recipient """ - email_address: Optional[EmailAddress] = field( + email_address: Optional[EmailAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmailAddress"}, ) @@ -1253,12 +1615,14 @@ class PatternedRecurrence: Definition: PatternedRecurrence """ - pattern: Optional[RecurrencePattern] = field( + pattern: Optional[RecurrencePattern | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Pattern"}, ) - range: Optional[RecurrenceRange] = field( + range: Optional[RecurrenceRange | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Range"}, ) @@ -1269,11 +1633,16 @@ class ResponseStatus: Definition: ResponseStatus """ - response: Optional[str] = field( + response: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Response"}, ) - time: Optional[str] = field(default=None, metadata={"wire_name": "Time"}) + time: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Time"}, + ) @dataclass @@ -1282,9 +1651,14 @@ class EmailAddress: Definition: EmailAddress """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) - address: Optional[str] = field( + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) + address: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Address"}, ) @@ -1295,24 +1669,29 @@ class GeoCoordinates: Definition: GeoCoordinates """ - altitude: Optional[float] = field( + altitude: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Altitude"}, ) - latitude: Optional[float] = field( + latitude: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Latitude"}, ) - longitude: Optional[float] = field( + longitude: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Longitude"}, ) - accuracy: Optional[float] = field( + accuracy: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Accuracy"}, ) - altitude_accuracy: Optional[float] = field( + altitude_accuracy: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AltitudeAccuracy"}, ) @@ -1323,25 +1702,41 @@ class RecurrencePattern: Definition: RecurrencePattern """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) - interval: Optional[int] = field( + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Type"}, + ) + interval: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Interval"}, ) - month: Optional[int] = field(default=None, metadata={"wire_name": "Month"}) - day_of_month: Optional[int] = field( + month: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Month"}, + ) + day_of_month: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DayOfMonth"}, ) - days_of_week: Optional[List[str]] = field( + days_of_week: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DaysOfWeek"}, ) - first_day_of_week: Optional[str] = field( + first_day_of_week: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FirstDayOfWeek"}, ) - index: Optional[str] = field(default=None, metadata={"wire_name": "Index"}) + index: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Index"}, + ) @dataclass @@ -1350,17 +1745,24 @@ class RecurrenceRange: Definition: RecurrenceRange """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) - start_date: Optional[str] = field( + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Type"}, + ) + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartDate"}, ) - end_date: Optional[str] = field( + end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EndDate"}, ) - number_of_occurrences: Optional[int] = field( + number_of_occurrences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfOccurrences"}, ) @@ -1371,7 +1773,12 @@ class CalendarEventListClientReceive: Definition: CalendarEventListClientReceive """ - value: Optional[List[CalendarEventClientReceive]] = None + value: Optional[ + List[CalendarEventClientReceive | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of calendar items""" @@ -1381,143 +1788,183 @@ class CalendarEventClientReceive: Definition: CalendarEventClientReceive """ - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Event subject""" - start: Optional[str] = field(default=None, metadata={"wire_name": "Start"}) + start: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Start"}, + ) """Start time of the event (example: '2016-11-01T14:30:00Z')""" - end: Optional[str] = field(default=None, metadata={"wire_name": "End"}) + end: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "End"}, + ) """End time of the event (example: '2016-11-01T15:30:00Z')""" - show_as: Optional[int] = field( + show_as: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowAs"}, ) """ Status to show during the event (Unknown - -1, Free - 0, Tentative - 1, Busy - 2, Oof - 3, WorkingElsewhere - 4) """ - recurrence: Optional[int] = field( + recurrence: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Recurrence"}, ) """ The recurrence pattern for the event (None - 0, Daily - 1, Weekly - 2, Monthly - 3, Yearly - 4) """ - response_type: Optional[int] = field( + response_type: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseType"}, ) """ The response type of the event (None - 0, Organizer - 1, TentativelyAccepted - 2, Accepted - 3, Declined - 4, NotResponded - 5) """ - response_time: Optional[str] = field( + response_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseTime"}, ) """The response time of the event""" - i_cal_u_id: Optional[str] = field( + i_cal_u_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ICalUId"}, ) """ A unique identifier that is shared by all instances of an event across different calendars """ - importance: Optional[int] = field( + importance: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the event (0 - Low, 1 - Normal, 2 - High)""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The event's unique identifier""" - date_time_created: Optional[str] = field( + date_time_created: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeCreated"}, ) """The date and time that the event was created""" - date_time_last_modified: Optional[str] = field( + date_time_last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeLastModified"}, ) """The date and time that the event was last modified""" - organizer: Optional[str] = field( + organizer: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Organizer"}, ) """The organizer of the event""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TimeZone"}, ) """Time zone of the event""" - series_master_id: Optional[str] = field( + series_master_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SeriesMasterId"}, ) """Unique identifier for Series Master event type""" - categories: Optional[List[str]] = field( + categories: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Categories"}, ) """The categories associated with the event""" - web_link: Optional[str] = field( + web_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebLink"}, ) """The URL to open the event in Outlook Web App""" - required_attendees: Optional[str] = field( + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequiredAttendees"}, ) """Required attendees for the event separated by semicolons""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OptionalAttendees"}, ) """Optional attendees for the event separated by semicolons""" - resource_attendees: Optional[str] = field( + resource_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceAttendees"}, ) """Resource attendees for the event separated by semicolons""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Body of the message associated with the event""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Set to true if the body is Html""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location of the event""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAllDay"}, ) """Set to true if the event lasts all day""" - recurrence_end: Optional[str] = field( + recurrence_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecurrenceEnd"}, ) """End time of the recurrence""" - number_of_occurrences: Optional[int] = field( + number_of_occurrences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfOccurrences"}, ) """How many times to repeat the event""" - reminder: Optional[int] = field( + reminder: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reminder"}, ) """Time in minutes before event start to remind""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseRequested"}, ) """ @@ -1532,8 +1979,11 @@ class PaginatedListResponseCalendarEventClientReceiveStringEnums: Definition: PaginatedListResponse[CalendarEventClientReceiveStringEnums] """ - values: Optional[List[CalendarEventClientReceiveStringEnums]] = field( + values: Optional[ + List[CalendarEventClientReceiveStringEnums | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Values"}, ) """Values""" @@ -1545,137 +1995,177 @@ class CalendarEventClientReceiveStringEnums: Definition: CalendarEventClientReceiveStringEnums """ - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the event: Low, Normal, or High""" - response_type: Optional[str] = field( + response_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseType"}, ) """ The response type of the event: None, Organizer, TentativelyAccepted, Accepted, Declined or NotResponded """ - recurrence: Optional[str] = field( + recurrence: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Recurrence"}, ) """The recurrence pattern for the event""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowAs"}, ) """Status to show during the event""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Event subject""" - start: Optional[str] = field(default=None, metadata={"wire_name": "Start"}) + start: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Start"}, + ) """Start time of the event (example: '2016-11-01T14:30:00Z')""" - end: Optional[str] = field(default=None, metadata={"wire_name": "End"}) + end: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "End"}, + ) """End time of the event (example: '2016-11-01T15:30:00Z')""" - response_time: Optional[str] = field( + response_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseTime"}, ) """The response time of the event""" - i_cal_u_id: Optional[str] = field( + i_cal_u_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ICalUId"}, ) """ A unique identifier that is shared by all instances of an event across different calendars """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The event's unique identifier""" - date_time_created: Optional[str] = field( + date_time_created: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeCreated"}, ) """The date and time that the event was created""" - date_time_last_modified: Optional[str] = field( + date_time_last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeLastModified"}, ) """The date and time that the event was last modified""" - organizer: Optional[str] = field( + organizer: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Organizer"}, ) """The organizer of the event""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TimeZone"}, ) """Time zone of the event""" - series_master_id: Optional[str] = field( + series_master_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SeriesMasterId"}, ) """Unique identifier for Series Master event type""" - categories: Optional[List[str]] = field( + categories: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Categories"}, ) """The categories associated with the event""" - web_link: Optional[str] = field( + web_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebLink"}, ) """The URL to open the event in Outlook Web App""" - required_attendees: Optional[str] = field( + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequiredAttendees"}, ) """Required attendees for the event separated by semicolons""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OptionalAttendees"}, ) """Optional attendees for the event separated by semicolons""" - resource_attendees: Optional[str] = field( + resource_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceAttendees"}, ) """Resource attendees for the event separated by semicolons""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Body of the message associated with the event""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Set to true if the body is Html""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location of the event""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAllDay"}, ) """Set to true if the event lasts all day""" - recurrence_end: Optional[str] = field( + recurrence_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecurrenceEnd"}, ) """End time of the recurrence""" - number_of_occurrences: Optional[int] = field( + number_of_occurrences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfOccurrences"}, ) """How many times to repeat the event""" - reminder: Optional[int] = field( + reminder: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reminder"}, ) """Time in minutes before event start to remind""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseRequested"}, ) """ @@ -1690,8 +2180,7 @@ class ClientSubscription: Definition: ClientSubscription """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "NotificationUrl"}, ) """ @@ -1706,7 +2195,12 @@ class EntityListResponseFilePickerFile: Definition: EntityListResponse[FilePickerFile] """ - value: Optional[List[FilePickerFile]] = None + value: Optional[ + List[FilePickerFile | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -1716,19 +2210,29 @@ class FilePickerFile: Definition: FilePickerFile """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Uniquely identifies the file""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Display name for the file""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """Set to true if the file is a folder""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """Path of the file""" @@ -1738,54 +2242,68 @@ class ClientSendMessage: Definition: ClientSendMessage """ - from_: Optional[str] = field(default=None, metadata={"wire_name": "From"}) + from_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "From"}, + ) """ Email address to send mail from (requires \"Send as\" or \"Send on behalf of\" permission for that mailbox). For more info on granting permissions please refer https://docs.microsoft.com/office365/admin/manage/send-email-as-distribution-list """ - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """ Specify email addresses separated by semicolons like someone@contoso.com """ - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """ Specify email addresses separated by semicolons like someone@contoso.com """ - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: str = dataclass_field(metadata={"wire_name": "To"}) """ Specify email addresses separated by semicolons like someone@contoso.com """ - subject: Optional[str] = field( - default=None, - metadata={"wire_name": "Subject"}, - ) + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) """Specify the subject of the mail""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: str = dataclass_field(metadata={"wire_name": "Body"}) """Specify the body of the mail""" - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Attachments""" - sensitivity: Optional[str] = field( + sensitivity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sensitivity"}, ) """Sensitivity""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """The email addresses to use when replying""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Importance""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Is Html?""" @@ -1797,10 +2315,9 @@ class ClientSendAttachment: Definition: ClientSendAttachment """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: str = dataclass_field(metadata={"wire_name": "Name"}) """Attachment name""" - content_bytes: Optional[str] = field( - default=None, + content_bytes: str = dataclass_field( metadata={"wire_name": "ContentBytes"}, ) """Attachment content""" @@ -1812,70 +2329,107 @@ class ClientReceiveMessageStringEnums: Definition: ClientReceiveMessageStringEnums """ - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the message""" - from_: Optional[str] = field(default=None, metadata={"wire_name": "From"}) + from_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "From"}, + ) """The mailbox owner and sender of the message""" - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "To"}, + ) """The recipients for the message""" - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """The Cc recipients for the message""" - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """The Bcc recipients for the message""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """The email addresses to use when replying""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """The subject of the message""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """The body of the message""" - body_preview: Optional[str] = field( + body_preview: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BodyPreview"}, ) """The preview of the message""" - has_attachment: Optional[bool] = field( + has_attachment: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HasAttachment"}, ) """Indicates whether the message has attachments""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique identifier of the message""" - internet_message_id: Optional[str] = field( + internet_message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InternetMessageId"}, ) """The message ID in the format specified by RFC2822""" - conversation_id: Optional[str] = field( + conversation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ConversationId"}, ) """The Id of the conversation the email belongs to""" - date_time_received: Optional[str] = field( + date_time_received: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeReceived"}, ) """The date and time the message was received""" - is_read: Optional[bool] = field( + is_read: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsRead"}, ) """Indicates whether the message has been read""" - attachments: Optional[List[ClientReceiveFileAttachment]] = field( + attachments: Optional[ + List[ClientReceiveFileAttachment | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """The file attachments for the message""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Is Html?""" @@ -1887,34 +2441,51 @@ class ClientReceiveFileAttachment: Definition: ClientReceiveFileAttachment """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Attachment Id""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Attachment name""" - content_bytes: Optional[str] = field( + content_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentBytes"}, ) """Attachment content""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentType"}, ) """Attachment content type""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size in bytes of the attachment""" - is_inline: Optional[bool] = field( + is_inline: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsInline"}, ) """Set to true if this is an inline attachment""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModifiedDateTime"}, ) """The date and time when the attachment was last modified""" - content_id: Optional[str] = field( + content_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentId"}, ) """Content Id""" @@ -1926,49 +2497,62 @@ class SendEmailInput: Definition: ClientSendHtmlMessage """ - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: str = dataclass_field(metadata={"wire_name": "To"}) """ Specify email addresses separated by semicolons like someone@contoso.com """ - subject: Optional[str] = field( - default=None, - metadata={"wire_name": "Subject"}, - ) + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) """Specify the subject of the mail""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: str = dataclass_field(metadata={"wire_name": "Body"}) """Specify the body of the mail""" - from_: Optional[str] = field(default=None, metadata={"wire_name": "From"}) + from_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "From"}, + ) """ Email address to send mail from (requires \"Send as\" or \"Send on behalf of\" permission for that mailbox). For more info on granting permissions please refer https://docs.microsoft.com/office365/admin/manage/send-email-as-distribution-list """ - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """ Specify email addresses separated by semicolons like someone@contoso.com """ - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """ Specify email addresses separated by semicolons like someone@contoso.com """ - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Attachments""" - sensitivity: Optional[str] = field( + sensitivity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sensitivity"}, ) """Sensitivity""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """The email addresses to use when replying""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Importance""" @@ -1980,49 +2564,62 @@ class DraftEmailInput: Definition: ClientDraftHtmlMessage """ - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: str = dataclass_field(metadata={"wire_name": "To"}) """ Specify email addresses separated by semicolons like someone@contoso.com """ - subject: Optional[str] = field( - default=None, - metadata={"wire_name": "Subject"}, - ) + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) """Specify the subject of the mail""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: str = dataclass_field(metadata={"wire_name": "Body"}) """Specify the body of the mail""" - from_: Optional[str] = field(default=None, metadata={"wire_name": "From"}) + from_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "From"}, + ) """ Email address to send mail from (requires \"Send as\" or \"Send on behalf of\" permission for that mailbox). For more info on granting permissions please refer https://docs.microsoft.com/office365/admin/manage/send-email-as-distribution-list """ - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """ Specify email addresses separated by semicolons like someone@contoso.com """ - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """ Specify email addresses separated by semicolons like someone@contoso.com """ - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Attachments""" - sensitivity: Optional[str] = field( + sensitivity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sensitivity"}, ) """Sensitivity""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """The email addresses to use when replying""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Importance""" @@ -2034,12 +2631,17 @@ class BatchItemFailureResult: Definition: BatchItemFailureResult """ - message_id: Optional[str] = field( + message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageId"}, ) """The ID of the failed message.""" - error: Optional[str] = field(default=None, metadata={"wire_name": "Error"}) + error: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Error"}, + ) """The error message of the failure.""" @@ -2049,7 +2651,12 @@ class BatchResponseClientReceiveMessage: Definition: BatchResponse[ClientReceiveMessage] """ - value: Optional[List[ClientReceiveMessage]] = None + value: Optional[ + List[ClientReceiveMessage | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A list of the response objects""" @@ -2059,70 +2666,107 @@ class ClientReceiveMessage: Definition: ClientReceiveMessage """ - from_: Optional[str] = field(default=None, metadata={"wire_name": "From"}) + from_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "From"}, + ) """The mailbox owner and sender of the message""" - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "To"}, + ) """The recipients for the message""" - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """The Cc recipients for the message""" - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """The Bcc recipients for the message""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """The email addresses to use when replying""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """The subject of the message""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """The body of the message""" - importance: Optional[int] = field( + importance: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the message (0 - Low, 1 - Normal, 2 - High)""" - body_preview: Optional[str] = field( + body_preview: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BodyPreview"}, ) """The preview of the message""" - has_attachment: Optional[bool] = field( + has_attachment: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HasAttachment"}, ) """Indicates whether the message has attachments""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique identifier of the message""" - internet_message_id: Optional[str] = field( + internet_message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InternetMessageId"}, ) """The message ID in the format specified by RFC2822""" - conversation_id: Optional[str] = field( + conversation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ConversationId"}, ) """The Id of the conversation the email belongs to""" - date_time_received: Optional[str] = field( + date_time_received: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeReceived"}, ) """The date and time the message was received""" - is_read: Optional[bool] = field( + is_read: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsRead"}, ) """Indicates whether the message has been read""" - attachments: Optional[List[ClientReceiveFileAttachment]] = field( + attachments: Optional[ + List[ClientReceiveFileAttachment | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """The file attachments for the message""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Is Html?""" @@ -2134,34 +2778,39 @@ class GraphClientReceiveFileAttachment: Definition: GraphClientReceiveFileAttachment """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Attachment Id""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Attachment name""" - content_bytes: Optional[str] = field( + content_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentBytes"}, ) """Attachment content""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentType"}, ) """Attachment content type""" - size: Optional[int] = None + size: Optional[int] = dataclass_field(default=None, kw_only=True) """The size in bytes of the attachment""" - is_inline: Optional[bool] = field( + is_inline: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isInline"}, ) """Set to true if this is an inline attachment""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """The date and time when the attachment was last modified""" - content_id: Optional[str] = field( + content_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentId"}, ) """Content Id""" @@ -2173,36 +2822,57 @@ class ReplyMessage: Definition: ReplyMessage """ - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "To"}, + ) """Example: recipient1@domain.com; recipient2@domain.com""" - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """Example: recipient1@domain.com; recipient2@domain.com""" - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """Example: recipient1@domain.com; recipient2@domain.com""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Email subject (if empty, the original subject used).""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Content of the email.""" - reply_all: Optional[bool] = field( + reply_all: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyAll"}, ) """True to reply to all recipients. (default: False)""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """True to send the reply as HTML. (default: True)""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Pick an importance. (default: Low)""" - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Details of attachments to be sent along with the reply.""" @@ -2214,31 +2884,51 @@ class ReplyEmailInput: Definition: ReplyHtmlMessage """ - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "To"}, + ) """Example: recipient1@domain.com; recipient2@domain.com""" - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """Example: recipient1@domain.com; recipient2@domain.com""" - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """Example: recipient1@domain.com; recipient2@domain.com""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Email subject (if empty, the original subject used).""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Content of the email.""" - reply_all: Optional[bool] = field( + reply_all: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyAll"}, ) """True to reply to all recipients. (default: False)""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Pick an importance. (default: Low)""" - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Details of attachments to be sent along with the reply.""" @@ -2250,7 +2940,12 @@ class TriggerBatchResponseClientReceiveMessage: Definition: TriggerBatchResponse[ClientReceiveMessage] """ - value: Optional[List[ClientReceiveMessage]] = None + value: Optional[ + List[ClientReceiveMessage | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A list of the response objects""" @@ -2260,7 +2955,12 @@ class BatchResponseSensitivityLabel: Definition: BatchResponse[SensitivityLabel] """ - value: Optional[List[SensitivityLabel]] = None + value: Optional[ + List[SensitivityLabel | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A list of the response objects""" @@ -2270,20 +2970,27 @@ class SensitivityLabel: Definition: SensitivityLabel """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Gets or sets the identifier.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Gets or sets the display name.""" - applicable_to: Optional[str] = field( + applicable_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ApplicableTo"}, ) """Gets or sets the applicable to.""" - sub_labels: Optional[List[SensitivityLabel]] = field( + sub_labels: Optional[List[SensitivityLabel | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SubLabels"}, ) """Gets or sets sub labels.""" @@ -2295,7 +3002,12 @@ class TriggerBatchResponseReceiveMessageMetadata: Definition: TriggerBatchResponse[ReceiveMessageMetadata] """ - value: Optional[List[ReceiveMessageMetadata]] = None + value: Optional[ + List[ReceiveMessageMetadata | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A list of the response objects""" @@ -2305,43 +3017,69 @@ class ReceiveMessageMetadata: Definition: ReceiveMessageMetadata """ - from_: Optional[str] = field(default=None, metadata={"wire_name": "From"}) + from_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "From"}, + ) """The mailbox owner and sender of the message""" - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "To"}, + ) """The recipients for the message""" - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """The Cc recipients for the message""" - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """The Bcc recipients for the message""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """The email addresses to use when replying""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """The subject of the message""" - importance: Optional[int] = field( + importance: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the message (0 - Low, 1 - Normal, 2 - High)""" - has_attachment: Optional[bool] = field( + has_attachment: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HasAttachment"}, ) """Indicates whether the message has attachments""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique identifier of the message""" - date_time_received: Optional[str] = field( + date_time_received: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeReceived"}, ) """The date and time the message was received""" - is_read: Optional[bool] = field( + is_read: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsRead"}, ) """Indicates whether the message has been read""" @@ -2353,8 +3091,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -2363,25 +3111,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -2393,15 +3145,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -2413,15 +3167,13 @@ class OptionsEmailSubscription: Definition: OptionsEmailSubscription """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "NotificationUrl"}, ) """ Gets or sets callback url to flow engine. It is expected as part of request """ - message: Optional[MessageWithOptions] = field( - default=None, + message: MessageWithOptions | Mapping[str, Any] = dataclass_field( metadata={"wire_name": "Message"}, ) @@ -2432,49 +3184,61 @@ class MessageWithOptions: Definition: MessageWithOptions """ - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: str = dataclass_field(metadata={"wire_name": "To"}) """ Specify email addresses separated by semicolons like someone@contoso.com """ - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Subject of the email""" - options: Optional[str] = field( + options: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Options"}, ) """List of comma separated options for the email response""" - header_text: Optional[str] = field( + header_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HeaderText"}, ) """Header text for email body""" - selection_text: Optional[str] = field( + selection_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SelectionText"}, ) """Header text for users options selection""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Body of the email""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Importance""" - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Attachments""" - use_only_h_t_m_l_message: Optional[bool] = field( + use_only_h_t_m_l_message: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UseOnlyHTMLMessage"}, ) """Use only HTML message""" - hide_h_t_m_l_message: Optional[bool] = field( + hide_h_t_m_l_message: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HideHTMLMessage"}, ) """ @@ -2482,16 +3246,18 @@ class MessageWithOptions: displayed. Email clients which do not support actionable messages will display HTML message regardless of the parameter value. """ - show_h_t_m_l_confirmation_dialog: Optional[bool] = field( + show_h_t_m_l_confirmation_dialog: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowHTMLConfirmationDialog"}, ) """ If set to Yes then a dialog wil be shown to confirm selected option of HTML message """ - hide_microsoft_footer: Optional[bool] = field( + hide_microsoft_footer: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HideMicrosoftFooter"}, ) """If set to Yes, then the Microsoft footer is hidden in the email body.""" @@ -2503,13 +3269,15 @@ class ApprovalEmailResponse: Definition: ApprovalEmailResponse """ - selected_option: Optional[str] = field( + selected_option: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SelectedOption"}, ) """User response""" - user_email_address: Optional[str] = field( + user_email_address: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UserEmailAddress"}, ) """ @@ -2517,16 +3285,18 @@ class ApprovalEmailResponse: users and user ID for the members in Distribution Group or Mail Enabled Security Group. """ - user_tenant_id: Optional[str] = field( + user_tenant_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UserTenantId"}, ) """ User tenant ID. The value is the tenant id of the user for both individual users and the members in Distribution Group or Mail Enabled Security Group. """ - user_id: Optional[str] = field( + user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UserId"}, ) """ @@ -2541,15 +3311,13 @@ class ApprovalEmailSubscription: Definition: ApprovalEmailSubscription """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "NotificationUrl"}, ) """ Gets or sets callback url to flow engine. It is expected as part of request """ - message: Optional[ApprovalMessage] = field( - default=None, + message: ApprovalMessage | Mapping[str, Any] = dataclass_field( metadata={"wire_name": "Message"}, ) @@ -2560,49 +3328,61 @@ class ApprovalMessage: Definition: ApprovalMessage """ - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: str = dataclass_field(metadata={"wire_name": "To"}) """ Specify email addresses separated by semicolons like someone@contoso.com """ - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Subject""" - options: Optional[str] = field( + options: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Options"}, ) """User Options""" - header_text: Optional[str] = field( + header_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HeaderText"}, ) """Header text for email body""" - selection_text: Optional[str] = field( + selection_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SelectionText"}, ) """Header text for users options selection""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Body""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Importance""" - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Attachments""" - use_only_h_t_m_l_message: Optional[bool] = field( + use_only_h_t_m_l_message: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UseOnlyHTMLMessage"}, ) """Use only HTML message""" - hide_h_t_m_l_message: Optional[bool] = field( + hide_h_t_m_l_message: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HideHTMLMessage"}, ) """ @@ -2610,8 +3390,9 @@ class ApprovalMessage: displayed. Email clients which do not support actionable messages will display HTML message regardless of the parameter value. """ - show_h_t_m_l_confirmation_dialog: Optional[bool] = field( + show_h_t_m_l_confirmation_dialog: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowHTMLConfirmationDialog"}, ) """ @@ -2626,52 +3407,61 @@ class SharedMailboxClientSendMessage: Definition: SharedMailboxClientSendMessage """ - mailbox_address: Optional[str] = field( - default=None, + mailbox_address: str = dataclass_field( metadata={"wire_name": "MailboxAddress"}, ) """Specify email address of a shared mailbox like someone@contoso.com""" - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: str = dataclass_field(metadata={"wire_name": "To"}) """ Specify email addresses separated by semicolons like someone@contoso.com """ - subject: Optional[str] = field( - default=None, - metadata={"wire_name": "Subject"}, - ) + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) """Specify the subject of the mail""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: str = dataclass_field(metadata={"wire_name": "Body"}) """Specify the body of the mail""" - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """ Specify email addresses separated by semicolons like someone@contoso.com """ - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """ Specify email addresses separated by semicolons like someone@contoso.com """ - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Attachments""" - sensitivity: Optional[str] = field( + sensitivity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sensitivity"}, ) """Sensitivity""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """The email addresses to use when replying""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Importance""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Is Html?""" @@ -2683,47 +3473,55 @@ class SharedMailboxSendEmailInput: Definition: SharedMailboxClientSendHtmlMessage """ - mailbox_address: Optional[str] = field( - default=None, + mailbox_address: str = dataclass_field( metadata={"wire_name": "MailboxAddress"}, ) """Specify email address of a shared mailbox like someone@contoso.com""" - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: str = dataclass_field(metadata={"wire_name": "To"}) """ Specify email addresses separated by semicolons like someone@contoso.com """ - subject: Optional[str] = field( - default=None, - metadata={"wire_name": "Subject"}, - ) + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) """Specify the subject of the mail""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: str = dataclass_field(metadata={"wire_name": "Body"}) """Specify the body of the mail""" - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """ Specify email addresses separated by semicolons like someone@contoso.com """ - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """ Specify email addresses separated by semicolons like someone@contoso.com """ - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Attachments""" - sensitivity: Optional[str] = field( + sensitivity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sensitivity"}, ) """Sensitivity""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """The email addresses to use when replying""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Importance""" @@ -2735,7 +3533,12 @@ class SubscriptionPayloadOutlookReceiveMessage: Definition: SubscriptionPayload[OutlookReceiveMessage] """ - value: Optional[List[SubscriptionPayloadEntityOutlookReceiveMessage]] = None + value: Optional[ + List[SubscriptionPayloadEntityOutlookReceiveMessage | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -2745,28 +3548,33 @@ class SubscriptionPayloadEntityOutlookReceiveMessage: Definition: SubscriptionPayloadEntity[OutlookReceiveMessage] """ - sequence_number: Optional[int] = field( + sequence_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SequenceNumber"}, ) """Sequence number""" - change_type: Optional[str] = field( + change_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChangeType"}, ) """Change type""" - client_state: Optional[str] = field( + client_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClientState"}, ) """Client state""" - resource: Optional[str] = field( + resource: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Resource"}, ) """Resource""" - resource_data: Optional[OutlookReceiveMessage] = field( + resource_data: Optional[OutlookReceiveMessage | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceData"}, ) @@ -2777,54 +3585,75 @@ class OutlookReceiveAttachment: Definition: OutlookReceiveAttachment """ - type_: Optional[str] = field( + type_: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.type"}, ) """OData type""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Attachment Id""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Attachment name""" - content_bytes: Optional[str] = field( + content_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentBytes"}, ) """Attachment content""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentType"}, ) """Attachment content type""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """Attachment size in bytes""" - permission: Optional[str] = field( + permission: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Permission"}, ) """Permission associated with a reference attachment""" - provider_type: Optional[str] = field( + provider_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ProviderType"}, ) """Provider for the reference attachment""" - source_url: Optional[str] = field( + source_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SourceUrl"}, ) """Reference attachment source url""" - is_inline: Optional[bool] = field( + is_inline: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsInline"}, ) """Set to true if this is an inline attachment""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModifiedDateTime"}, ) """The date and time when the attachment was last modified""" - content_id: Optional[str] = field( + content_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentId"}, ) """Content Id""" @@ -2836,9 +3665,17 @@ class InternetMessageHeader: Definition: InternetMessageHeader """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Header name""" - value: Optional[str] = field(default=None, metadata={"wire_name": "Value"}) + value: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Value"}, + ) """Header value""" @@ -2848,7 +3685,12 @@ class SubscriptionPayloadSubscriptionEvent: Definition: SubscriptionPayload[SubscriptionEvent] """ - value: Optional[List[SubscriptionPayloadEntitySubscriptionEvent]] = None + value: Optional[ + List[SubscriptionPayloadEntitySubscriptionEvent | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -2858,28 +3700,33 @@ class SubscriptionPayloadEntitySubscriptionEvent: Definition: SubscriptionPayloadEntity[SubscriptionEvent] """ - sequence_number: Optional[int] = field( + sequence_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SequenceNumber"}, ) """Sequence number""" - change_type: Optional[str] = field( + change_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChangeType"}, ) """Change type""" - client_state: Optional[str] = field( + client_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClientState"}, ) """Client state""" - resource: Optional[str] = field( + resource: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Resource"}, ) """Resource""" - resource_data: Optional[SubscriptionEvent] = field( + resource_data: Optional[SubscriptionEvent | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceData"}, ) @@ -2890,7 +3737,11 @@ class SubscriptionEvent: Definition: SubscriptionEvent """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The Event's unique identifier""" @@ -2900,7 +3751,12 @@ class EntityListResponseTable: Definition: EntityListResponse[Table] """ - value: Optional[List[Table]] = None + value: Optional[ + List[Table | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -2910,15 +3766,21 @@ class Table: Definition: Table """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the table. The name is used at runtime.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the table.""" - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DynamicProperties"}, ) """Additional table properties provided by the connector to the clients.""" @@ -2930,7 +3792,12 @@ class EntityListResponseCalendarEventBackend: Definition: EntityListResponse[CalendarEventBackend] """ - value: Optional[List[CalendarEventBackend]] = None + value: Optional[ + List[CalendarEventBackend | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -2940,7 +3807,12 @@ class EntityListResponseCalendarEventClientReceiveStringEnums: Definition: EntityListResponse[CalendarEventClientReceiveStringEnums] """ - value: Optional[List[CalendarEventClientReceiveStringEnums]] = None + value: Optional[ + List[CalendarEventClientReceiveStringEnums | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -2950,84 +3822,99 @@ class CalendarEventClient: Definition: CalendarEventClient """ - subject: Optional[str] = field( - default=None, - metadata={"wire_name": "Subject"}, - ) + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) """Event subject""" - start: Optional[str] = field(default=None, metadata={"wire_name": "Start"}) + start: str = dataclass_field(metadata={"wire_name": "Start"}) """Start time of the event (example: '2016-11-01T14:30:00Z')""" - end: Optional[str] = field(default=None, metadata={"wire_name": "End"}) + end: str = dataclass_field(metadata={"wire_name": "End"}) """End time of the event (example: '2016-11-01T15:30:00Z')""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TimeZone"}, ) """Time zone of the event""" - required_attendees: Optional[str] = field( + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequiredAttendees"}, ) """Required attendees for the event separated by semicolons""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OptionalAttendees"}, ) """Optional attendees for the event separated by semicolons""" - resource_attendees: Optional[str] = field( + resource_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceAttendees"}, ) """Resource attendees for the event separated by semicolons""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Body of the message associated with the event""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Set to true if the body is Html""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location of the event""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the event: Low, Normal, or High""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAllDay"}, ) """Set to true if the event lasts all day""" - recurrence: Optional[str] = field( + recurrence: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Recurrence"}, ) """The recurrence pattern for the event""" - recurrence_end: Optional[str] = field( + recurrence_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecurrenceEnd"}, ) """End time of the recurrence""" - number_of_occurrences: Optional[int] = field( + number_of_occurrences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfOccurrences"}, ) """How many times to repeat the event""" - reminder: Optional[int] = field( + reminder: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reminder"}, ) """Time in minutes before event start to remind""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowAs"}, ) """Status to show during the event""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseRequested"}, ) """ @@ -3042,79 +3929,93 @@ class CalendarEventHtmlClient: Definition: CalendarEventHtmlClient """ - subject: Optional[str] = field( - default=None, - metadata={"wire_name": "Subject"}, - ) + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) """Event subject""" - start: Optional[str] = field(default=None, metadata={"wire_name": "Start"}) + start: str = dataclass_field(metadata={"wire_name": "Start"}) """Start time of the event (example: '2016-11-01T14:30:00Z')""" - end: Optional[str] = field(default=None, metadata={"wire_name": "End"}) + end: str = dataclass_field(metadata={"wire_name": "End"}) """End time of the event (example: '2016-11-01T15:30:00Z')""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TimeZone"}, ) """Time zone of the event""" - required_attendees: Optional[str] = field( + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequiredAttendees"}, ) """Required attendees for the event separated by semicolons""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OptionalAttendees"}, ) """Optional attendees for the event separated by semicolons""" - resource_attendees: Optional[str] = field( + resource_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceAttendees"}, ) """Resource attendees for the event separated by semicolons""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Body of the message associated with the event""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location of the event""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the event: Low, Normal, or High""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAllDay"}, ) """Set to true if the event lasts all day""" - recurrence: Optional[str] = field( + recurrence: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Recurrence"}, ) """The recurrence pattern for the event""" - recurrence_end: Optional[str] = field( + recurrence_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecurrenceEnd"}, ) """End time of the recurrence""" - number_of_occurrences: Optional[int] = field( + number_of_occurrences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfOccurrences"}, ) """How many times to repeat the event""" - reminder: Optional[int] = field( + reminder: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reminder"}, ) """Time in minutes before event start to remind""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowAs"}, ) """Status to show during the event""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseRequested"}, ) """ @@ -3129,92 +4030,100 @@ class GraphCalendarEventClient: Definition: GraphCalendarEventClient """ - subject: Optional[str] = None + subject: str """Event subject""" - start: Optional[str] = None + start: str """Start time of the event (example: '2017-08-29T04:00:00')""" - end: Optional[str] = None + end: str """End time of the event (example: '2017-08-29T05:00:00')""" - time_zone: Optional[str] = field( - default=None, - metadata={"wire_name": "timeZone"}, - ) - """Time zone of the event""" - required_attendees: Optional[str] = field( + time_zone: str = dataclass_field(metadata={"wire_name": "timeZone"}) + """Time zone of the event""" + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredAttendees"}, ) """Required attendees for the event separated by semicolons""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "optionalAttendees"}, ) """Optional attendees for the event separated by semicolons""" - resource_attendees: Optional[str] = field( + resource_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceAttendees"}, ) """Resource attendees for the event separated by semicolons""" - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """Body of the message associated with the event""" - categories: Optional[List[str]] = None + categories: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """The categories associated with the event""" - location: Optional[str] = None + location: Optional[str] = dataclass_field(default=None, kw_only=True) """Location of the event""" - importance: Optional[str] = None + importance: Optional[str] = dataclass_field(default=None, kw_only=True) """The importance of the event: low, normal, or high""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAllDay"}, ) """Set to true if the event lasts all day""" - recurrence: Optional[str] = None + recurrence: Optional[str] = dataclass_field(default=None, kw_only=True) """ The recurrence pattern for the event: none, daily, weekly, monthly or yearly """ - selected_days_of_week: Optional[List[str]] = field( + selected_days_of_week: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selectedDaysOfWeek"}, ) """Days of week for weekly recurrence""" - recurrence_end: Optional[str] = field( + recurrence_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recurrenceEnd"}, ) """End Date of the recurrence""" - number_of_occurences: Optional[int] = field( + number_of_occurences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "numberOfOccurences"}, ) """How many times to repeat the event""" - reminder_minutes_before_start: Optional[int] = field( + reminder_minutes_before_start: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reminderMinutesBeforeStart"}, ) """Time in minutes before event start to remind""" - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isReminderOn"}, ) """Set to true if an alert is set to remind the user of the event.""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showAs"}, ) """ Status to show during the event: free, tentative, busy, oof, workingElsewhere or unknown """ - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseRequested"}, ) """ Set to true if the sender would like a response when the event is accepted or declined """ - sensitivity: Optional[str] = None + sensitivity: Optional[str] = dataclass_field(default=None, kw_only=True) """The possible values are: normal, personal, private, confidential""" @@ -3224,7 +4133,12 @@ class CalendarEventListWithActionType: Definition: CalendarEventListWithActionType """ - value: Optional[List[CalendarEventClientWithActionType]] = None + value: Optional[ + List[CalendarEventClientWithActionType | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of calendar items""" @@ -3234,164 +4148,207 @@ class CalendarEventClientWithActionType: Definition: CalendarEventClientWithActionType """ - action_type: Optional[str] = field( + action_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ActionType"}, ) """Changed action type of the event - added, updated or deleted.""" - is_added: Optional[bool] = field( + is_added: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAdded"}, ) """ Flag that indicates whether the event was added since the last poll of the trigger. """ - is_updated: Optional[bool] = field( + is_updated: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsUpdated"}, ) """ Flag that indicates whether the event was updated since the last poll of the trigger. """ - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Event subject""" - start: Optional[str] = field(default=None, metadata={"wire_name": "Start"}) + start: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Start"}, + ) """Start time of the event (example: '2016-11-01T14:30:00Z')""" - end: Optional[str] = field(default=None, metadata={"wire_name": "End"}) + end: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "End"}, + ) """End time of the event (example: '2016-11-01T15:30:00Z')""" - show_as: Optional[int] = field( + show_as: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowAs"}, ) """ Status to show during the event (Unknown - -1, Free - 0, Tentative - 1, Busy - 2, Oof - 3, WorkingElsewhere - 4) """ - recurrence: Optional[int] = field( + recurrence: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Recurrence"}, ) """ The recurrence pattern for the event (None - 0, Daily - 1, Weekly - 2, Monthly - 3, Yearly - 4) """ - response_type: Optional[int] = field( + response_type: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseType"}, ) """ The response type of the event (None - 0, Organizer - 1, TentativelyAccepted - 2, Accepted - 3, Declined - 4, NotResponded - 5) """ - response_time: Optional[str] = field( + response_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseTime"}, ) """The response time of the event""" - i_cal_u_id: Optional[str] = field( + i_cal_u_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ICalUId"}, ) """ A unique identifier that is shared by all instances of an event across different calendars """ - importance: Optional[int] = field( + importance: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the event (0 - Low, 1 - Normal, 2 - High)""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The event's unique identifier""" - date_time_created: Optional[str] = field( + date_time_created: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeCreated"}, ) """The date and time that the event was created""" - date_time_last_modified: Optional[str] = field( + date_time_last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeLastModified"}, ) """The date and time that the event was last modified""" - organizer: Optional[str] = field( + organizer: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Organizer"}, ) """The organizer of the event""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TimeZone"}, ) """Time zone of the event""" - series_master_id: Optional[str] = field( + series_master_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SeriesMasterId"}, ) """Unique identifier for Series Master event type""" - categories: Optional[List[str]] = field( + categories: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Categories"}, ) """The categories associated with the event""" - web_link: Optional[str] = field( + web_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebLink"}, ) """The URL to open the event in Outlook Web App""" - required_attendees: Optional[str] = field( + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequiredAttendees"}, ) """Required attendees for the event separated by semicolons""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OptionalAttendees"}, ) """Optional attendees for the event separated by semicolons""" - resource_attendees: Optional[str] = field( + resource_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceAttendees"}, ) """Resource attendees for the event separated by semicolons""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Body of the message associated with the event""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Set to true if the body is Html""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location of the event""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAllDay"}, ) """Set to true if the event lasts all day""" - recurrence_end: Optional[str] = field( + recurrence_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecurrenceEnd"}, ) """End time of the recurrence""" - number_of_occurrences: Optional[int] = field( + number_of_occurrences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfOccurrences"}, ) """How many times to repeat the event""" - reminder: Optional[int] = field( + reminder: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reminder"}, ) """Time in minutes before event start to remind""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseRequested"}, ) """ @@ -3406,174 +4363,198 @@ class GraphCalendarEventClientWithActionType: Definition: GraphCalendarEventClientWithActionType """ - action_type: Optional[str] = field( + action_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ActionType"}, ) """Changed action type of the event - added, updated or deleted.""" - is_added: Optional[bool] = field( + is_added: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAdded"}, ) """ Flag that indicates whether the event was added since the last poll of the trigger. """ - is_updated: Optional[bool] = field( + is_updated: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsUpdated"}, ) """ Flag that indicates whether the event was updated since the last poll of the trigger. """ - subject: Optional[str] = None + subject: Optional[str] = dataclass_field(default=None, kw_only=True) """Event subject""" - start: Optional[str] = None + start: Optional[str] = dataclass_field(default=None, kw_only=True) """Start time of the event (example: '2017-08-29T04:00:00.0000000')""" - end: Optional[str] = None + end: Optional[str] = dataclass_field(default=None, kw_only=True) """End time of the event (example: '2017-08-29T05:00:00.0000000')""" - start_with_time_zone: Optional[str] = field( + start_with_time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startWithTimeZone"}, ) """ Start time of the event with time zone (example: '2017-08-29T04:00:00.0000000+00:00') """ - end_with_time_zone: Optional[str] = field( + end_with_time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endWithTimeZone"}, ) """ End time of the event with time zone (example: '2017-08-29T05:00:00.0000000+00:00') """ - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """Body of the message associated with the event""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isHtml"}, ) """Set to true if the body is Html""" - response_type: Optional[str] = field( + response_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseType"}, ) """ The response type of the event (none, organizer, tentativelyAccepted, accepted, declined or notResponded) """ - response_time: Optional[str] = field( + response_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseTime"}, ) """The response time of the event""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The event's unique identifier""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """The date and time that the event was created""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """The date and time that the event was last modified""" - organizer: Optional[str] = None + organizer: Optional[str] = dataclass_field(default=None, kw_only=True) """The organizer of the event""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "timeZone"}, ) """Time zone of the event""" - series_master_id: Optional[str] = field( + series_master_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "seriesMasterId"}, ) """Unique identifier for Series Master event type""" - i_cal_u_id: Optional[str] = field( + i_cal_u_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "iCalUId"}, ) """ A unique identifier for an event across calendars. This ID is different for each occurrence in a recurring series """ - categories: Optional[List[str]] = None + categories: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """The categories associated with the event""" - web_link: Optional[str] = field( + web_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webLink"}, ) """The URL to open the event in Outlook Web App""" - required_attendees: Optional[str] = field( + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredAttendees"}, ) """Required attendees for the event separated by semicolons""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "optionalAttendees"}, ) """Optional attendees for the event separated by semicolons""" - resource_attendees: Optional[str] = field( + resource_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceAttendees"}, ) """Resource attendees for the event separated by semicolons""" - location: Optional[str] = None + location: Optional[str] = dataclass_field(default=None, kw_only=True) """Location of the event""" - importance: Optional[str] = None + importance: Optional[str] = dataclass_field(default=None, kw_only=True) """The importance of the event: low, normal, or high""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAllDay"}, ) """Set to true if the event lasts all day""" - recurrence: Optional[str] = None + recurrence: Optional[str] = dataclass_field(default=None, kw_only=True) """ The recurrence pattern for the event: none, daily, weekly, monthly or yearly """ - recurrence_end: Optional[str] = field( + recurrence_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recurrenceEnd"}, ) """End Date of the recurrence""" - number_of_occurences: Optional[int] = field( + number_of_occurences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "numberOfOccurences"}, ) """How many times to repeat the event""" - reminder_minutes_before_start: Optional[int] = field( + reminder_minutes_before_start: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reminderMinutesBeforeStart"}, ) """Time in minutes before event start to remind""" - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isReminderOn"}, ) """Set to true if an alert is set to remind the user of the event.""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showAs"}, ) """ Status to show during the event: free, tentative, busy, oof, workingElsewhere or unknown """ - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseRequested"}, ) """ Set to true if the sender would like a response when the event is accepted or declined """ - sensitivity: Optional[str] = None + sensitivity: Optional[str] = dataclass_field(default=None, kw_only=True) """The possible values are: normal, personal, private, confidential""" @@ -3583,15 +4564,17 @@ class GraphContactFolder: Definition: GraphContactFolder """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the contacts folder""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The name of the contacts folder""" - parent_folder_id: Optional[str] = field( + parent_folder_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentFolderId"}, ) """The ID of the parent folder""" @@ -3603,7 +4586,12 @@ class DataSetsList: Definition: DataSetsList """ - value: Optional[List[DataSet]] = None + value: Optional[ + List[DataSet | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of datasets""" @@ -3613,14 +4601,24 @@ class DataSet: Definition: DataSet """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Dataset name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Dataset display name""" - query: Optional[List[PassThroughNativeQuery]] = None + query: Optional[ + List[PassThroughNativeQuery | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Pass-through Native Queries""" @@ -3630,10 +4628,15 @@ class Procedure: Definition: Procedure """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Procedure name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Procedure display name""" @@ -3645,8 +4648,9 @@ class PassThroughNativeQuery: Definition: PassThroughNativeQuery """ - language: Optional[str] = field( + language: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Language"}, ) """Query language""" @@ -3658,30 +4662,33 @@ class AutomaticRepliesSettingClient: Definition: AutomaticRepliesSettingClient """ - status: Optional[str] = None + status: str """Automatic reply setting status""" - external_audience: Optional[str] = field( - default=None, + external_audience: str = dataclass_field( metadata={"wire_name": "externalAudience"}, ) """The audience that will see the external reply message""" - scheduled_start_date_time: Optional[Dict[str, Any]] = field( + scheduled_start_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "scheduledStartDateTime"}, ) """Scheduled start time (example: '2017-08-29T04:00:00.0000000')""" - scheduled_end_date_time: Optional[Dict[str, Any]] = field( + scheduled_end_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "scheduledEndDateTime"}, ) """Scheduled end time (example: '2017-08-29T05:00:00.0000000')""" - internal_reply_message: Optional[str] = field( + internal_reply_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "internalReplyMessage"}, ) """Message for people within your organization""" - external_reply_message: Optional[str] = field( + external_reply_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "externalReplyMessage"}, ) """Message for people outside your organization""" @@ -3693,37 +4700,44 @@ class MailTipsClientReceive: Definition: MailTipsClientReceive """ - automatic_replies: Optional[MailTipsAutomaticReplies] = field( + automatic_replies: Optional[MailTipsAutomaticReplies | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "automaticReplies"}, ) - delivery_restricted: Optional[bool] = field( + delivery_restricted: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "deliveryRestricted"}, ) """Is delivery restricted""" - external_member_count: Optional[int] = field( + external_member_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "externalMemberCount"}, ) """Number of external members""" - is_moderated: Optional[bool] = field( + is_moderated: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isModerated"}, ) """Is moderated""" - mailbox_full: Optional[bool] = field( + mailbox_full: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mailboxFull"}, ) """Is mailbox full""" - max_message_size: Optional[int] = field( + max_message_size: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "maxMessageSize"}, ) """Maximum message size""" - total_member_count: Optional[int] = field( + total_member_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "totalMemberCount"}, ) """Total member count""" @@ -3735,7 +4749,7 @@ class MailTipsAutomaticReplies: Definition: MailTipsAutomaticReplies """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """Automatic replies message""" @@ -3745,7 +4759,7 @@ class UpdateEmailFlag: Definition: UpdateEmailFlag """ - flag: Optional[Dict[str, Any]] = None + flag: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Flag status""" @@ -3755,13 +4769,15 @@ class ResponseToEventInvite: Definition: ResponseToEventInvite """ - comment: Optional[str] = field( + comment: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comment"}, ) """Comment""" - send_response: Optional[bool] = field( + send_response: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SendResponse"}, ) """Send response to organizer?""" @@ -3773,13 +4789,13 @@ class DirectForwardMessage: Definition: DirectForwardMessage """ - comment: Optional[str] = field( + comment: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comment"}, ) """Comment""" - to_recipients: Optional[str] = field( - default=None, + to_recipients: str = dataclass_field( metadata={"wire_name": "ToRecipients"}, ) """Semicolon separated list of recipients to forward the message to""" @@ -3794,18 +4810,21 @@ class LocationConstraint: Definition: LocationConstraint """ - is_required: Optional[bool] = field( + is_required: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsRequired"}, ) """Should a meeting location be returned for the meeting?""" - suggest_location: Optional[bool] = field( + suggest_location: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SuggestLocation"}, ) """Should the response provide one or more meeting location suggestions?""" - locations: Optional[List[Dict[str, Any]]] = field( + locations: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Locations"}, ) """Locations""" @@ -3817,13 +4836,15 @@ class DateTimeTimeZone: Definition: DateTimeTimeZone """ - date_time: Optional[str] = field( + date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dateTime"}, ) """DateTime (example: '2017-08-29T04:00:00.0000000')""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "timeZone"}, ) """TimeZone (example: 'Pacific Standard Time')""" @@ -3835,8 +4856,8 @@ class EmailAddressV2: Definition: EmailAddress_V2 """ - name: Optional[str] = None - address: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + address: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -3845,19 +4866,21 @@ class PhysicalAddress: Definition: PhysicalAddress """ - street: Optional[str] = None + street: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's street address.""" - city: Optional[str] = None + city: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's city.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's state.""" - country_or_region: Optional[str] = field( + country_or_region: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "countryOrRegion"}, ) """The contact's country of region.""" - postal_code: Optional[str] = field( + postal_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "postalCode"}, ) """The contact's postal code.""" @@ -3869,145 +4892,164 @@ class Contact: Definition: Contact """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's unique identifier.""" - parent_folder_id: Optional[str] = field( + parent_folder_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentFolderId"}, ) """The ID of the contact's parent folder""" - birthday: Optional[str] = None + birthday: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's birthday""" - file_as: Optional[str] = field( + file_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fileAs"}, ) """The name the contact is filed under""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The contact's display name""" - given_name: Optional[str] = field( - default=None, - metadata={"wire_name": "givenName"}, - ) + given_name: str = dataclass_field(metadata={"wire_name": "givenName"}) """The contact's given name""" - initials: Optional[str] = None + initials: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's initials""" - middle_name: Optional[str] = field( + middle_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "middleName"}, ) """The contact's middle name""" - nick_name: Optional[str] = field( + nick_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nickName"}, ) """The contact's nickname""" - surname: Optional[str] = None + surname: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's surname""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's title""" - generation: Optional[str] = None + generation: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's generation""" - email_addresses: Optional[List[EmailAddressV2]] = field( + email_addresses: Optional[List[EmailAddressV2 | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "emailAddresses"}, ) """The contact's email addresses""" - im_addresses: Optional[List[str]] = field( + im_addresses: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "imAddresses"}, ) """The contact's instant messaging (IM) addresses""" - job_title: Optional[str] = field( + job_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobTitle"}, ) """The contact's job title""" - company_name: Optional[str] = field( + company_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "companyName"}, ) """The name of the contact's company""" - department: Optional[str] = None + department: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's department""" - office_location: Optional[str] = field( + office_location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "officeLocation"}, ) """The location of the contact's office""" - profession: Optional[str] = None + profession: Optional[str] = dataclass_field(default=None, kw_only=True) """The contact's profession""" - business_home_page: Optional[str] = field( + business_home_page: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "businessHomePage"}, ) """The business home page of the contact""" - assistant_name: Optional[str] = field( + assistant_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assistantName"}, ) """The name of the contact's assistant""" - manager: Optional[str] = None + manager: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the contact's manager""" - home_phones: Optional[List[str]] = field( - default=None, + home_phones: List[str] = dataclass_field( metadata={"wire_name": "homePhones"}, ) """The contact's home phone numbers""" - business_phones: Optional[List[str]] = field( + business_phones: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "businessPhones"}, ) """The contact's business phone numbers""" - mobile_phone: Optional[str] = field( + mobile_phone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mobilePhone"}, ) """The contact's mobile phone number""" - home_address: Optional[PhysicalAddress] = field( + home_address: Optional[PhysicalAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "homeAddress"}, ) - business_address: Optional[PhysicalAddress] = field( + business_address: Optional[PhysicalAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "businessAddress"}, ) - other_address: Optional[PhysicalAddress] = field( + other_address: Optional[PhysicalAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "otherAddress"}, ) - yomi_company_name: Optional[str] = field( + yomi_company_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "yomiCompanyName"}, ) """The phonetic Japanese company name of the contact""" - yomi_given_name: Optional[str] = field( + yomi_given_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "yomiGivenName"}, ) """The phonetic Japanese given name (first name) of the contact""" - yomi_surname: Optional[str] = field( + yomi_surname: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "yomiSurname"}, ) """The phonetic Japanese surname (last name) of the contact""" - categories: Optional[List[str]] = None + categories: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """The categories associated with the contact""" - change_key: Optional[str] = field( + change_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "changeKey"}, ) """Identifies the version of the event object""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """The time the contact was created""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """The time the contact was modified""" @@ -4019,41 +5061,47 @@ class SensitivityLabelMetadata: Definition: sensitivityLabelMetadata """ - sensitivity_label_id: Optional[str] = field( + sensitivity_label_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelId"}, ) """SensitivityLabel Id.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel name.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """SensitivityLabel displayName info""" - tooltip: Optional[str] = None + tooltip: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel details on tooltip.""" - priority: Optional[int] = None + priority: Optional[int] = dataclass_field(default=None, kw_only=True) """SensitivityLabel priority.""" - color: Optional[str] = None + color: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel color.""" - is_encrypted: Optional[bool] = field( + is_encrypted: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEncrypted"}, ) """ is SensitivityLabel Encrypted.""" - is_enabled: Optional[bool] = field( + is_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEnabled"}, ) """Whether SensitivityLabel is Enabled.""" - is_parent: Optional[bool] = field( + is_parent: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isParent"}, ) """Whether SensitivityLabel is Parent.""" - parent_sensitivity_label_id: Optional[str] = field( + parent_sensitivity_label_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentSensitivityLabelId"}, ) """Parent SensitivityLabel Id.""" @@ -4065,14 +5113,15 @@ class MCPQueryRequest: Definition: MCPQueryRequest """ - jsonrpc: Optional[str] = None - id: Optional[str] = None - method: Optional[str] = None - params: Optional[Dict[str, Any]] = None - result: Optional[Dict[str, Any]] = None - error: Optional[Dict[str, Any]] = None - callback_endpoint: Optional[str] = field( + jsonrpc: Optional[str] = dataclass_field(default=None, kw_only=True) + id: Optional[str] = dataclass_field(default=None, kw_only=True) + method: Optional[str] = dataclass_field(default=None, kw_only=True) + params: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + result: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + error: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + callback_endpoint: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "callbackEndpoint"}, ) @@ -4085,16 +5134,16 @@ class Office365Client(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -4105,8 +5154,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -4114,8 +5163,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -4127,7 +5176,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -4149,7 +5198,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -4181,49 +5230,88 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def get_outlook_category_names_async( + def list_outlook_category_names( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Outlook category names This operation gets Outlook category display names. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetOutlookCategoryNames`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Categories" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def draft_email_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def draft_email( self, - input: DraftEmailInput, + input: DraftEmailInput | Mapping[str, Any], + *, message_id: Optional[str] = None, draft_type: Optional[str] = None, comment: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4233,6 +5321,25 @@ async def draft_email_async( Draft an email message This operation drafts an email message. + + Swagger operation ID: `DraftEmail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Message Id. + draft_type: Draft Type. + comment: Draft Comment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Draft" query_params = [] @@ -4254,7 +5361,7 @@ async def draft_email_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4268,6 +5375,7 @@ async def draft_email_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4275,9 +5383,9 @@ async def draft_email_async( return json.loads(response.text) - async def update_draft_email_async( + def update_draft_email( self, - input: DraftEmailInput, + input: DraftEmailInput | Mapping[str, Any], message_id: str, *, timeout: Optional[float] = None, @@ -4289,6 +5397,23 @@ async def update_draft_email_async( Updates an email Draft message This operation updates an an email Draft message. + + Swagger operation ID: `UpdateDraftEmail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Message Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Draft" query_params = [] @@ -4299,7 +5424,7 @@ async def update_draft_email_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -4313,9 +5438,10 @@ async def update_draft_email_async( request_url, response.status, response.text, + response=response, ) - async def send_draft_email_async( + def send_draft_email( self, message_id: str, *, @@ -4328,13 +5454,28 @@ async def send_draft_email_async( Send a Draft message This operation sends a Draft message. + + Swagger operation ID: `SendDraftEmail`. + + Args: + message_id: Message Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/Draft/Send/{quote(str(message_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -4348,9 +5489,10 @@ async def send_draft_email_async( request_url, response.status, response.text, + response=response, ) - async def assign_category_async( + def assign_category( self, message_id: str, category: str, @@ -4364,6 +5506,22 @@ async def assign_category_async( Assigns an Outlook category This operation assigns an Outlook category to an email. + + Swagger operation ID: `AssignCategory`. + + Args: + message_id: Message Id. + category: Category. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/Mail/Category" query_params = [] @@ -4378,7 +5536,7 @@ async def assign_category_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -4392,9 +5550,10 @@ async def assign_category_async( request_url, response.status, response.text, + response=response, ) - async def assign_category_bulk_async( + def assign_category_bulk( self, input: AssignCategoryBulkInput, category_name: str, @@ -4408,13 +5567,29 @@ async def assign_category_bulk_async( Assign a category to multiple emails This operation assigns an Outlook category to multiple emails. + + Swagger operation ID: `AssignCategoryBulk`. + + Args: + input: The request body. + category_name: Category Name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/Mail/Category/Bulk/{quote(str(category_name), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4428,6 +5603,7 @@ async def assign_category_bulk_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4435,9 +5611,9 @@ async def assign_category_bulk_async( return json.loads(response.text) - async def send_mail_with_options_async( + def send_mail_with_options( self, - input: OptionsEmailSubscription, + input: OptionsEmailSubscription | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -4452,12 +5628,28 @@ async def send_mail_with_options_async( following link regarding the support of actionable messages in different mail clients: https://docs.microsoft.com/outlook/actionable-messages/#outlook-version-requirements-for-actionable-messages. + + Swagger operation ID: `SendMailWithOptions`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/mailwithoptions/$subscriptions" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4471,6 +5663,7 @@ async def send_mail_with_options_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4478,9 +5671,9 @@ async def send_mail_with_options_async( return json.loads(response.text) - async def send_approval_mail_async( + def send_approval_mail( self, - input: ApprovalEmailSubscription, + input: ApprovalEmailSubscription | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -4494,12 +5687,28 @@ async def send_approval_mail_async( the recipient. Please refer to the following link regarding the support of actionable messages in different mail clients: https://docs.microsoft.com/outlook/actionable-messages/#outlook-version-requirements-for-actionable-messages. + + Swagger operation ID: `SendApprovalMail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/approvalmail/$subscriptions" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4513,6 +5722,7 @@ async def send_approval_mail_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4520,7 +5730,7 @@ async def send_approval_mail_async( return json.loads(response.text) - async def update_my_contact_photo_async( + def update_my_contact_photo( self, input: bytes, folder: str, @@ -4536,6 +5746,23 @@ async def update_my_contact_photo_async( Updates the photo of the specified contact of the current user. The size of the photo must be less than 4 MB. + + Swagger operation ID: `UpdateMyContactPhoto`. + + Args: + input: The binary request body. + folder: Select a contacts folder. + id: Unique identifier of a contact to update photo. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4550,7 +5777,7 @@ async def update_my_contact_photo_async( f"/$value" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, @@ -4567,9 +5794,10 @@ async def update_my_contact_photo_async( request_url, response.status, response.text, + response=response, ) - async def http_request_async( + def http_request( self, input: bytes, *, @@ -4586,10 +5814,25 @@ async def http_request_async( messages, mailFolders, events, calendar, calendars, outlook, inferenceClassification. Learn more: https://docs.microsoft.com/en-us/graph/use-the-api. + + Swagger operation ID: `HttpRequest`. + + Args: + input: The binary request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/codeless/httprequest" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -4606,6 +5849,7 @@ async def http_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4613,11 +5857,11 @@ async def http_request_async( return json.loads(response.text) - async def mcp_emails_management_async( + def mcp_emails_management( self, - input: MCPQueryRequest, - session_id: Optional[str] = None, + input: MCPQueryRequest | Mapping[str, Any], *, + session_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4627,6 +5871,23 @@ async def mcp_emails_management_async( Email Management MCP Server (deprecated) This MCP server manages email messages from your Office 365 account + + Swagger operation ID: `mcp_EmailsManagement`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + session_id: sessionId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/mcp/EmailsManagement" query_params = [] @@ -4638,7 +5899,7 @@ async def mcp_emails_management_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4652,6 +5913,7 @@ async def mcp_emails_management_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4659,11 +5921,11 @@ async def mcp_emails_management_async( return json.loads(response.text) - async def mcp_meeting_management_async( + def mcp_meeting_management( self, - input: MCPQueryRequest, - session_id: Optional[str] = None, + input: MCPQueryRequest | Mapping[str, Any], *, + session_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4673,6 +5935,23 @@ async def mcp_meeting_management_async( Meeting Management MCP Server (deprecated) This MCP server manages events, calendars and meetings + + Swagger operation ID: `mcp_MeetingManagement`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + session_id: sessionId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/mcp/MeetingManagement" query_params = [] @@ -4684,7 +5963,7 @@ async def mcp_meeting_management_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4698,6 +5977,7 @@ async def mcp_meeting_management_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4705,11 +5985,11 @@ async def mcp_meeting_management_async( return json.loads(response.text) - async def mcp_contacts_management_async( + def mcp_contacts_management( self, - input: MCPQueryRequest, - session_id: Optional[str] = None, + input: MCPQueryRequest | Mapping[str, Any], *, + session_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4719,6 +5999,23 @@ async def mcp_contacts_management_async( Contact Management MCP Server This MCP server manages contacts + + Swagger operation ID: `mcp_ContactsManagement`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + session_id: sessionId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/mcp/ContactsManagement" query_params = [] @@ -4730,7 +6027,7 @@ async def mcp_contacts_management_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4744,6 +6041,7 @@ async def mcp_contacts_management_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4751,7 +6049,7 @@ async def mcp_contacts_management_async( return json.loads(response.text) - async def calendar_delete_item_async( + def calendar_delete_item( self, calendar: str, event: str, @@ -4765,6 +6063,22 @@ async def calendar_delete_item_async( Delete event This operation deletes an event in a calendar. + + Swagger operation ID: `CalendarDeleteItem_V2`. + + Args: + calendar: Select a calendar. + event: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4777,7 +6091,7 @@ async def calendar_delete_item_async( f"/{quote(quote(str(event), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -4791,9 +6105,10 @@ async def calendar_delete_item_async( request_url, response.status, response.text, + response=response, ) - async def calendar_get_item_async( + def calendar_get_item( self, table: str, id: str, @@ -4807,6 +6122,22 @@ async def calendar_get_item_async( Get event This operation gets a specific event from a calendar using Graph API. + + Swagger operation ID: `V3CalendarGetItem`. + + Args: + table: Select a calendar. + id: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4819,7 +6150,7 @@ async def calendar_get_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4833,6 +6164,7 @@ async def calendar_get_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4840,23 +6172,48 @@ async def calendar_get_item_async( return json.loads(response.text) - async def calendar_get_items_async( + def list_calendar_get_items( self, table: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get events This operation gets events from a calendar using Graph API. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `V4CalendarGetItems`. + + Args: + table: Select a calendar. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4890,40 +6247,79 @@ async def calendar_get_items_async( query_params.append(f"$skip={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def calendar_get_tables_async( + return ItemPaged(get_next, extract_data) + + def list_calendar_get_tables( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get calendars This operation lists available calendars. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `CalendarGetTables_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/codeless/v1.0/me/calendars" @@ -4934,31 +6330,52 @@ async def calendar_get_tables_async( query_params.append("orderBy=" + quote("name", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def calendar_patch_item_async( + def calendar_patch_item( self, - input: GraphCalendarEventClient, + input: GraphCalendarEventClient | Mapping[str, Any], table: str, id: str, *, @@ -4971,6 +6388,24 @@ async def calendar_patch_item_async( Update event This operation updates an event in a calendar using Graph API. + + Swagger operation ID: `V4CalendarPatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Select a calendar. + id: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4983,7 +6418,7 @@ async def calendar_patch_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -4997,6 +6432,7 @@ async def calendar_patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5004,9 +6440,9 @@ async def calendar_patch_item_async( return json.loads(response.text) - async def calendar_post_item_async( + def calendar_post_item( self, - input: GraphCalendarEventClient, + input: GraphCalendarEventClient | Mapping[str, Any], table: str, *, timeout: Optional[float] = None, @@ -5018,6 +6454,23 @@ async def calendar_post_item_async( Create event This operation creates a new event in a calendar. + + Swagger operation ID: `V4CalendarPostItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Select a calendar. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5029,7 +6482,7 @@ async def calendar_post_item_async( f"/items" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5043,6 +6496,7 @@ async def calendar_post_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5050,7 +6504,7 @@ async def calendar_post_item_async( return json.loads(response.text) - async def contact_delete_item_async( + def contact_delete_item( self, folder: str, id: str, @@ -5064,6 +6518,22 @@ async def contact_delete_item_async( Delete contact This operation deletes a contact from a contacts folder. + + Swagger operation ID: `ContactDeleteItem_V2`. + + Args: + folder: Select a contacts folder. + id: Unique identifier of contact to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5076,7 +6546,7 @@ async def contact_delete_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -5090,9 +6560,10 @@ async def contact_delete_item_async( request_url, response.status, response.text, + response=response, ) - async def contact_get_item_async( + def contact_get_item( self, folder: str, id: str, @@ -5106,6 +6577,22 @@ async def contact_get_item_async( Get contact This operation gets a specific contact from a contacts folder. + + Swagger operation ID: `ContactGetItem_V2`. + + Args: + folder: Select a contacts folder. + id: Unique identifier of a contact to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5118,7 +6605,7 @@ async def contact_get_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5132,6 +6619,7 @@ async def contact_get_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5139,26 +6627,48 @@ async def contact_get_item_async( return json.loads(response.text) - async def contact_get_items_async( + def list_contact_get_items( self, folder: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get contacts This operation gets contacts from a contacts folder. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ContactGetItems_V2`. + + Args: + folder: Unique identifier of the contacts folder to retrieve. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5192,11 +6702,18 @@ async def contact_get_items_async( query_params.append(f"$skip={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -5209,63 +6726,111 @@ async def contact_get_items_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def contact_get_tables_async( + return ItemPaged(get_next, extract_data) + + def list_contact_get_tables( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get contact folders This operation lists available contacts folders using Graph API + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ContactGetTablesV2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v2/datasets/contacts/tables" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def contact_patch_item_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def contact_patch_item( self, - input: Contact, + input: Contact | Mapping[str, Any], folder: str, id: str, *, @@ -5278,6 +6843,24 @@ async def contact_patch_item_async( Update contact This operation updates a contact in a contacts folder. + + Swagger operation ID: `ContactPatchItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + folder: Select a contacts folder. + id: Unique identifier of contact to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5290,7 +6873,7 @@ async def contact_patch_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -5304,6 +6887,7 @@ async def contact_patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5311,9 +6895,9 @@ async def contact_patch_item_async( return json.loads(response.text) - async def contact_post_item_async( + def contact_post_item( self, - input: Contact, + input: Contact | Mapping[str, Any], folder: str, *, timeout: Optional[float] = None, @@ -5325,6 +6909,23 @@ async def contact_post_item_async( Create contact This operation creates a new contact in a contacts folder. + + Swagger operation ID: `ContactPostItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + folder: Select a contacts folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5336,7 +6937,7 @@ async def contact_post_item_async( f"/contacts" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5350,6 +6951,7 @@ async def contact_post_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5357,11 +6959,11 @@ async def contact_post_item_async( return json.loads(response.text) - async def delete_email_async( + def delete_email( self, message_id: str, - mailbox_address: Optional[str] = None, *, + mailbox_address: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5371,6 +6973,22 @@ async def delete_email_async( Delete email This operation deletes an email by id. + + Swagger operation ID: `DeleteEmail_V2`. + + Args: + message_id: Id of the email to delete. + mailbox_address: Address of the shared mailbox to delete mail from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5385,7 +7003,7 @@ async def delete_email_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -5399,13 +7017,14 @@ async def delete_email_async( request_url, response.status, response.text, + response=response, ) - async def export_email_async( + def export_email( self, message_id: str, - mailbox_address: Optional[str] = None, *, + mailbox_address: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5415,6 +7034,22 @@ async def export_email_async( Export email Export the content of the email in the EML file format. + + Swagger operation ID: `ExportEmail_V2`. + + Args: + message_id: Id of the email to export. + mailbox_address: Address of the shared mailbox to export from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5434,7 +7069,7 @@ async def export_email_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5448,13 +7083,14 @@ async def export_email_async( request_url, response.status, response.text, + response=response, ) return response.content - async def find_meeting_times_async( + def find_meeting_times( self, - input: FindMeetingTimesInput, + input: FindMeetingTimesInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5466,12 +7102,28 @@ async def find_meeting_times_async( Find meeting time suggestions based on organizer, attendee availability, and time or location constraints + + Swagger operation ID: `FindMeetingTimes_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/codeless/beta/me/findMeetingTimes" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5485,6 +7137,7 @@ async def find_meeting_times_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5492,12 +7145,12 @@ async def find_meeting_times_async( return json.loads(response.text) - async def flag_async( + def flag( self, - input: UpdateEmailFlag, + input: UpdateEmailFlag | Mapping[str, Any], message_id: str, - mailbox_address: Optional[str] = None, *, + mailbox_address: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5507,6 +7160,24 @@ async def flag_async( Flag email This operation updates an email flag. + + Swagger operation ID: `Flag_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Id of the email to be flagged. + mailbox_address: Address of the shared mailbox to update mail. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5526,7 +7197,7 @@ async def flag_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -5540,16 +7211,17 @@ async def flag_async( request_url, response.status, response.text, + response=response, ) - async def forward_email_async( + def forward_email( self, - input: DirectForwardMessage, + input: DirectForwardMessage | Mapping[str, Any], message_id: str, + *, mailbox_address: Optional[str] = None, extract_sensitivity_label: Optional[bool] = None, fetch_sensitivity_label_metadata: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5559,6 +7231,30 @@ async def forward_email_async( Forward an email Forward an email. + + Swagger operation ID: `ForwardEmail_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Id of the message to forward. (You can use 'Message Id' + from trigger or 'Get Emails' action output). + mailbox_address: Address of the shared mailbox to forward mail + from. + extract_sensitivity_label: Select if you want to extract + Sensitivity label ( false, true). + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5588,7 +7284,7 @@ async def forward_email_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5602,16 +7298,17 @@ async def forward_email_async( request_url, response.status, response.text, + response=response, ) - async def get_attachment_async( + def get_attachment( self, message_id: str, attachment_id: str, + *, mailbox_address: Optional[str] = None, extract_sensitivity_label: Optional[bool] = None, fetch_sensitivity_label_metadata: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5621,6 +7318,28 @@ async def get_attachment_async( Get Attachment This operation gets an email attachment by id. + + Swagger operation ID: `GetAttachment_V2`. + + Args: + message_id: Id of the email. + attachment_id: Id of the attachment to download. + mailbox_address: Address of the shared mailbox to retrieve + attachment from. + extract_sensitivity_label: Select if you want to extract + Sensitivity label ( false, true). + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5651,7 +7370,7 @@ async def get_attachment_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5665,6 +7384,7 @@ async def get_attachment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5672,15 +7392,15 @@ async def get_attachment_async( return json.loads(response.text) - async def get_email_async( + def get_email( self, message_id: str, + *, mailbox_address: Optional[str] = None, include_attachments: Optional[bool] = None, internet_message_id: Optional[str] = None, extract_sensitivity_label: Optional[bool] = None, fetch_sensitivity_label_metadata: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5690,6 +7410,30 @@ async def get_email_async( Get email This operation gets an email by id. + + Swagger operation ID: `GetEmailV2`. + + Args: + message_id: Id of the email. + mailbox_address: Address of the shared mailbox to retrieve mail + from. + include_attachments: If set to true, attachments content will also + be retrieved along with the email. + internet_message_id: Internet Message Id. + extract_sensitivity_label: Select if you want to extract + Sensitivity label ( false, true). + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5724,7 +7468,7 @@ async def get_email_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5738,6 +7482,7 @@ async def get_email_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5745,8 +7490,9 @@ async def get_email_async( return json.loads(response.text) - async def get_emails_async( + def list_emails( self, + *, folder_path: Optional[str] = None, to: Optional[str] = None, cc: Optional[str] = None, @@ -5760,12 +7506,11 @@ async def get_emails_async( include_attachments: Optional[bool] = None, search_query: Optional[str] = None, top: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get emails @@ -5774,6 +7519,48 @@ async def get_emails_async( Importance, Fetch Only With Attachments, Subject Filter, is performed using first 250 items in a given mail folder. To avoid that limitation you can use 'Search Query' field. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetEmailsV3`. + + Args: + folder_path: Mail folder to retrieve emails from (default: + 'Inbox'). + to: Recipient email addresses separated by semicolons (If any + match, the trigger will run). + cc: CC recipient email addresses separated by semicolons (If any + match, the trigger will run). + to_or_cc: To or CC recipient email addresses separated by + semicolons (If any match, the trigger will run). + from_: Sender email addresses separated by semicolons (If any + match, the trigger will run). + importance: Importance of the email (Any, High, Normal, Low). + fetch_only_with_attachment: If set to true, only emails with an + attachment will be retrieved. Emails without any attachments + will be skipped. If set to false, all emails will be retrieved. + subject_filter: String to look for in the subject line. + fetch_only_unread: Retrieve only unread emails?. + mailbox_address: Address of the shared mailbox to retrieve mails + from. + include_attachments: If set to true, attachments content will also + be retrieved along with the email. + search_query: Search query to filter emails. How to use '$search' + parameter please refer to: + https://docs.microsoft.com/graph/query-parameters#search-parameter. + top: Number of emails to retrieve (default: 10, max: 1000). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v3/Mail" query_params = [] @@ -5845,49 +7632,100 @@ async def get_emails_async( query_params.append(f"top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_events_calendar_view_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_events_calendar_view( self, calendar_id: str, start_date_time_utc: str, end_date_time_utc: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, search: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get calendar view of events This operation gets all events (including instances of recurrences) in a calendar using Graph API. Recurrence property is null in this case. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetEventsCalendarViewV3`. + + Args: + calendar_id: Select a calendar. + start_date_time_utc: Start time in UTC (example: + '2017-01-01T08:00:00'). + end_date_time_utc: End time in UTC (example: + '2017-02-01T08:00:00'). + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + search: Search text for matching event body and subject. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5933,145 +7771,285 @@ async def get_events_calendar_view_async( query_params.append(f"search={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def get_mail_tips_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_mail_tips( self, - input: GetMailTipsInput, + input: GetMailTipsInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get mail tips for a mailbox Get mail tips for a mailbox such as automatic replies / OOF message or if the mailbox is full. This is not available in GccHigh and Mooncake. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMailTips_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/codeless/v1.0/me/getMailTips" ) + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def get_room_lists_async( + return ItemPaged(get_next, extract_data) + + def list_room_lists( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get room lists Get all the room lists defined in the user's tenant + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetRoomLists_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/codeless/beta/me/findRoomLists" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - async def get_rooms_async( + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_rooms( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get rooms Get all the meeting rooms defined in the user's tenant + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetRooms_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/codeless/beta/me/findRooms" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_rooms_in_room_list_async( + def list_get_rooms_in_room( self, room_list: str, *, @@ -6079,11 +8057,30 @@ async def get_rooms_in_room_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get rooms in room list Get the meeting rooms in a specific room list + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetRoomsInRoomList_V2`. + + Args: + room_list: Room list to find rooms in. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6092,34 +8089,55 @@ async def get_rooms_in_room_list_async( f"/me" f"/findRooms(RoomList='{quote(str(room_list), safe='')}')" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def mark_as_read_async( + def mark_as_read( self, - input: MarkAsReadInput, + input: MarkAsReadInput | Mapping[str, Any], message_id: str, - mailbox_address: Optional[str] = None, *, + mailbox_address: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -6129,6 +8147,24 @@ async def mark_as_read_async( Mark as read or unread This operation marks an email as read/unread. + + Swagger operation ID: `MarkAsRead_V3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Id of the email to be marked. + mailbox_address: Address of the shared mailbox to update mail. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6149,7 +8185,7 @@ async def mark_as_read_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -6163,14 +8199,15 @@ async def mark_as_read_async( request_url, response.status, response.text, + response=response, ) - async def move_async( + def move( self, message_id: str, folder_path: str, - mailbox_address: Optional[str] = None, *, + mailbox_address: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -6181,6 +8218,23 @@ async def move_async( This operation moves an email to the specified folder within the same mailbox. + + Swagger operation ID: `MoveV2`. + + Args: + message_id: Id of the email to be moved. + folder_path: Mail folder to move the email to. + mailbox_address: Address of the shared mailbox to move mail from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6199,7 +8253,7 @@ async def move_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -6213,6 +8267,7 @@ async def move_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6220,12 +8275,12 @@ async def move_async( return json.loads(response.text) - async def reply_to_async( + def reply_to( self, - input: ReplyEmailInput, + input: ReplyEmailInput | Mapping[str, Any], message_id: str, - mailbox_address: Optional[str] = None, *, + mailbox_address: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -6235,6 +8290,24 @@ async def reply_to_async( Reply to email This operation replies to an email. + + Swagger operation ID: `ReplyToV3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Id of the email to reply to. + mailbox_address: Address of the shared mailbox to reply from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6249,7 +8322,7 @@ async def reply_to_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6263,11 +8336,12 @@ async def reply_to_async( request_url, response.status, response.text, + response=response, ) - async def respond_to_event_async( + def respond_to_event( self, - input: ResponseToEventInvite, + input: ResponseToEventInvite | Mapping[str, Any], event_id: str, response: str, *, @@ -6280,6 +8354,24 @@ async def respond_to_event_async( Respond to an event invite Respond to an event invite. + + Swagger operation ID: `RespondToEvent_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + event_id: Id of the event to respond to. + response: Response for the event invite. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6291,7 +8383,7 @@ async def respond_to_event_async( f"/{quote(str(response), safe='')}" ) - http_response = await self.http_client.send_async( + http_response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6305,11 +8397,12 @@ async def respond_to_event_async( request_url, http_response.status, http_response.text, + response=http_response, ) - async def send_email_async( + def send_email( self, - input: SendEmailInput, + input: SendEmailInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6320,10 +8413,26 @@ async def send_email_async( Send an email This operation sends an email message. + + Swagger operation ID: `SendEmailV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/Mail" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6337,11 +8446,12 @@ async def send_email_async( request_url, response.status, response.text, + response=response, ) - async def set_automatic_replies_setting_async( + def set_automatic_replies_setting( self, - input: SetAutomaticRepliesSettingInput, + input: SetAutomaticRepliesSettingInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6352,12 +8462,28 @@ async def set_automatic_replies_setting_async( Set up automatic replies Set the automatic replies setting for your mailbox. + + Swagger operation ID: `SetAutomaticRepliesSetting_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/codeless/v1.0/me/mailboxSettings" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -6371,6 +8497,7 @@ async def set_automatic_replies_setting_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6378,9 +8505,9 @@ async def set_automatic_replies_setting_async( return json.loads(response.text) - async def shared_mailbox_send_email_async( + def shared_mailbox_send_email( self, - input: SharedMailboxSendEmailInput, + input: SharedMailboxSendEmailInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6393,10 +8520,26 @@ async def shared_mailbox_send_email_async( This operation sends an email from a shared mailbox. Your account should have permission to access the mailbox for this operation to succeed. + + Swagger operation ID: `SharedMailboxSendEmailV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/SharedMailbox/Mail" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6410,6 +8553,7 @@ async def shared_mailbox_send_email_async( request_url, response.status, response.text, + response=response, ) diff --git a/src/azure/connectors/office365groups.py b/src/azure/connectors/office365groups.py index fced862..c5cdab3 100644 --- a/src/azure/connectors/office365groups.py +++ b/src/azure/connectors/office365groups.py @@ -5,21 +5,37 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "Office365groupsClient", + "CreateCalendarEventResponse", + "ListGroupMembersResponse", + "ListGroupsResponse", + "ListOwnedGroupsResponse", + "ObjectWithoutType", + "OnGroupMemberAddedOrRemovedResponse", + "OnNewEventResponse", + "SensitivityLabelMetadata", + "UpdateCalendarEventHTMLRequest", + "UpdateCalendarEventRequest", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,20 +45,22 @@ class ListGroupMembersResponse: Response for List group members """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The OData context.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """ Only used in Power Apps Canvas to genereate the `$skipToken` for pagination. Power Automate and Logic Apps must use the pagination setting. """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" @@ -55,20 +73,22 @@ class ListGroupsResponse: Response for List groups """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The OData context.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """ Only used in Power Apps Canvas to genereate the `$skipToken` for pagination. Power Automate and Logic Apps must use the pagination setting. """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" @@ -78,44 +98,49 @@ class CreateCalendarEventResponse: Response for Update a group event """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique id of the event.""" - reminder_minutes_before_start: Optional[int] = field( + reminder_minutes_before_start: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reminderMinutesBeforeStart"}, ) """Time in minutes before event starts to remind.""" - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isReminderOn"}, ) """Set to true if the event has a reminder.""" - subject: Optional[str] = None + subject: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of the event.""" - importance: Optional[str] = None + importance: Optional[str] = dataclass_field(default=None, kw_only=True) """The importance of the event: Low, Normal, or High.""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAllDay"}, ) """True if the event is an all day event.""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseRequested"}, ) """True if a response was requested for the event.""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showAs"}, ) """Status to show during the event.""" - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """body""" - start: Optional[Dict[str, Any]] = None + start: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """start""" - end: Optional[Dict[str, Any]] = None + end: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """end""" - location: Optional[Dict[str, Any]] = None + location: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """location""" @@ -128,7 +153,7 @@ class ObjectWithoutType: Response for Send an HTTP request """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -141,12 +166,13 @@ class ListOwnedGroupsResponse: Response for List groups that I own and belong to """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The OData context.""" - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" @@ -156,41 +182,47 @@ class SensitivityLabelMetadata: Definition: SensitivityLabelMetadata """ - sensitivity_label_id: Optional[str] = field( + sensitivity_label_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelId"}, ) """SensitivityLabel Id.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel name.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """SensitivityLabel displayName info""" - tooltip: Optional[str] = None + tooltip: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel details on tooltip.""" - priority: Optional[int] = None + priority: Optional[int] = dataclass_field(default=None, kw_only=True) """SensitivityLabel priority.""" - color: Optional[str] = None + color: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel color.""" - is_encrypted: Optional[bool] = field( + is_encrypted: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEncrypted"}, ) """ is SensitivityLabel Encrypted.""" - is_enabled: Optional[bool] = field( + is_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEnabled"}, ) """Whether SensitivityLabel is Enabled.""" - is_parent: Optional[bool] = field( + is_parent: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isParent"}, ) """Whether SensitivityLabel is Parent.""" - parent_sensitivity_label_id: Optional[str] = field( + parent_sensitivity_label_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentSensitivityLabelId"}, ) """Parent SensitivityLabel Id.""" @@ -202,36 +234,41 @@ class UpdateCalendarEventRequest: Definition: UpdateCalendarEvent_Request """ - subject: Optional[str] = None + subject: str """Title of the event.""" - start: Optional[Dict[str, Any]] = None - end: Optional[Dict[str, Any]] = None - body: Optional[Dict[str, Any]] = None - location: Optional[Dict[str, Any]] = None - importance: Optional[str] = None + start: Dict[str, Any] + end: Dict[str, Any] + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + location: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + importance: Optional[str] = dataclass_field(default=None, kw_only=True) """The importance of the event: Low, Normal, or High.""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAllDay"}, ) """Set to true if the event lasts all day.""" - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isReminderOn"}, ) """Set to true if the event has a reminder.""" - reminder_minutes_before_start: Optional[int] = field( + reminder_minutes_before_start: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reminderMinutesBeforeStart"}, ) """Time in minutes before event start to remind.""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showAs"}, ) """Status to show during the event.""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseRequested"}, ) """ @@ -246,36 +283,41 @@ class UpdateCalendarEventHTMLRequest: Definition: UpdateCalendarEvent_HTMLRequest """ - subject: Optional[str] = None + subject: str """Title of the event.""" - start: Optional[Dict[str, Any]] = None - end: Optional[Dict[str, Any]] = None - body: Optional[Dict[str, Any]] = None - location: Optional[Dict[str, Any]] = None - importance: Optional[str] = None + start: Dict[str, Any] + end: Dict[str, Any] + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + location: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + importance: Optional[str] = dataclass_field(default=None, kw_only=True) """The importance of the event: Low, Normal, or High.""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAllDay"}, ) """Set to true if the event lasts all day.""" - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isReminderOn"}, ) """Set to true if the event has a reminder.""" - reminder_minutes_before_start: Optional[int] = field( + reminder_minutes_before_start: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reminderMinutesBeforeStart"}, ) """Time in minutes before event start to remind.""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showAs"}, ) """Status to show during the event.""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseRequested"}, ) """ @@ -292,16 +334,16 @@ class Office365groupsClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -312,8 +354,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -321,8 +363,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -334,7 +376,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -356,7 +398,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -388,16 +430,16 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def list_group_members_async( + def list_group_members( self, group_id: str, - top: Optional[int] = None, *, + top: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List group members @@ -407,8 +449,26 @@ async def list_group_members_async( values please turn on Settings->Pagination feature and provide Threshold limit. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListGroupMembers`. + + Args: + group_id: Pick a group from the drop down or enter group id. + top: Number of group members to retrieve (from 1 to 999, default is + 100). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -422,11 +482,18 @@ async def list_group_members_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -439,23 +506,32 @@ async def list_group_members_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def add_member_to_group_async( + return ItemPaged(get_next, extract_data) + + def add_member_to_group( self, group_id: str, user_upn: str, @@ -469,6 +545,22 @@ async def add_member_to_group_async( Add member to group This operation is used to add a member to an O365 group, using a UPN. + + Swagger operation ID: `AddMemberToGroup`. + + Args: + group_id: Pick a group from the drop down or enter group id. + user_upn: The user principal name (UPN) of the user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -482,7 +574,7 @@ async def add_member_to_group_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -496,28 +588,53 @@ async def add_member_to_group_async( request_url, response.status, response.text, + response=response, ) - async def list_groups_async( + def list_groups( self, + *, extract_sensitivity_label: Optional[bool] = None, fetch_sensitivity_label_metadata: Optional[bool] = None, filter: Optional[str] = None, top: Optional[int] = None, skiptoken: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List groups This operation returns a list of all groups in the organization. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListGroups`. + + Args: + extract_sensitivity_label: A boolean whether to extract sensitivity + label Id for associated artefact. + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + filter: Enter an OData style filter expression to limit which rows + are listed. + top: Sets the page size of results. + skiptoken: Token that references the next page of results and is + returned in the @odata.nextLink property in the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/groups" query_params = [] @@ -548,11 +665,18 @@ async def list_groups_async( query_params.append(f"$skiptoken={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -565,25 +689,34 @@ async def list_groups_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def update_calendar_event_async( + return ItemPaged(get_next, extract_data) + + def update_calendar_event( self, - input: UpdateCalendarEventHTMLRequest, + input: UpdateCalendarEventHTMLRequest | Mapping[str, Any], group_id: str, event: str, *, @@ -596,6 +729,24 @@ async def update_calendar_event_async( Update a group event This operation is used to update a new event in a group calendar. + + Swagger operation ID: `UpdateCalendarEvent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Pick a group from the drop down or enter group id. + event: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -606,7 +757,7 @@ async def update_calendar_event_async( f"/{quote(quote(str(event), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -620,6 +771,7 @@ async def update_calendar_event_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -627,7 +779,7 @@ async def update_calendar_event_async( return json.loads(response.text) - async def remove_member_from_group_async( + def remove_member_from_group( self, group_id: str, user_upn: str, @@ -642,6 +794,22 @@ async def remove_member_from_group_async( This operation is used to remove a member from an O365 group, using a UPN. + + Swagger operation ID: `RemoveMemberFromGroup`. + + Args: + group_id: Pick a group from the drop down or enter group id. + user_upn: The user principal name (UPN) of the user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -660,7 +828,7 @@ async def remove_member_from_group_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -674,33 +842,56 @@ async def remove_member_from_group_async( request_url, response.status, response.text, + response=response, ) - async def list_deleted_groups_async( + def list_deleted_groups( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List deleted groups Lists deleted groups that can be restored. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListDeletedGroups`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/directory/deletedItems/microsoft.graph.group" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -713,23 +904,32 @@ async def list_deleted_groups_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def restore_deleted_group_async( + def restore_deleted_group( self, group_id: str, *, @@ -742,6 +942,21 @@ async def restore_deleted_group_async( Restore a deleted group Restore a recently deleted group + + Swagger operation ID: `RestoreDeletedGroup`. + + Args: + group_id: Pick a group from the drop down or enter group id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -752,7 +967,7 @@ async def restore_deleted_group_async( f"/restore" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -766,33 +981,56 @@ async def restore_deleted_group_async( request_url, response.status, response.text, + response=response, ) - async def list_deleted_groups_by_owner_async( + def list_deleted_groups_by_owner( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List deleted groups by owner List deleted groups that can be restored by owner - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListDeletedGroupsByOwner`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/directory/deletedItems/getUserOwnedObjects" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "POST", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -805,23 +1043,32 @@ async def list_deleted_groups_by_owner_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def calendar_delete_item_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def calendar_delete_item( self, group_id: str, event: str, @@ -835,6 +1082,22 @@ async def calendar_delete_item_async( Delete event This operation deletes an event in a calendar. + + Swagger operation ID: `CalendarDeleteItem_V2`. + + Args: + group_id: Pick a group from the drop down or enter group id. + event: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -845,7 +1108,7 @@ async def calendar_delete_item_async( f"/{quote(quote(str(event), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -859,11 +1122,12 @@ async def calendar_delete_item_async( request_url, response.status, response.text, + response=response, ) - async def create_calendar_event_async( + def create_calendar_event( self, - input: UpdateCalendarEventHTMLRequest, + input: UpdateCalendarEventHTMLRequest | Mapping[str, Any], group_id: str, *, timeout: Optional[float] = None, @@ -875,13 +1139,30 @@ async def create_calendar_event_async( Create a group event This operation is used to create a new event in a group calendar. + + Swagger operation ID: `CreateCalendarEventV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Pick a group from the drop down or enter group id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v2/v1.0/groups/{quote(str(group_id), safe='')}/events" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -895,6 +1176,7 @@ async def create_calendar_event_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -902,7 +1184,7 @@ async def create_calendar_event_async( return json.loads(response.text) - async def http_request_async( + def http_request( self, input: bytes, *, @@ -917,10 +1199,25 @@ async def http_request_async( Construct a Microsoft Graph REST API request to invoke. There is one segment that is supported: /groups. Learn more: https://docs.microsoft.com/en-us/graph/use-the-api. + + Swagger operation ID: `HttpRequestV2`. + + Args: + input: The binary request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/httprequest" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -937,6 +1234,7 @@ async def http_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -944,20 +1242,42 @@ async def http_request_async( return json.loads(response.text) - async def list_owned_groups_async( + def list_owned_groups( self, + *, extract_sensitivity_label: Optional[bool] = None, fetch_sensitivity_label_metadata: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List groups that I own and belong to This operation returns a list of all groups that you own and belong to. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListOwnedGroups_V3`. + + Args: + extract_sensitivity_label: A boolean whether to extract sensitivity + label Id for associated artefact. + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -976,27 +1296,48 @@ async def list_owned_groups_async( query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/office365groupsmail.py b/src/azure/connectors/office365groupsmail.py index d07ec91..cb999d8 100644 --- a/src/azure/connectors/office365groupsmail.py +++ b/src/azure/connectors/office365groupsmail.py @@ -5,21 +5,52 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "Office365groupsmailClient", + "Attachment", + "ClientSendAttachment", + "Conversation", + "ConversationThread", + "ConversationThreadTriggerResponse", + "ConversationTriggerResponse", + "CreateConversationBody", + "CreateConversationResponse", + "EmailAddress", + "ForwardPostBody", + "GetAttachmentsResponse", + "GetUsersGraphAction", + "ItemBody", + "ListConversationThreadsResponse", + "ListConversationsResponse", + "ListGroupThreadsResponse", + "ListGroupsResponse", + "ListThreadPostsResponse", + "NewConversationThreadResponse", + "NewPostBody", + "ObjectWithoutType", + "OnNewEmailInGroupResponse", + "Post", + "PostTriggerResponse", + "ReplyConversationThreadBody", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,12 +60,18 @@ class ListConversationsResponse: Response for List the conversations of a group """ - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """Link to get next page of results""" - value: Optional[List[Conversation]] = None + value: Optional[ + List[Conversation | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -43,19 +80,21 @@ class CreateConversationResponse: Response for Create a new conversation in a group """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The @odata.context link.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """New Conversation ID.""" - threads_odata_context: Optional[str] = field( + threads_odata_context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "threads@odata.context"}, ) """The threads@odata.context link.""" - threads: Optional[List[Dict[str, Any]]] = None + threads: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Created conversation thread.""" @@ -65,36 +104,44 @@ class Conversation: Response for Get a group conversation """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The conversations's unique identifier.""" - topic: Optional[str] = None + topic: Optional[str] = dataclass_field(default=None, kw_only=True) """The topic of the conversation.""" - has_attachments: Optional[bool] = field( + has_attachments: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasAttachments"}, ) """ Indicates whether any of the posts within this Conversation has at least one attachment. """ - last_delivered_date_time: Optional[str] = field( + last_delivered_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastDeliveredDateTime"}, ) """ The Timestamp type represents date and time information using ISO 8601 format and is always in UTC time. """ - unique_senders: Optional[List[str]] = field( + unique_senders: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "uniqueSenders"}, ) """All the users that sent a message to this Conversation.""" - preview: Optional[str] = None + preview: Optional[str] = dataclass_field(default=None, kw_only=True) """ A short summary from the body of the latest post in this Conversation. """ - threads: Optional[List[ConversationThread]] = None + threads: Optional[ + List[ConversationThread | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -103,17 +150,24 @@ class ListConversationThreadsResponse: Response for List the conversation threads of a conversation """ - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """Link to get next page of results""" - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The Odata.context link.""" - value: Optional[List[ConversationThread]] = None + value: Optional[ + List[ConversationThread | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -122,12 +176,13 @@ class NewConversationThreadResponse: Response for Create a conversation thread """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The @odata.context link.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """New conversation thread ID.""" @@ -137,12 +192,18 @@ class ListGroupThreadsResponse: Response for List the threads of a group """ - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """Link to get next page of results""" - value: Optional[List[ConversationThread]] = None + value: Optional[ + List[ConversationThread | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -151,51 +212,62 @@ class ConversationThread: Response for Get a conversation thread """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The conversation thread's unique identifier.""" - topic: Optional[str] = None + topic: Optional[str] = dataclass_field(default=None, kw_only=True) """The topic of the conversation.""" - has_attachments: Optional[bool] = field( + has_attachments: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasAttachments"}, ) """ Indicates whether any of the posts within this Conversation has at least one attachment. """ - last_delivered_date_time: Optional[str] = field( + last_delivered_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastDeliveredDateTime"}, ) """ The Timestamp type represents date and time information using ISO 8601 format and is always in UTC time. """ - unique_senders: Optional[List[str]] = field( + unique_senders: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "uniqueSenders"}, ) """All the users that sent a message to this Conversation.""" - preview: Optional[str] = None + preview: Optional[str] = dataclass_field(default=None, kw_only=True) """ A short summary from the body of the latest post in this Conversation. """ - is_locked: Optional[bool] = field( + is_locked: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isLocked"}, ) """Indicates if the thread is locked.""" - to_recipients: Optional[List[EmailAddress]] = field( + to_recipients: Optional[List[EmailAddress | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "toRecipients"}, ) """The To: recipients for the thread.""" - cc_recipients: Optional[List[EmailAddress]] = field( + cc_recipients: Optional[List[EmailAddress | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ccRecipients"}, ) """The Cc: recipients for the thread.""" - posts: Optional[List[Post]] = None + posts: Optional[ + List[Post | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -204,17 +276,24 @@ class ListThreadPostsResponse: Response for List the posts of a conversation thread """ - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """Link to get next page of results""" - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The @odata.context link.""" - value: Optional[List[Post]] = None + value: Optional[ + List[Post | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Array containing the posts in the specified thread.""" @@ -224,58 +303,72 @@ class Post: Response for Get a thread post """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The post's unique identifier.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) - change_key: Optional[str] = field( + change_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "changeKey"}, ) """Identifies the version of the post.""" - conversation_id: Optional[str] = field( + conversation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "conversationId"}, ) """Unique ID of the conversation the post belongs to.""" - conversation_thread_id: Optional[str] = field( + conversation_thread_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "conversationThreadId"}, ) """Unique ID of the conversation thread the post belongs to.""" - categories: Optional[List[str]] = None + categories: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """The categories associated with the post.""" - received_date_time: Optional[str] = field( + received_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "receivedDateTime"}, ) """Post received timestamp.""" - has_attachments: Optional[bool] = field( + has_attachments: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasAttachments"}, ) """Indicates whether the post has at least one attachment.""" - new_participants: Optional[List[EmailAddress]] = field( + new_participants: Optional[List[EmailAddress | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newParticipants"}, ) """ Conversation participants that were added to the thread as part of this post. """ - body: Optional[ItemBody] = None - from_: Optional[EmailAddress] = field( + body: Optional[ItemBody | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + from_: Optional[EmailAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "from"}, ) - sender: Optional[EmailAddress] = None - attachments: Optional[List[Attachment]] = None + sender: Optional[EmailAddress | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + attachments: Optional[ + List[Attachment | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -284,17 +377,24 @@ class GetAttachmentsResponse: Response for List the attachments of a post """ - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """Link to get next page of results""" - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The @odata.context link.""" - value: Optional[List[Attachment]] = None + value: Optional[ + List[Attachment | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Array containing the attachments of the post.""" @@ -304,7 +404,12 @@ class OnNewEmailInGroupResponse: Response for When a new email arrives to a group """ - value: Optional[List[ConversationTriggerResponse]] = None + value: Optional[ + List[ConversationTriggerResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Response of the trigger.""" @@ -314,7 +419,7 @@ class ObjectWithoutType: Response for Send an HTTP request """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -327,7 +432,7 @@ class ListGroupsResponse: Response for List user groups """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Array with the groups the user is part of.""" @@ -337,19 +442,21 @@ class Attachment: Definition: Attachment """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id of the attachment.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of attachment.""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentType"}, ) """Content type of attachment.""" - size: Optional[int] = None + size: Optional[int] = dataclass_field(default=None, kw_only=True) """Size of attachment.""" - content_bytes: Optional[str] = field( + content_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentBytes"}, ) """Content of attachment.""" @@ -361,8 +468,9 @@ class EmailAddress: Definition: EmailAddress """ - email_address: Optional[Dict[str, Any]] = field( + email_address: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "emailAddress"}, ) """ @@ -377,12 +485,13 @@ class ItemBody: Definition: ItemBody """ - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentType"}, ) """Content type of the body.""" - content: Optional[str] = None + content: Optional[str] = dataclass_field(default=None, kw_only=True) """Content of the body.""" @@ -392,7 +501,7 @@ class ReplyConversationThreadBody: Definition: ReplyConversationThreadBody """ - post: Optional[NewPostBody] = None + post: Optional[NewPostBody | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -401,13 +510,13 @@ class ForwardPostBody: Definition: ForwardPost_V2Body """ - comment: Optional[str] = field( + comment: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comment"}, ) """Comment to forward with the post.""" - to_recipients: Optional[List[GetUsersGraphAction]] = field( - default=None, + to_recipients: List[GetUsersGraphAction | Mapping[str, Any]] = dataclass_field( metadata={"wire_name": "ToRecipients"}, ) """The recipients to whom the threaded is forwarded to.""" @@ -419,9 +528,9 @@ class CreateConversationBody: Definition: CreateConversationBody """ - topic: Optional[str] = None + topic: str """Topic of the new conversation.""" - post: Optional[NewPostBody] = None + post: Optional[NewPostBody | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -430,16 +539,24 @@ class NewPostBody: Definition: NewPostBody """ - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Body of the new post.""" - categories: Optional[List[str]] = None + categories: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """The categories associated with the post.""" - new_participants: Optional[List[GetUsersGraphAction]] = field( + new_participants: Optional[ + List[GetUsersGraphAction | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newParticipants"}, ) """Add participants to the thread as part of this post.""" - attachments: Optional[List[ClientSendAttachment]] = None + attachments: Optional[ + List[ClientSendAttachment | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """File attachments to include.""" @@ -449,8 +566,9 @@ class GetUsersGraphAction: Definition: GetUsers__GraphAction """ - email_address: Optional[Dict[str, Any]] = field( + email_address: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmailAddress"}, ) """User email address.""" @@ -462,15 +580,11 @@ class ClientSendAttachment: Definition: ClientSendAttachment """ - type_: Optional[str] = field( - default=None, - metadata={"wire_name": "@odata.type"}, - ) + type_: str = dataclass_field(metadata={"wire_name": "@odata.type"}) """@odata.type for a file attachment.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: str = dataclass_field(metadata={"wire_name": "Name"}) """Name of the attachment.""" - content_bytes: Optional[str] = field( - default=None, + content_bytes: str = dataclass_field( metadata={"wire_name": "ContentBytes"}, ) """Content of the attachment.""" @@ -482,17 +596,23 @@ class ConversationTriggerResponse: Definition: ConversationTriggerResponse """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The conversation unique identifier.""" - last_delivered_date_time: Optional[str] = field( + last_delivered_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastDeliveredDateTime"}, ) """ The Timestamp type represents date and time information using ISO 8601 format and is always in UTC time. """ - threads: Optional[List[ConversationThreadTriggerResponse]] = None + threads: Optional[ + List[ConversationThreadTriggerResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -501,9 +621,14 @@ class ConversationThreadTriggerResponse: Definition: ConversationThreadTriggerResponse """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The conversation thread's unique identifier.""" - posts: Optional[List[PostTriggerResponse]] = None + posts: Optional[ + List[PostTriggerResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -512,14 +637,16 @@ class PostTriggerResponse: Definition: PostTriggerResponse """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The post's unique identifier.""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) - change_key: Optional[str] = field( + change_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "changeKey"}, ) """Identifies the version of the post.""" @@ -533,16 +660,16 @@ class Office365groupsmailClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -553,8 +680,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -562,8 +689,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -575,7 +702,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -597,7 +724,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -629,7 +756,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def list_conversations_async( + def list_conversations( self, group_id: str, *, @@ -637,24 +764,47 @@ async def list_conversations_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List the conversations of a group Get all the conversations in this group. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListConversations`. + + Args: + group_id: Pick a group from the drop down or enter group id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/groups/{quote(str(group_id), safe='')}/conversations" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -667,25 +817,34 @@ async def list_conversations_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def create_conversation_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def create_conversation( self, - input: CreateConversationBody, + input: CreateConversationBody | Mapping[str, Any], group_id: str, *, timeout: Optional[float] = None, @@ -697,13 +856,30 @@ async def create_conversation_async( Create a new conversation in a group Create a new conversation in this group. + + Swagger operation ID: `CreateConversation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Pick a group from the drop down or enter group id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/groups/{quote(str(group_id), safe='')}/conversations" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -717,6 +893,7 @@ async def create_conversation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -724,7 +901,7 @@ async def create_conversation_async( return json.loads(response.text) - async def get_group_conversation_async( + def get_group_conversation( self, group_id: str, conversation_id: str, @@ -738,6 +915,22 @@ async def get_group_conversation_async( Get a group conversation Retrieves the properties of a particular conversation. + + Swagger operation ID: `GetGroupConversation`. + + Args: + group_id: Pick a group from the drop down or enter group id. + conversation_id: Enter the conversation ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -748,7 +941,7 @@ async def get_group_conversation_async( f"/{quote(str(conversation_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -762,6 +955,7 @@ async def get_group_conversation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -769,7 +963,7 @@ async def get_group_conversation_async( return json.loads(response.text) - async def list_conversation_threads_async( + def list_conversation_threads( self, group_id: str, conversation_id: str, @@ -778,14 +972,31 @@ async def list_conversation_threads_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List the conversation threads of a conversation Get all the threads in a group conversation. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListConversationThreads`. + + Args: + group_id: Pick a group from the drop down or enter group id. + conversation_id: Enter the conversation ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -796,11 +1007,18 @@ async def list_conversation_threads_async( f"/{quote(str(conversation_id), safe='')}" f"/threads" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -813,25 +1031,34 @@ async def list_conversation_threads_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def create_conversation_thread_async( + return ItemPaged(get_next, extract_data) + + def create_conversation_thread( self, - input: CreateConversationBody, + input: CreateConversationBody | Mapping[str, Any], group_id: str, conversation_id: str, *, @@ -844,6 +1071,24 @@ async def create_conversation_thread_async( Create a conversation thread Create a new thread in the specified conversation. + + Swagger operation ID: `CreateConversationThread`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Pick a group from the drop down or enter group id. + conversation_id: Enter the conversation ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -855,7 +1100,7 @@ async def create_conversation_thread_async( f"/threads" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -869,6 +1114,7 @@ async def create_conversation_thread_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -876,7 +1122,7 @@ async def create_conversation_thread_async( return json.loads(response.text) - async def list_group_threads_async( + def list_group_threads( self, group_id: str, *, @@ -884,24 +1130,47 @@ async def list_group_threads_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List the threads of a group Get all the threads of a group. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListGroupThreads`. + + Args: + group_id: Pick a group from the drop down or enter group id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/groups/{quote(str(group_id), safe='')}/threads" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -914,25 +1183,34 @@ async def list_group_threads_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def create_group_thread_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def create_group_thread( self, - input: CreateConversationBody, + input: CreateConversationBody | Mapping[str, Any], group_id: str, *, timeout: Optional[float] = None, @@ -944,13 +1222,30 @@ async def create_group_thread_async( Start a new group conversation by creating a thread Start a new group conversation by first creating a thread. + + Swagger operation ID: `CreateGroupThread`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Pick a group from the drop down or enter group id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/groups/{quote(str(group_id), safe='')}/threads" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -964,6 +1259,7 @@ async def create_group_thread_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -971,7 +1267,7 @@ async def create_group_thread_async( return json.loads(response.text) - async def get_conversation_thread_async( + def get_conversation_thread( self, group_id: str, thread_id: str, @@ -985,6 +1281,22 @@ async def get_conversation_thread_async( Get a conversation thread Get a specific thread that belongs to a group. + + Swagger operation ID: `GetConversationThread`. + + Args: + group_id: Pick a group from the drop down or enter group id. + thread_id: Enter the conversation thread ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -995,7 +1307,7 @@ async def get_conversation_thread_async( f"/{quote(str(thread_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1009,6 +1321,7 @@ async def get_conversation_thread_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1016,7 +1329,7 @@ async def get_conversation_thread_async( return json.loads(response.text) - async def delete_conversation_thread_async( + def delete_conversation_thread( self, group_id: str, thread_id: str, @@ -1030,6 +1343,22 @@ async def delete_conversation_thread_async( Delete a conversation thread Deletes the specified conversation thread. + + Swagger operation ID: `DeleteConversationThread`. + + Args: + group_id: Pick a group from the drop down or enter group id. + thread_id: Enter the conversation thread ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1040,7 +1369,7 @@ async def delete_conversation_thread_async( f"/{quote(str(thread_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1054,9 +1383,10 @@ async def delete_conversation_thread_async( request_url, response.status, response.text, + response=response, ) - async def list_thread_posts_async( + def list_thread_posts( self, group_id: str, thread_id: str, @@ -1065,14 +1395,31 @@ async def list_thread_posts_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List the posts of a conversation thread Get all the posts of the specified conversation thread. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListThreadPosts`. + + Args: + group_id: Pick a group from the drop down or enter group id. + thread_id: Enter the conversation thread ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1083,11 +1430,18 @@ async def list_thread_posts_async( f"/{quote(str(thread_id), safe='')}" f"/posts" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1100,23 +1454,32 @@ async def list_thread_posts_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_thread_async( + return ItemPaged(get_next, extract_data) + + def get_thread( self, group_id: str, thread_id: str, @@ -1131,6 +1494,23 @@ async def get_thread_async( Get a thread post Retrieves a post in a specified thread. + + Swagger operation ID: `GetThreadPost`. + + Args: + group_id: Pick a group from the drop down or enter group id. + thread_id: Enter the conversation thread ID. + post_id: Enter the post ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1147,7 +1527,7 @@ async def get_thread_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1161,6 +1541,7 @@ async def get_thread_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1168,7 +1549,7 @@ async def get_thread_async( return json.loads(response.text) - async def get_attachments_async( + def list_attachments( self, group_id: str, thread_id: str, @@ -1178,14 +1559,32 @@ async def get_attachments_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List the attachments of a post Retrieve a list of attachments that belong to a post. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAttachments`. + + Args: + group_id: Pick a group from the drop down or enter group id. + thread_id: Enter the conversation thread ID. + post_id: Enter the post ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1198,11 +1597,18 @@ async def get_attachments_async( f"/{quote(str(post_id), safe='')}" f"/attachments" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1215,25 +1621,34 @@ async def get_attachments_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def reply_to_a_thread_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def reply_to_a_thread( self, - input: ReplyConversationThreadBody, + input: ReplyConversationThreadBody | Mapping[str, Any], group_id: str, thread_id: str, *, @@ -1246,6 +1661,24 @@ async def reply_to_a_thread_async( Reply to a conversation thread Reply to a thread in a group conversation and add a new post to it. + + Swagger operation ID: `ReplyToAThread`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Pick a group from the drop down or enter group id. + thread_id: Enter the conversation thread ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1257,7 +1690,7 @@ async def reply_to_a_thread_async( f"/reply" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1271,11 +1704,12 @@ async def reply_to_a_thread_async( request_url, response.status, response.text, + response=response, ) - async def reply_async( + def reply( self, - input: ReplyConversationThreadBody, + input: ReplyConversationThreadBody | Mapping[str, Any], group_id: str, thread_id: str, post_id: str, @@ -1290,6 +1724,25 @@ async def reply_async( Reply to a post and add a new post to the specified thread in a group conversation. + + Swagger operation ID: `ReplyPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Pick a group from the drop down or enter group id. + thread_id: Enter the conversation thread ID. + post_id: Enter the post ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1303,7 +1756,7 @@ async def reply_async( f"/reply" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1317,9 +1770,10 @@ async def reply_async( request_url, response.status, response.text, + response=response, ) - async def http_request_async( + def http_request( self, input: bytes, *, @@ -1333,10 +1787,25 @@ async def http_request_async( Construct a Microsoft Graph REST API request to invoke. Learn more: https://docs.microsoft.com/en-us/graph/use-the-api + + Swagger operation ID: `HttpRequest`. + + Args: + input: The binary request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/httprequest" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -1353,6 +1822,7 @@ async def http_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1360,9 +1830,9 @@ async def http_request_async( return json.loads(response.text) - async def forward_async( + def forward( self, - input: ForwardPostBody, + input: ForwardPostBody | Mapping[str, Any], group_mail: str, conversation_id: str, thread_id: str, @@ -1377,6 +1847,27 @@ async def forward_async( Forward a post Forward a post to a recipient. + + Swagger operation ID: `ForwardPost_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_mail: Pick a group from the drop down or enter the group mail + address. + conversation_id: Enter the conversation ID. + thread_id: Enter the conversation thread ID. + post_id: Enter the post ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1392,7 +1883,7 @@ async def forward_async( f"/forward" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1406,20 +1897,39 @@ async def forward_async( request_url, response.status, response.text, + response=response, ) - async def list_groups_async( + def list_groups( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List user groups Retrieves all Office 365 Groups the user is part of. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListGroups`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1431,27 +1941,48 @@ async def list_groups_async( query_params.append("$top=" + quote("999", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/office365users.py b/src/azure/connectors/office365users.py index c8f2ad7..7899cf0 100644 --- a/src/azure/connectors/office365users.py +++ b/src/azure/connectors/office365users.py @@ -5,21 +5,43 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "Office365usersClient", + "ClientPhotoMetadata", + "DirectReportsResponse", + "EntityListResponseIReadOnlyListUser", + "GraphTrending", + "GraphUser", + "GraphUserUpdateable", + "LinklessEntityListResponseListPerson", + "MyTrendingDocumentsResponse", + "ObjectEntity", + "ObjectWithoutType", + "Person", + "Phone", + "ResourceVisualization", + "ScoredEmailAddress", + "SensitivityLabelMetadata", + "TrendingDocumentsResponse", + "User", +] + # Type Definitions @@ -29,7 +51,12 @@ class MyTrendingDocumentsResponse: Response for Get my trending documents """ - value: Optional[List[GraphTrending]] = None + value: Optional[ + List[GraphTrending | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """value""" @@ -39,7 +66,12 @@ class LinklessEntityListResponseListPerson: Response for Get relevant people """ - value: Optional[List[Person]] = None + value: Optional[ + List[Person | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Value""" @@ -49,25 +81,33 @@ class ClientPhotoMetadata: Response for Get user photo metadata """ - has_photo: Optional[bool] = field( + has_photo: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HasPhoto"}, ) """Has photo""" - height: Optional[int] = field( + height: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Height"}, ) """Height of photo""" - width: Optional[int] = field(default=None, metadata={"wire_name": "Width"}) + width: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Width"}, + ) """Width of photo""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentType"}, ) """Content Type of photo""" - image_file_extension: Optional[str] = field( + image_file_extension: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImageFileExtension"}, ) """File extension for the photo (ex: \".jpg\")""" @@ -79,7 +119,12 @@ class TrendingDocumentsResponse: Response for Get trending documents """ - value: Optional[List[GraphTrending]] = None + value: Optional[ + List[GraphTrending | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """value""" @@ -89,7 +134,7 @@ class ObjectWithoutType: Response for Send an HTTP request """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -102,7 +147,12 @@ class DirectReportsResponse: Response for Get direct reports """ - value: Optional[List[GraphUser]] = None + value: Optional[ + List[GraphUser | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Value""" @@ -112,96 +162,110 @@ class GraphUser: Response for Get manager """ - about_me: Optional[str] = field( + about_me: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "aboutMe"}, ) """About Me""" - account_enabled: Optional[bool] = field( + account_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "accountEnabled"}, ) """ true if the account is enabled; otherwise, false. This property is required when a user is created. """ - birthday: Optional[str] = None + birthday: Optional[str] = dataclass_field(default=None, kw_only=True) """Birthday""" - business_phones: Optional[List[str]] = field( + business_phones: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "businessPhones"}, ) """Business Phones""" - city: Optional[str] = None + city: Optional[str] = dataclass_field(default=None, kw_only=True) """The city in which the user is located.""" - company_name: Optional[str] = field( + company_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "companyName"}, ) """The name of the company in which the user works.""" - country: Optional[str] = None + country: Optional[str] = dataclass_field(default=None, kw_only=True) """ The country/region in which the user is located; for example, \"US\" or \"UK\". """ - department: Optional[str] = None + department: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the department in which the user works.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display Name""" - given_name: Optional[str] = field( + given_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "givenName"}, ) """Given Name""" - hire_date: Optional[str] = field( + hire_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hireDate"}, ) """Hire Date""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id""" - interests: Optional[List[str]] = None + interests: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Interests""" - job_title: Optional[str] = field( + job_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobTitle"}, ) """Job Title""" - mail: Optional[str] = None + mail: Optional[str] = dataclass_field(default=None, kw_only=True) """Mail""" - mail_nickname: Optional[str] = field( + mail_nickname: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mailNickname"}, ) """ The mail alias for the user. This property must be specified when a user is created. """ - mobile_phone: Optional[str] = field( + mobile_phone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mobilePhone"}, ) """Mobile Phone""" - my_site: Optional[str] = field( + my_site: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mySite"}, ) """My Site""" - office_location: Optional[str] = field( + office_location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "officeLocation"}, ) """Office Location""" - past_projects: Optional[List[str]] = field( + past_projects: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pastProjects"}, ) """Past Projects""" - postal_code: Optional[str] = field( + postal_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "postalCode"}, ) """ @@ -209,38 +273,43 @@ class GraphUser: to the user's country/region. In the United States of America, this attribute contains the ZIP code. """ - preferred_language: Optional[str] = field( + preferred_language: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "preferredLanguage"}, ) """Preferred Language""" - preferred_name: Optional[str] = field( + preferred_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "preferredName"}, ) """Preferred Name""" - responsibilities: Optional[List[str]] = None + responsibilities: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Responsibilities""" - schools: Optional[List[str]] = None + schools: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Schools""" - skills: Optional[List[str]] = None + skills: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Skills""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """State""" - street_address: Optional[str] = field( + street_address: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "streetAddress"}, ) """Street Address""" - surname: Optional[str] = None + surname: Optional[str] = dataclass_field(default=None, kw_only=True) """Surname""" - user_principal_name: Optional[str] = field( + user_principal_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userPrincipalName"}, ) """User Principal Name""" - user_type: Optional[str] = field( + user_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userType"}, ) """User Type""" @@ -252,10 +321,16 @@ class EntityListResponseIReadOnlyListUser: Response for Search for users """ - value: Optional[List[User]] = None + value: Optional[ + List[User | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Value""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """Next page link""" @@ -267,28 +342,31 @@ class GraphUserUpdateable: Definition: GraphUserUpdateable """ - about_me: Optional[str] = field( + about_me: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "aboutMe"}, ) """About Me""" - birthday: Optional[str] = None + birthday: Optional[str] = dataclass_field(default=None, kw_only=True) """Birthday""" - interests: Optional[List[str]] = None + interests: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Interests""" - my_site: Optional[str] = field( + my_site: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mySite"}, ) """My Site""" - past_projects: Optional[List[str]] = field( + past_projects: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pastProjects"}, ) """Past Projects""" - schools: Optional[List[str]] = None + schools: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Schools""" - skills: Optional[List[str]] = None + skills: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Skills""" @@ -298,16 +376,20 @@ class GraphTrending: Definition: GraphTrending """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the relationship""" - weight: Optional[float] = None + weight: Optional[float] = dataclass_field(default=None, kw_only=True) """Value indicating how much the document is currently trending""" - resource_visualization: Optional[ResourceVisualization] = field( + resource_visualization: Optional[ResourceVisualization | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceVisualization"}, ) - sensitivity_label_info: Optional[List[SensitivityLabelMetadata]] = field( + sensitivity_label_info: Optional[ + List[SensitivityLabelMetadata | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelInfo"}, ) @@ -318,43 +400,53 @@ class ResourceVisualization: Definition: resourceVisualization """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The item's title text""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """ The item's media type (can be used for filtering for a specific file based on a specific type) """ - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mediaType"}, ) """ The items media type (can be used for filtering for a specific type of file based on supported IANA Media MIME types) """ - preview_image_url: Optional[str] = field( + preview_image_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "previewImageUrl"}, ) """A URL leading to the preview image for the item""" - preview_text: Optional[str] = field( + preview_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "previewText"}, ) """A preview text for the item""" - container_web_url: Optional[str] = field( + container_web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "containerWebUrl"}, ) """A path leading to the folder in which the item is stored""" - container_display_name: Optional[str] = field( + container_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "containerDisplayName"}, ) """A string describing where the item is stored""" - container_type: Optional[str] = field( + container_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "containerType"}, ) """ @@ -369,41 +461,47 @@ class SensitivityLabelMetadata: Definition: sensitivityLabelMetadata """ - sensitivity_label_id: Optional[str] = field( + sensitivity_label_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelId"}, ) """SensitivityLabel Id.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel name.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """SensitivityLabel displayName info""" - tooltip: Optional[str] = None + tooltip: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel details on tooltip.""" - priority: Optional[int] = None + priority: Optional[int] = dataclass_field(default=None, kw_only=True) """SensitivityLabel priority.""" - color: Optional[str] = None + color: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel color.""" - is_encrypted: Optional[bool] = field( + is_encrypted: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEncrypted"}, ) """ is SensitivityLabel Encrypted.""" - is_enabled: Optional[bool] = field( + is_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEnabled"}, ) """Whether SensitivityLabel is Enabled.""" - is_parent: Optional[bool] = field( + is_parent: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isParent"}, ) """Whether SensitivityLabel is Parent.""" - parent_sensitivity_label_id: Optional[str] = field( + parent_sensitivity_label_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentSensitivityLabelId"}, ) """Parent SensitivityLabel Id.""" @@ -415,53 +513,61 @@ class Person: Definition: Person """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """A unique identifier for the Person object in the directory""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The person's display name""" - given_name: Optional[str] = field( + given_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "givenName"}, ) """The person's given name""" - surname: Optional[str] = None + surname: Optional[str] = dataclass_field(default=None, kw_only=True) """The person's surname""" - birthday: Optional[str] = None + birthday: Optional[str] = dataclass_field(default=None, kw_only=True) """The person's birthday""" - person_notes: Optional[str] = field( + person_notes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personNotes"}, ) """Free-form notes that the current user has taken about this person""" - is_favorite: Optional[bool] = field( + is_favorite: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isFavorite"}, ) """If the current user has flagged this person as a favorite""" - job_title: Optional[str] = field( + job_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobTitle"}, ) """The person's job title""" - company_name: Optional[str] = field( + company_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "companyName"}, ) """The name of the person's company""" - department: Optional[str] = None + department: Optional[str] = dataclass_field(default=None, kw_only=True) """The person's department""" - office_location: Optional[str] = field( + office_location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "officeLocation"}, ) """The location of the person's office""" - profession: Optional[str] = None + profession: Optional[str] = dataclass_field(default=None, kw_only=True) """The person's profession""" - user_principal_name: Optional[str] = field( + user_principal_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userPrincipalName"}, ) """ @@ -471,17 +577,26 @@ class Person: @domain, where domain must be present in the tenant's collection of verified domains. """ - im_address: Optional[str] = field( + im_address: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "imAddress"}, ) """The person's VOIP SIP address""" - scored_email_addresses: Optional[List[ScoredEmailAddress]] = field( + scored_email_addresses: Optional[ + List[ScoredEmailAddress | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "scoredEmailAddresses"}, ) """Collection of the person's email addresses with a relevance score""" - phones: Optional[List[Phone]] = None + phones: Optional[ + List[Phone | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The person's phone numbers""" @@ -491,10 +606,11 @@ class ScoredEmailAddress: Definition: ScoredEmailAddress """ - address: Optional[str] = None + address: Optional[str] = dataclass_field(default=None, kw_only=True) """The email address""" - relevance_score: Optional[float] = field( + relevance_score: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "relevanceScore"}, ) """ @@ -512,9 +628,13 @@ class Phone: Definition: Phone """ - number: Optional[str] = None + number: Optional[str] = dataclass_field(default=None, kw_only=True) """The phone number""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """ The type of phone number. Possible values: home, business, mobile, other, assistant, homeFax, businessFax, otherFax, pager, radio. @@ -527,43 +647,53 @@ class User: Definition: User """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: str = dataclass_field(metadata={"wire_name": "Id"}) """A unique identifier for the user object in the directory.""" - account_enabled: Optional[bool] = field( + account_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountEnabled"}, ) """ true if the account is enabled; otherwise, false. This property is required when a user is created. """ - business_phones: Optional[List[str]] = field( + business_phones: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BusinessPhones"}, ) """A list of business phone numbers for the user""" - city: Optional[str] = field(default=None, metadata={"wire_name": "City"}) + city: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "City"}, + ) """The city in which the user is located.""" - company_name: Optional[str] = field( + company_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CompanyName"}, ) """The name of the company in which the user works.""" - country: Optional[str] = field( + country: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Country"}, ) """ The country/region in which the user is located; for example, \"US\" or \"UK\". """ - department: Optional[str] = field( + department: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Department"}, ) """The name of the department in which the user works.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """ @@ -572,41 +702,51 @@ class User: property is required when a user is created and it cannot be cleared during updates. """ - given_name: Optional[str] = field( + given_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GivenName"}, ) """The given name (first name) of the user.""" - job_title: Optional[str] = field( + job_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JobTitle"}, ) """The user's job title.""" - mail: Optional[str] = field(default=None, metadata={"wire_name": "Mail"}) + mail: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Mail"}, + ) """ The SMTP/email address for the user, for example, \"jeff@contoso.onmicrosoft.com\". Read-Only. """ - mail_nickname: Optional[str] = field( + mail_nickname: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MailNickname"}, ) """ The mail alias for the user. This property must be specified when a user is created. """ - mobile_phone: Optional[str] = field( + mobile_phone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mobilePhone"}, ) """The primary cellular telephone number for the user.""" - office_location: Optional[str] = field( + office_location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfficeLocation"}, ) """The office location in the user's place of business.""" - postal_code: Optional[str] = field( + postal_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PostalCode"}, ) """ @@ -614,18 +754,21 @@ class User: to the user's country/region. In the United States of America, this attribute contains the ZIP code. """ - surname: Optional[str] = field( + surname: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Surname"}, ) """The user's surname (family name or last name).""" - telephone_number: Optional[str] = field( + telephone_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TelephoneNumber"}, ) """The primary cellular telephone number for the user.""" - user_principal_name: Optional[str] = field( + user_principal_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UserPrincipalName"}, ) """ @@ -643,7 +786,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -658,16 +801,16 @@ class Office365usersClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -678,8 +821,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -687,8 +830,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -700,7 +843,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -722,7 +865,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -754,9 +897,9 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def update_my_profile_async( + def update_my_profile( self, - input: GraphUserUpdateable, + input: GraphUserUpdateable | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -767,10 +910,26 @@ async def update_my_profile_async( Update my profile Updates the profile of the current user + + Swagger operation ID: `UpdateMyProfile`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/codeless/v1.0/me" - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -784,9 +943,10 @@ async def update_my_profile_async( request_url, response.status, response.text, + response=response, ) - async def update_my_photo_async( + def update_my_photo( self, input: bytes, *, @@ -800,12 +960,27 @@ async def update_my_photo_async( Updates the profile photo of the current user. The size of the photo must be less than 4 MB. + + Swagger operation ID: `UpdateMyPhoto`. + + Args: + input: The binary request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/codeless/v1.0/me/photo/$value" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, @@ -822,23 +997,49 @@ async def update_my_photo_async( request_url, response.status, response.text, + response=response, ) - async def my_trending_documents_async( + def list_my_trending_documents( self, + *, filter: Optional[str] = None, extract_sensitivity_label: Optional[bool] = None, fetch_sensitivity_label_metadata: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get my trending documents Retrieves the trending documents for the signed in user + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `MyTrendingDocuments`. + + Args: + filter: An OData filter to filter the resources selected. Filter + selected resources on ResourceVisualization/Type or + ResourceVisualization/containerType. + extract_sensitivity_label: Select if you want to extract + Sensitivity label ( false, true). + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -862,29 +1063,50 @@ async def my_trending_documents_async( query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def relevant_people_async( + def list_relevant_people( self, user_id: str, *, @@ -892,39 +1114,79 @@ async def relevant_people_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get relevant people Get relevant people. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `RelevantPeople`. + + Args: + user_id: User principal name or id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/users/{quote(str(user_id), safe='')}/relevantpeople" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def user_photo_metadata_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def user_photo_metadata( self, user_id: str, *, @@ -937,6 +1199,21 @@ async def user_photo_metadata_async( Get user photo metadata Get user photo metadata. + + Swagger operation ID: `UserPhotoMetadata`. + + Args: + user_id: User principal name or id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/users/photo" query_params = [] @@ -947,7 +1224,7 @@ async def user_photo_metadata_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -961,6 +1238,7 @@ async def user_photo_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -968,22 +1246,48 @@ async def user_photo_metadata_async( return json.loads(response.text) - async def trending_documents_async( + def list_trending_documents( self, id: str, + *, filter: Optional[str] = None, extract_sensitivity_label: Optional[bool] = None, fetch_sensitivity_label_metadata: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get trending documents Retrieves the trending documents for a user + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `TrendingDocuments`. + + Args: + id: User principal name or id. + filter: An OData filter to filter the resources selected. Filter + selected resources on ResourceVisualization/Type or + ResourceVisualization/containerType. + extract_sensitivity_label: Select if you want to extract + Sensitivity label ( false, true). + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1007,29 +1311,50 @@ async def trending_documents_async( query_params.append(f"fetchSensitivityLabelMetadata={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def http_request_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def http_request( self, input: bytes, *, @@ -1046,10 +1371,25 @@ async def http_request_async( messages, mailFolders, events, calendar, calendars, outlook, inferenceClassification. Learn more: https://docs.microsoft.com/en-us/graph/use-the-api. + + Swagger operation ID: `HttpRequest`. + + Args: + input: The binary request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/codeless/httprequest" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -1066,6 +1406,7 @@ async def http_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1073,23 +1414,46 @@ async def http_request_async( return json.loads(response.text) - async def direct_reports_async( + def list_direct_reports( self, id: str, + *, select: Optional[str] = None, top: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get direct reports Retrieves the user profiles of the specified user's direct reports. Learn more about available fields to select: https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/user#properties + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `DirectReports_V2`. + + Args: + id: User principal name or id. + select: Comma separated list of fields to select. Example: surname, + department, jobTitle. + top: Limit on the number of results to return. By default returns + all entries. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1108,33 +1472,54 @@ async def direct_reports_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def manager_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def manager( self, id: str, - select: Optional[str] = None, *, + select: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1146,6 +1531,23 @@ async def manager_async( Retrieves the profile of the specified user's manager. Learn more about available fields to select: https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/user#properties + + Swagger operation ID: `Manager_V2`. + + Args: + id: User principal name or id. + select: Comma separated list of fields to select. Example: surname, + department, jobTitle. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1160,7 +1562,7 @@ async def manager_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1174,6 +1576,7 @@ async def manager_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1181,10 +1584,10 @@ async def manager_async( return json.loads(response.text) - async def my_profile_async( + def my_profile( self, - select: Optional[str] = None, *, + select: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1196,6 +1599,22 @@ async def my_profile_async( Retrieves the profile of the current user. Learn more about available fields to select: https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/user#properties + + Swagger operation ID: `MyProfile_V2`. + + Args: + select: Comma separated list of fields to select. Example: surname, + department, jobTitle. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/codeless/v1.0/me" query_params = [] @@ -1207,7 +1626,7 @@ async def my_profile_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1221,6 +1640,7 @@ async def my_profile_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1228,24 +1648,46 @@ async def my_profile_async( return json.loads(response.text) - async def search_user_async( + def list_search_user( self, + *, search_term: Optional[str] = None, top: Optional[int] = None, is_search_term_required: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Search for users Retrieves the user profiles that match the search term. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SearchUserV2`. + + Args: + search_term: Search string (applies to: display name, given name, + surname, mail, mail nickname and user principal name). + top: Limit on the number of results to return. Minimum value is 1. + Default value is 1000. + is_search_term_required: If set to 'Yes' then no user profiles will + be returned when the search term is empty. If set to 'No' then + no filtering will be applied when the search term is empty. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/users" query_params = [] @@ -1266,11 +1708,18 @@ async def search_user_async( query_params.append(f"isSearchTermRequired={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1283,23 +1732,32 @@ async def search_user_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def user_photo_async( + def user_photo( self, id: str, *, @@ -1312,13 +1770,28 @@ async def user_photo_async( Get user photo Retrieves the photo of the specified user if they have one + + Swagger operation ID: `UserPhoto_V2`. + + Args: + id: User principal name or id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/codeless/v1.0/users/{quote(str(id), safe='')}/photo/$value" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1332,15 +1805,16 @@ async def user_photo_async( request_url, response.status, response.text, + response=response, ) return response.content - async def user_profile_async( + def user_profile( self, id: str, - select: Optional[str] = None, *, + select: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1352,6 +1826,23 @@ async def user_profile_async( Retrieves the profile of a specific user. Learn more about available fields to select: https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/user#properties + + Swagger operation ID: `UserProfile_V2`. + + Args: + id: User principal name or id. + select: Comma separated list of fields to select. Example: surname, + department, jobTitle. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1366,7 +1857,7 @@ async def user_profile_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1380,6 +1871,7 @@ async def user_profile_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/onedrive.py b/src/azure/connectors/onedrive.py index 7694bcb..273fb15 100644 --- a/src/azure/connectors/onedrive.py +++ b/src/azure/connectors/onedrive.py @@ -5,21 +5,35 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "OnedriveClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "BlobMetadataPage", + "DataSetsMetadata", + "SharingLink", + "TabularDataSetsMetadata", + "Tags", + "Thumbnail", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,51 +43,78 @@ class BlobMetadata: Response for Get file metadata """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique identifier of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - name_no_ext: Optional[str] = field( + name_no_ext: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameNoExt"}, ) """The name of the file or folder, without the file extension.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The file or folder size in bytes.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The file locator of the file or folder.""" - last_modified_by: Optional[str] = field( + last_modified_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModifiedBy"}, ) """The user who last modified the file or folder.""" @@ -85,8 +126,9 @@ class Tags: Response for Get file tags """ - tags: Optional[List[str]] = field( + tags: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Tags"}, ) """A list of tags.""" @@ -98,12 +140,21 @@ class Thumbnail: Response for Get file thumbnail """ - url: Optional[str] = field(default=None, metadata={"wire_name": "Url"}) + url: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Url"}, + ) """A URL that points to the thumbnail.""" - width: Optional[int] = field(default=None, metadata={"wire_name": "Width"}) + width: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Width"}, + ) """The thumbnail width in pixels.""" - height: Optional[int] = field( + height: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Height"}, ) """The thumbnail height in pixels.""" @@ -115,8 +166,9 @@ class SharingLink: Response for Create share link """ - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebUrl"}, ) """A URL that points to the file or folder.""" @@ -128,10 +180,16 @@ class BlobMetadataPage: Response for List files in folder """ - value: Optional[List[BlobMetadata]] = None + value: Optional[ + List[BlobMetadata | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Blob metadata collection.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """A URL which can be used to retrieve the next page.""" @@ -143,8 +201,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -153,25 +221,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -183,15 +255,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -205,16 +279,16 @@ class OnedriveClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -225,8 +299,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -234,8 +308,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -247,7 +321,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -269,7 +343,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -301,7 +375,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def get_file_metadata_async( + def get_file_metadata( self, id: str, *, @@ -314,6 +388,21 @@ async def get_file_metadata_async( Get file metadata This operation gets the metadata for a file. + + Swagger operation ID: `GetFileMetadata`. + + Args: + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -323,7 +412,7 @@ async def get_file_metadata_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -337,6 +426,7 @@ async def get_file_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -344,7 +434,7 @@ async def get_file_metadata_async( return json.loads(response.text) - async def update_file_async( + def update_file( self, input: bytes, id: str, @@ -358,6 +448,22 @@ async def update_file_async( Update file This operation updates a file. + + Swagger operation ID: `UpdateFile`. + + Args: + input: The binary request body. + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -367,7 +473,7 @@ async def update_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, @@ -384,6 +490,7 @@ async def update_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -391,7 +498,7 @@ async def update_file_async( return json.loads(response.text) - async def delete_file_async( + def delete_file( self, id: str, *, @@ -404,6 +511,21 @@ async def delete_file_async( Delete file This operation deletes a file. + + Swagger operation ID: `DeleteFile`. + + Args: + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -413,7 +535,7 @@ async def delete_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -427,9 +549,10 @@ async def delete_file_async( request_url, response.status, response.text, + response=response, ) - async def get_file_metadata_by_path_async( + def get_file_metadata_by_path( self, path: str, *, @@ -442,6 +565,21 @@ async def get_file_metadata_by_path_async( Get file metadata using path This operation gets the metadata of a file using the path. + + Swagger operation ID: `GetFileMetadataByPath`. + + Args: + path: The unique path of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/GetFileByPath" @@ -454,7 +592,7 @@ async def get_file_metadata_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -468,6 +606,7 @@ async def get_file_metadata_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -475,11 +614,11 @@ async def get_file_metadata_by_path_async( return json.loads(response.text) - async def get_file_content_by_path_async( + def get_file_content_by_path( self, path: str, - infer_content_type: Optional[bool] = None, *, + infer_content_type: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -489,6 +628,23 @@ async def get_file_content_by_path_async( Get file content using path This operation gets the content of a file using the path. + + Swagger operation ID: `GetFileContentByPath`. + + Args: + path: The unique path of the file. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -507,7 +663,7 @@ async def get_file_content_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -521,15 +677,16 @@ async def get_file_content_by_path_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_file_content_async( + def get_file_content( self, id: str, - infer_content_type: Optional[bool] = None, *, + infer_content_type: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -539,6 +696,23 @@ async def get_file_content_async( Get file content This operation gets the content of a file. + + Swagger operation ID: `GetFileContent`. + + Args: + id: The unique identifier of the file. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -557,7 +731,7 @@ async def get_file_content_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -571,11 +745,12 @@ async def get_file_content_async( request_url, response.status, response.text, + response=response, ) return response.content - async def create_file_async( + def create_file( self, input: bytes, folder_path: str, @@ -590,6 +765,24 @@ async def create_file_async( Create file This operation creates a file. + + Swagger operation ID: `CreateFile`. + + Args: + input: The binary request body. + folder_path: The unique path of the folder. + name: The name of the file. Certain characters are disallowed by + OneDrive and will be replaced by underscores. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/datasets/default/files" query_params = [] @@ -604,7 +797,7 @@ async def create_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -621,6 +814,7 @@ async def create_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -628,12 +822,12 @@ async def create_file_async( return json.loads(response.text) - async def copy_file_async( + def copy_file( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -643,6 +837,23 @@ async def copy_file_async( Upload file from URL This operation uploads a file from a URL to OneDrive. + + Swagger operation ID: `CopyFile`. + + Args: + source: The url to the source file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/copyFile" @@ -664,7 +875,7 @@ async def copy_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -678,6 +889,7 @@ async def copy_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -685,12 +897,12 @@ async def copy_file_async( return json.loads(response.text) - async def copy_drive_file_async( + def copy_drive_file( self, id: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -700,6 +912,23 @@ async def copy_drive_file_async( Copy file This operation copies a file within OneDrive. + + Swagger operation ID: `CopyDriveFile`. + + Args: + id: The unique identifier of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -722,7 +951,7 @@ async def copy_drive_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -736,6 +965,7 @@ async def copy_drive_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -743,12 +973,12 @@ async def copy_drive_file_async( return json.loads(response.text) - async def copy_drive_file_by_path_async( + def copy_drive_file_by_path( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -758,6 +988,23 @@ async def copy_drive_file_by_path_async( Copy file using path This operation copies a file within OneDrive by path. + + Swagger operation ID: `CopyDriveFileByPath`. + + Args: + source: The unique path of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/CopyFileByPath" @@ -779,7 +1026,7 @@ async def copy_drive_file_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -793,6 +1040,7 @@ async def copy_drive_file_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -800,12 +1048,12 @@ async def copy_drive_file_by_path_async( return json.loads(response.text) - async def move_file_async( + def move_file( self, id: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -815,6 +1063,23 @@ async def move_file_async( Move or rename a file This operation moves or renames a file. + + Swagger operation ID: `MoveFile`. + + Args: + id: The unique identifier of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -837,7 +1102,7 @@ async def move_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -851,6 +1116,7 @@ async def move_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -858,12 +1124,12 @@ async def move_file_async( return json.loads(response.text) - async def move_file_by_path_async( + def move_file_by_path( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -873,6 +1139,23 @@ async def move_file_by_path_async( Move or rename a file using path This operation moves or renames a file using the path. + + Swagger operation ID: `MoveFileByPath`. + + Args: + source: The unique path of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/MoveFileByPath" @@ -894,7 +1177,7 @@ async def move_file_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -908,6 +1191,7 @@ async def move_file_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -915,11 +1199,11 @@ async def move_file_by_path_async( return json.loads(response.text) - async def convert_file_async( + def convert_file( self, id: str, - type_: Optional[str] = None, *, + type_: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -930,6 +1214,22 @@ async def convert_file_async( This operation converts a file to another format. The list of supported conversions can be found at https://aka.ms/onedriveconversions + + Swagger operation ID: `ConvertFile`. + + Args: + id: The unique identifier of the file. + type_: The target file type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -948,7 +1248,7 @@ async def convert_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -962,15 +1262,16 @@ async def convert_file_async( request_url, response.status, response.text, + response=response, ) return response.content - async def convert_file_by_path_async( + def convert_file_by_path( self, path: str, - type_: Optional[str] = None, *, + type_: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -982,6 +1283,22 @@ async def convert_file_by_path_async( This operation converts a file to another format using the path. The list of supported conversions can be found at https://aka.ms/onedriveconversions + + Swagger operation ID: `ConvertFileByPath`. + + Args: + path: The unique path of the file. + type_: The target file type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1000,7 +1317,7 @@ async def convert_file_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1014,11 +1331,12 @@ async def convert_file_by_path_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_file_tags_async( + def list_file_tags( self, id: str, *, @@ -1026,11 +1344,30 @@ async def get_file_tags_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[str]: """ Get file tags This operation gets the tags of a file. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetFileTags`. + + Args: + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[str]: An Azure Core pager over connector results. Consume + it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1040,29 +1377,50 @@ async def get_file_tags_async( f"/{quote(quote(str(id), safe=''), safe='')}" f"/tags" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[str]: + for item in page.get("Tags", []): + yield item - async def add_file_tag_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def add_file_tag( self, id: str, tag: str, @@ -1076,6 +1434,22 @@ async def add_file_tag_async( Add file tag This operation adds a tag to a file. + + Swagger operation ID: `AddFileTag`. + + Args: + id: The unique identifier of the file. + tag: The name of the tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1093,7 +1467,7 @@ async def add_file_tag_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1107,6 +1481,7 @@ async def add_file_tag_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1114,7 +1489,7 @@ async def add_file_tag_async( return json.loads(response.text) - async def remove_file_tag_async( + def remove_file_tag( self, id: str, tag: str, @@ -1128,6 +1503,22 @@ async def remove_file_tag_async( Remove file tag This operation removes a tag from a file. + + Swagger operation ID: `RemoveFileTag`. + + Args: + id: The unique identifier of the file. + tag: The name of the tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1145,7 +1536,7 @@ async def remove_file_tag_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1159,9 +1550,10 @@ async def remove_file_tag_async( request_url, response.status, response.text, + response=response, ) - async def get_file_thumbnail_async( + def get_file_thumbnail( self, id: str, size: str, @@ -1176,6 +1568,22 @@ async def get_file_thumbnail_async( This operation gets the thumbnail of a file. The thumbnail will only be valid for 6 hours. + + Swagger operation ID: `GetFileThumbnail`. + + Args: + id: The unique identifier of the file. + size: The size of the thumbnail to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1193,7 +1601,7 @@ async def get_file_thumbnail_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1207,6 +1615,7 @@ async def get_file_thumbnail_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1214,62 +1623,127 @@ async def get_file_thumbnail_async( return json.loads(response.text) - async def list_root_folder_async( + def list_root_folder( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List files in root folder This operation gets the list of files and subfolders in the root folder. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListRootFolder`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/folders" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def find_files_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_find_files( self, id: str, query: str, find_mode: str, - max_file_count: Optional[int] = None, *, + max_file_count: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Find files in folder This operation finds files within a folder using search or name pattern match. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `FindFiles`. + + Args: + id: The unique identifier of the folder. + query: The search query to use. + find_mode: The search method to use. \"Search\" mode searches your + OneDrive using the search query (similar a normal search + engine). When \"Regular Expression Pattern Match\" mode is + selected, the search query will be treated as a regex pattern, + and it will return files with names that match the query. + max_file_count: Maximum number of files to return (1-100). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1295,45 +1769,92 @@ async def find_files_async( query_params.append(f"maxFileCount={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def find_files_by_path_async( + return ItemPaged(get_next, extract_data) + + def list_find_files_by_path( self, query: str, path: str, find_mode: str, - max_file_count: Optional[int] = None, *, + max_file_count: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Find files in folder by path This operation finds files within a folder by path using search or name pattern match. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `FindFilesByPath`. + + Args: + query: The search query to use. + path: The unique path of the folder. + find_mode: The search method to use. \"Search\" mode searches your + OneDrive using the search query (similar a normal search + engine). When \"Regular Expression Pattern Match\" mode is + selected, the search query will be treated as a regex pattern, + and it will return files with names that match the query. + max_file_count: Maximum number of files to return (1-100). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/findFile" @@ -1358,29 +1879,50 @@ async def find_files_by_path_async( query_params.append(f"maxFileCount={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def create_share_link_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def create_share_link( self, id: str, type_: str, @@ -1394,6 +1936,22 @@ async def create_share_link_async( Create share link This operation creates a share link for a file. + + Swagger operation ID: `CreateShareLinkV2`. + + Args: + id: The unique identifier of the file. + type_: The type of link. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1411,7 +1969,7 @@ async def create_share_link_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1425,6 +1983,7 @@ async def create_share_link_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1432,7 +1991,7 @@ async def create_share_link_async( return json.loads(response.text) - async def create_share_link_by_path_async( + def create_share_link_by_path( self, path: str, type_: str, @@ -1446,6 +2005,22 @@ async def create_share_link_by_path_async( Create share link by path This operation creates a share link for a file using the path. + + Swagger operation ID: `CreateShareLinkByPathV2`. + + Args: + path: The unique path of the file. + type_: The type of link. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1463,7 +2038,7 @@ async def create_share_link_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1477,6 +2052,7 @@ async def create_share_link_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1484,12 +2060,12 @@ async def create_share_link_by_path_async( return json.loads(response.text) - async def extract_folder_async( + def extract_folder( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1500,6 +2076,23 @@ async def extract_folder_async( This operation extracts an archive file into a folder (example: .zip). Maximum archive size is 50 MB and 100 files inside. + + Swagger operation ID: `ExtractFolderV2`. + + Args: + source: The path to the archive file. + destination: The path to extract the archive contents. + overwrite: Overwrites the destination files if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/extractFolderV2" @@ -1521,7 +2114,7 @@ async def extract_folder_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1535,6 +2128,7 @@ async def extract_folder_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1542,7 +2136,7 @@ async def extract_folder_async( return json.loads(response.text) - async def list_folder_async( + def list_folder( self, id: str, *, @@ -1550,14 +2144,30 @@ async def list_folder_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List files in folder This operation gets the list of files and subfolders in a folder. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListFolderV2`. + + Args: + id: The unique identifier of the folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1571,11 +2181,18 @@ async def list_folder_async( query_params.append("top=" + quote("20", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1588,21 +2205,30 @@ async def list_folder_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/onedriveforbusiness.py b/src/azure/connectors/onedriveforbusiness.py index e660079..4215d78 100644 --- a/src/azure/connectors/onedriveforbusiness.py +++ b/src/azure/connectors/onedriveforbusiness.py @@ -5,21 +5,36 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "OnedriveforbusinessClient", + "BlobDataSetsMetadata", + "BlobMetadata", + "BlobMetadataPage", + "DataSetsMetadata", + "ForASelectedFileResponse", + "SharingLink", + "TabularDataSetsMetadata", + "Tags", + "Thumbnail", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,51 +44,78 @@ class BlobMetadata: Response for Get file metadata """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique identifier of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - name_no_ext: Optional[str] = field( + name_no_ext: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameNoExt"}, ) """The name of the file or folder, without the file extension.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The file or folder size in bytes.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The file locator of the file or folder.""" - last_modified_by: Optional[str] = field( + last_modified_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModifiedBy"}, ) """The user who last modified the file or folder.""" @@ -85,12 +127,21 @@ class Thumbnail: Response for Get file thumbnail """ - url: Optional[str] = field(default=None, metadata={"wire_name": "Url"}) + url: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Url"}, + ) """A URL that points to the thumbnail.""" - width: Optional[int] = field(default=None, metadata={"wire_name": "Width"}) + width: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Width"}, + ) """The thumbnail width in pixels.""" - height: Optional[int] = field( + height: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Height"}, ) """The thumbnail height in pixels.""" @@ -102,8 +153,9 @@ class SharingLink: Response for Create share link """ - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebUrl"}, ) """A URL that points to the file or folder.""" @@ -115,10 +167,16 @@ class BlobMetadataPage: Response for List files in folder """ - value: Optional[List[BlobMetadata]] = None + value: Optional[ + List[BlobMetadata | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Blob metadata collection.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """A URL which can be used to retrieve the next page.""" @@ -130,8 +188,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -140,25 +208,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -170,15 +242,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -190,8 +264,9 @@ class Tags: Definition: Tags """ - tags: Optional[List[str]] = field( + tags: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Tags"}, ) """A list of tags.""" @@ -203,13 +278,15 @@ class ForASelectedFileResponse: Definition: ForASelectedFileResponse """ - file_path: Optional[str] = field( + file_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filePath"}, ) """The unique path of the file.""" - file_url: Optional[str] = field( + file_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fileUrl"}, ) """The URL to the source file.""" @@ -223,16 +300,16 @@ class OnedriveforbusinessClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -243,8 +320,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -252,8 +329,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -265,7 +342,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -287,7 +364,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -319,7 +396,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def get_file_metadata_async( + def get_file_metadata( self, id: str, *, @@ -332,6 +409,21 @@ async def get_file_metadata_async( Get file metadata This operation gets the metadata for a file. + + Swagger operation ID: `GetFileMetadata`. + + Args: + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -341,7 +433,7 @@ async def get_file_metadata_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -355,6 +447,7 @@ async def get_file_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -362,7 +455,7 @@ async def get_file_metadata_async( return json.loads(response.text) - async def update_file_async( + def update_file( self, input: bytes, id: str, @@ -376,6 +469,22 @@ async def update_file_async( Update file This operation updates a file. + + Swagger operation ID: `UpdateFile`. + + Args: + input: The binary request body. + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -385,7 +494,7 @@ async def update_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, @@ -402,6 +511,7 @@ async def update_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -409,7 +519,7 @@ async def update_file_async( return json.loads(response.text) - async def delete_file_async( + def delete_file( self, id: str, *, @@ -422,6 +532,21 @@ async def delete_file_async( Delete file This operation deletes a file. + + Swagger operation ID: `DeleteFile`. + + Args: + id: The unique identifier of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -431,7 +556,7 @@ async def delete_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -445,9 +570,10 @@ async def delete_file_async( request_url, response.status, response.text, + response=response, ) - async def get_file_metadata_by_path_async( + def get_file_metadata_by_path( self, path: str, *, @@ -460,6 +586,21 @@ async def get_file_metadata_by_path_async( Get file metadata using path This operation gets the metadata of a file using the path. + + Swagger operation ID: `GetFileMetadataByPath`. + + Args: + path: The unique path of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/GetFileByPath" @@ -472,7 +613,7 @@ async def get_file_metadata_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -486,6 +627,7 @@ async def get_file_metadata_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -493,11 +635,11 @@ async def get_file_metadata_by_path_async( return json.loads(response.text) - async def get_file_content_by_path_async( + def get_file_content_by_path( self, path: str, - infer_content_type: Optional[bool] = None, *, + infer_content_type: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -507,6 +649,23 @@ async def get_file_content_by_path_async( Get file content using path This operation gets the content of a file using the path. + + Swagger operation ID: `GetFileContentByPath`. + + Args: + path: The unique path of the file. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -525,7 +684,7 @@ async def get_file_content_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -539,15 +698,16 @@ async def get_file_content_by_path_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_file_content_async( + def get_file_content( self, id: str, - infer_content_type: Optional[bool] = None, *, + infer_content_type: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -557,6 +717,23 @@ async def get_file_content_async( Get file content This operation gets the content of a file. + + Swagger operation ID: `GetFileContent`. + + Args: + id: The unique identifier of the file. + infer_content_type: A boolean value (true, false) to infer + content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -575,7 +752,7 @@ async def get_file_content_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -589,11 +766,12 @@ async def get_file_content_async( request_url, response.status, response.text, + response=response, ) return response.content - async def create_file_async( + def create_file( self, input: bytes, folder_path: str, @@ -608,6 +786,24 @@ async def create_file_async( Create file This operation creates a file. + + Swagger operation ID: `CreateFile`. + + Args: + input: The binary request body. + folder_path: The unique path of the folder. + name: The name of the file. Certain characters are disallowed by + OneDrive and will be replaced by underscores. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/datasets/default/files" query_params = [] @@ -622,7 +818,7 @@ async def create_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -639,6 +835,7 @@ async def create_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -646,12 +843,12 @@ async def create_file_async( return json.loads(response.text) - async def copy_file_async( + def copy_file( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -661,6 +858,23 @@ async def copy_file_async( Upload file from URL This operation uploads a file from a URL to OneDrive. + + Swagger operation ID: `CopyFile`. + + Args: + source: The url to the source file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/copyFile" @@ -682,7 +896,7 @@ async def copy_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -696,6 +910,7 @@ async def copy_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -703,12 +918,12 @@ async def copy_file_async( return json.loads(response.text) - async def copy_drive_file_async( + def copy_drive_file( self, id: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -718,6 +933,23 @@ async def copy_drive_file_async( Copy file This operation copies a file within OneDrive. + + Swagger operation ID: `CopyDriveFile`. + + Args: + id: The unique identifier of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -740,7 +972,7 @@ async def copy_drive_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -754,6 +986,7 @@ async def copy_drive_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -761,12 +994,12 @@ async def copy_drive_file_async( return json.loads(response.text) - async def copy_drive_file_by_path_async( + def copy_drive_file_by_path( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -776,6 +1009,23 @@ async def copy_drive_file_by_path_async( Copy file using path This operation copies a file within OneDrive by path. + + Swagger operation ID: `CopyDriveFileByPath`. + + Args: + source: The unique path of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/CopyFileByPath" @@ -797,7 +1047,7 @@ async def copy_drive_file_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -811,6 +1061,7 @@ async def copy_drive_file_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -818,12 +1069,12 @@ async def copy_drive_file_by_path_async( return json.loads(response.text) - async def move_file_async( + def move_file( self, id: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -833,6 +1084,23 @@ async def move_file_async( Move or rename a file This operation moves or renames a file. + + Swagger operation ID: `MoveFile`. + + Args: + id: The unique identifier of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -855,7 +1123,7 @@ async def move_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -869,6 +1137,7 @@ async def move_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -876,12 +1145,12 @@ async def move_file_async( return json.loads(response.text) - async def move_file_by_path_async( + def move_file_by_path( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -891,6 +1160,23 @@ async def move_file_by_path_async( Move or rename a file using path This operation moves or renames a file using the path. + + Swagger operation ID: `MoveFileByPath`. + + Args: + source: The unique path of the file. + destination: The destination file path, including target filename. + overwrite: Overwrites the destination file if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/MoveFileByPath" @@ -912,7 +1198,7 @@ async def move_file_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -926,6 +1212,7 @@ async def move_file_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -933,11 +1220,11 @@ async def move_file_by_path_async( return json.loads(response.text) - async def convert_file_async( + def convert_file( self, id: str, - type_: Optional[str] = None, *, + type_: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -948,6 +1235,22 @@ async def convert_file_async( This operation converts a file to another format. The list of supported conversions can be found at https://aka.ms/onedriveconversions + + Swagger operation ID: `ConvertFile`. + + Args: + id: The unique identifier of the file. + type_: The target file type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -966,7 +1269,7 @@ async def convert_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -980,15 +1283,16 @@ async def convert_file_async( request_url, response.status, response.text, + response=response, ) return response.content - async def convert_file_by_path_async( + def convert_file_by_path( self, path: str, - type_: Optional[str] = None, *, + type_: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1000,6 +1304,22 @@ async def convert_file_by_path_async( This operation converts a file to another format using the path. The list of supported conversions can be found at https://aka.ms/onedriveconversions + + Swagger operation ID: `ConvertFileByPath`. + + Args: + path: The unique path of the file. + type_: The target file type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1018,7 +1338,7 @@ async def convert_file_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1032,11 +1352,12 @@ async def convert_file_by_path_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_file_thumbnail_async( + def get_file_thumbnail( self, id: str, size: str, @@ -1051,6 +1372,22 @@ async def get_file_thumbnail_async( This operation gets the thumbnail of a file. The thumbnail will only be valid for 6 hours. + + Swagger operation ID: `GetFileThumbnail`. + + Args: + id: The unique identifier of the file. + size: The size of the thumbnail to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1068,7 +1405,7 @@ async def get_file_thumbnail_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1082,6 +1419,7 @@ async def get_file_thumbnail_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1089,62 +1427,127 @@ async def get_file_thumbnail_async( return json.loads(response.text) - async def list_root_folder_async( + def list_root_folder( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List files in root folder This operation gets the list of files and subfolders in the root folder. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListRootFolder`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/folders" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def find_files_async( + def list_find_files( self, id: str, query: str, find_mode: str, - max_file_count: Optional[int] = None, *, + max_file_count: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Find files in folder This operation finds files within a folder using search or name pattern match. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `FindFiles`. + + Args: + id: The unique identifier of the folder. + query: The search query to use. + find_mode: The search method to use. \"Search\" mode searches your + OneDrive using the search query (similar a normal search + engine). When \"Regular Expression Pattern Match\" mode is + selected, the search query will be treated as a regex pattern, + and it will return files with names that match the query. + max_file_count: Maximum number of files to return (1-100). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1170,45 +1573,92 @@ async def find_files_async( query_params.append(f"maxFileCount={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - async def find_files_by_path_async( + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_find_files_by_path( self, query: str, path: str, find_mode: str, - max_file_count: Optional[int] = None, *, + max_file_count: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Find files in folder by path This operation finds files within a folder by path using search or name pattern match. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `FindFilesByPath`. + + Args: + query: The search query to use. + path: The unique path of the folder. + find_mode: The search method to use. \"Search\" mode searches your + OneDrive using the search query (similar a normal search + engine). When \"Regular Expression Pattern Match\" mode is + selected, the search query will be treated as a regex pattern, + and it will return files with names that match the query. + max_file_count: Maximum number of files to return (1-100). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/findFile" @@ -1233,34 +1683,55 @@ async def find_files_by_path_async( query_params.append(f"maxFileCount={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def create_share_link_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def create_share_link( self, id: str, type_: str, - scope: Optional[str] = None, *, + scope: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1270,6 +1741,23 @@ async def create_share_link_async( Create share link This operation creates a share link for a file. + + Swagger operation ID: `CreateShareLinkV2`. + + Args: + id: The unique identifier of the file. + type_: The type of link. + scope: The scope of the link. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1292,7 +1780,7 @@ async def create_share_link_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1306,6 +1794,7 @@ async def create_share_link_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1313,12 +1802,12 @@ async def create_share_link_async( return json.loads(response.text) - async def create_share_link_by_path_async( + def create_share_link_by_path( self, path: str, type_: str, - scope: Optional[str] = None, *, + scope: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1328,6 +1817,23 @@ async def create_share_link_by_path_async( Create share link by path This operation creates a share link for a file using the path. + + Swagger operation ID: `CreateShareLinkByPathV2`. + + Args: + path: The unique path of the file. + type_: The type of link. + scope: The scope of the link. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1350,7 +1856,7 @@ async def create_share_link_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1364,6 +1870,7 @@ async def create_share_link_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1371,12 +1878,12 @@ async def create_share_link_by_path_async( return json.loads(response.text) - async def extract_folder_async( + def extract_folder( self, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1387,6 +1894,23 @@ async def extract_folder_async( This operation extracts an archive file into a folder (example: .zip). Maximum archive size is 50 MB and 100 files inside. + + Swagger operation ID: `ExtractFolderV2`. + + Args: + source: The path to the archive file. + destination: The path to extract the archive contents. + overwrite: Overwrites the destination files if set to 'true'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/extractFolderV2" @@ -1408,7 +1932,7 @@ async def extract_folder_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1422,6 +1946,7 @@ async def extract_folder_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1429,7 +1954,7 @@ async def extract_folder_async( return json.loads(response.text) - async def list_folder_async( + def list_folder( self, id: str, *, @@ -1437,14 +1962,30 @@ async def list_folder_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List files in folder This operation gets the list of files and subfolders in a folder. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListFolderV2`. + + Args: + id: The unique identifier of the folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1458,11 +1999,18 @@ async def list_folder_async( query_params.append("top=" + quote("20", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1475,21 +2023,30 @@ async def list_folder_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/onenote.py b/src/azure/connectors/onenote.py index 8a70e43..b645c05 100644 --- a/src/azure/connectors/onenote.py +++ b/src/azure/connectors/onenote.py @@ -5,21 +5,47 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "OnenoteClient", + "CreatePageInQuickNotesInput", + "CreatePageInSectionInput", + "CreateSectionInNotebookResponse", + "CreateSectionRequest", + "GetPageResponse", + "GetPagesInSectionResponse", + "GetSectionsInNotebookResponse", + "Link", + "NewPageResponse", + "NewSectionGroupResponse", + "NewSectionResponse", + "Notebook", + "OneNoteClientUrl", + "OneNoteWebUrl", + "Page", + "ParentNotebook", + "SectionGroupResponse", + "SectionListItem", + "SectionResponse", + "UpdatePageContentRequest", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,47 +55,54 @@ class CreateSectionInNotebookResponse: Response for Create section in a notebook """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The OData context.""" - created_by: Optional[str] = field( + created_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdBy"}, ) """This section created by name.""" - created_time: Optional[str] = field( + created_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdTime"}, ) """This section created time.""" - id: Optional[str] = None - is_default: Optional[bool] = field( + id: Optional[str] = dataclass_field(default=None, kw_only=True) + is_default: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isDefault"}, ) """A flag to indication if this is the default section.""" - last_modified_by: Optional[str] = field( + last_modified_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedBy"}, ) """Last modified by name.""" - last_modified_time: Optional[str] = field( + last_modified_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedTime"}, ) """The time this section was last modified.""" - links: Optional[Dict[str, Any]] = None + links: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """OneNote client links.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the section.""" - pages_url: Optional[str] = field( + pages_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pagesUrl"}, ) """The url of the pages.""" - self: Optional[str] = None + self: Optional[str] = dataclass_field(default=None, kw_only=True) """The url to create section in notebook group.""" @@ -82,25 +115,28 @@ class Page: Response for Create page in a section """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the page.""" - links: Optional[Link] = None - content_url: Optional[str] = field( + links: Optional[Link | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + content_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentUrl"}, ) """A url to the page content.""" - last_modified_time: Optional[str] = field( + last_modified_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedTime"}, ) """The last modified date of the page.""" - created_time: Optional[str] = field( + created_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdTime"}, ) """The date the page was created.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique identifier of the page.""" @@ -110,15 +146,17 @@ class GetPagesInSectionResponse: Response for Get pages for a specific section """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The OData context.""" - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -133,11 +171,16 @@ class Notebook: Response for Get recent notebooks """ - file_name: Optional[str] = field( + file_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileName"}, ) - key: Optional[str] = field(default=None, metadata={"wire_name": "Key"}) + key: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Key"}, + ) @dataclass @@ -146,7 +189,12 @@ class GetSectionsInNotebookResponse: Response for Get sections in notebook """ - value: Optional[List[SectionListItem]] = None + value: Optional[ + List[SectionListItem | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -155,7 +203,12 @@ class NewSectionResponse: Response for When a new section is created """ - value: Optional[List[SectionResponse]] = None + value: Optional[ + List[SectionResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """An array of objects, each representing a specific section.""" @@ -165,7 +218,12 @@ class NewSectionGroupResponse: Response for When a new section group is created """ - value: Optional[List[SectionGroupResponse]] = None + value: Optional[ + List[SectionGroupResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """An array of objects, each representing a specific section group.""" @@ -175,7 +233,12 @@ class NewPageResponse: Response for When a new page is created in a section """ - value: Optional[List[Page]] = None + value: Optional[ + List[Page | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """An array of objects, each representing a specific page.""" @@ -185,7 +248,7 @@ class CreateSectionRequest: Definition: CreateSectionRequest """ - name: Optional[str] = None + name: str """The name of the new section.""" @@ -198,12 +261,13 @@ class GetPageResponse: Definition: GetPageResponse """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """The OData context.""" - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """This page response value.""" @@ -213,11 +277,11 @@ class ParentNotebook: Definition: ParentNotebook """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique identifier of the parent notebook.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the parent notebook.""" - self: Optional[str] = None + self: Optional[str] = dataclass_field(default=None, kw_only=True) """A url link to the parent notebook.""" @@ -227,12 +291,10 @@ class Link: Definition: Link """ - one_note_client_url: Optional[OneNoteClientUrl] = field( - default=None, + one_note_client_url: OneNoteClientUrl | Mapping[str, Any] = dataclass_field( metadata={"wire_name": "oneNoteClientUrl"}, ) - one_note_web_url: Optional[OneNoteWebUrl] = field( - default=None, + one_note_web_url: OneNoteWebUrl | Mapping[str, Any] = dataclass_field( metadata={"wire_name": "oneNoteWebUrl"}, ) @@ -243,7 +305,7 @@ class OneNoteClientUrl: Definition: OneNoteClientUrl """ - href: Optional[str] = None + href: str """A link to the notebook using the OneNote windows client.""" @@ -253,7 +315,7 @@ class OneNoteWebUrl: Definition: OneNoteWebUrl """ - href: Optional[str] = None + href: str """A link to the notebook using the OneNote web client.""" @@ -263,14 +325,15 @@ class SectionListItem: Definition: SectionListItem """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the section.""" - pages_url: Optional[str] = field( + pages_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pagesUrl"}, ) """The key used to reference this section; also a url to the pages.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the section.""" @@ -280,45 +343,52 @@ class SectionResponse: Definition: SectionResponse """ - created_by: Optional[str] = field( + created_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdBy"}, ) """The creator of the section.""" - created_time: Optional[str] = field( + created_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdTime"}, ) """The creation date and time of the section.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the section.""" - is_default: Optional[bool] = field( + is_default: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isDefault"}, ) """Indicates whether it is the default section.""" - last_modified_by: Optional[str] = field( + last_modified_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedBy"}, ) """The user who last modified the section.""" - last_modified_time: Optional[str] = field( + last_modified_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedTime"}, ) """The last modified date and time of the section.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the section.""" - pages_url: Optional[str] = field( + pages_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pagesUrl"}, ) """Url to the pages in this section.""" - parent_notebook: Optional[ParentNotebook] = field( + parent_notebook: Optional[ParentNotebook | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentNotebook"}, ) - self: Optional[str] = None + self: Optional[str] = dataclass_field(default=None, kw_only=True) """The url to this section.""" @@ -328,36 +398,41 @@ class SectionGroupResponse: Definition: SectionGroupResponse """ - created_time: Optional[str] = field( + created_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdTime"}, ) """The creation date and time of the section group.""" - created_by: Optional[str] = field( + created_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdBy"}, ) """The creator of the section group.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the section group.""" - last_modified_by: Optional[str] = field( + last_modified_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedBy"}, ) """The user who last modified the section group.""" - last_modified_time: Optional[str] = field( + last_modified_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedTime"}, ) """The last modification date and time of the section group.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the section group.""" - sections_url: Optional[str] = field( + sections_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sectionsUrl"}, ) """Url of the sections within this section group.""" - self: Optional[str] = None + self: Optional[str] = dataclass_field(default=None, kw_only=True) """The url to this section group.""" @@ -369,16 +444,16 @@ class OnenoteClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -389,8 +464,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -398,8 +473,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -411,7 +486,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -433,7 +508,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -465,9 +540,9 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def create_section_in_notebook_async( + def create_section_in_notebook( self, - input: CreateSectionRequest, + input: CreateSectionRequest | Mapping[str, Any], notebook_key: str, *, timeout: Optional[float] = None, @@ -479,6 +554,24 @@ async def create_section_in_notebook_async( Create section in a notebook Create section in a notebook. + + Swagger operation ID: `CreateSectionInNotebook`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + notebook_key: A key identifying the notebook. Note this is specific + to the API and cannot be hand-typed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/notebooks/Dynamic/sections" @@ -491,7 +584,7 @@ async def create_section_in_notebook_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -505,6 +598,7 @@ async def create_section_in_notebook_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -512,7 +606,7 @@ async def create_section_in_notebook_async( return json.loads(response.text) - async def create_page_in_section_async( + def create_page_in_section( self, input: CreatePageInSectionInput, notebook_key: str, @@ -527,6 +621,24 @@ async def create_page_in_section_async( Create page in a section Create new page in a specified section. + + Swagger operation ID: `CreatePageInSection`. + + Args: + input: The request body. + notebook_key: A key identifying the notebook. Note this is specific + to the API and cannot be hand-typed. + section_id: API URL of the section pages. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/sections/Dynamic/pages" query_params = [] @@ -541,7 +653,7 @@ async def create_page_in_section_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -555,6 +667,7 @@ async def create_page_in_section_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -562,7 +675,7 @@ async def create_page_in_section_async( return json.loads(response.text) - async def get_pages_in_section_async( + def list_pages_in_section( self, notebook_key: str, section_id: str, @@ -571,14 +684,32 @@ async def get_pages_in_section_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get pages for a specific section Get pages for a specific section. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetPagesInSection`. + + Args: + notebook_key: A key identifying the notebook. Note this is specific + to the API and cannot be hand-typed. + section_id: API URL of the section pages. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/sections/Dynamic/pages" query_params = [] @@ -592,11 +723,18 @@ async def get_pages_in_section_async( query_params.append(f"sectionId={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -609,23 +747,32 @@ async def get_pages_in_section_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def create_page_in_quick_notes_async( + def create_page_in_quick_notes( self, input: CreatePageInQuickNotesInput, *, @@ -638,10 +785,25 @@ async def create_page_in_quick_notes_async( Create a page in Quick Notes Create a new page in the Quick Notes section. + + Swagger operation ID: `CreatePageInQuickNotes`. + + Args: + input: The request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/pages" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -655,6 +817,7 @@ async def create_page_in_quick_notes_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -662,7 +825,7 @@ async def create_page_in_quick_notes_async( return json.loads(response.text) - async def delete_page_async( + def delete_page( self, notebook_key: str, section_id: str, @@ -677,6 +840,24 @@ async def delete_page_async( Delete a page Delete a page. + + Swagger operation ID: `DeletePage`. + + Args: + notebook_key: A key identifying the notebook. Note this is specific + to the API and cannot be hand-typed. + section_id: API URL of the section pages. + page_id: Unique id of the page. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/pages" query_params = [] @@ -695,7 +876,7 @@ async def delete_page_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -709,9 +890,10 @@ async def delete_page_async( request_url, response.status, response.text, + response=response, ) - async def get_page_content_async( + def get_page_content( self, notebook_key: str, section_id: str, @@ -726,6 +908,24 @@ async def get_page_content_async( Get page content Get HTML page content. + + Swagger operation ID: `GetPageContent`. + + Args: + notebook_key: A key identifying the notebook. Note this is specific + to the API and cannot be hand-typed. + section_id: API URL of the section pages. + page_id: Unique id of the page. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/pages/Dynamic/content" query_params = [] @@ -745,7 +945,7 @@ async def get_page_content_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -759,6 +959,7 @@ async def get_page_content_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -766,7 +967,7 @@ async def get_page_content_async( return json.loads(response.text) - async def update_page_content_async( + def update_page_content( self, input: UpdatePageContentRequest, notebook_key: str, @@ -782,6 +983,25 @@ async def update_page_content_async( Update page content Update HTML page content. + + Swagger operation ID: `UpdatePageContent`. + + Args: + input: The request body. + notebook_key: A key identifying the notebook. Note this is specific + to the API and cannot be hand-typed. + section_id: API URL of the section pages. + page_id: Unique id of the page. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/pages/Dynamic/content" query_params = [] @@ -800,7 +1020,7 @@ async def update_page_content_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -814,6 +1034,7 @@ async def update_page_content_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -821,43 +1042,82 @@ async def update_page_content_async( return json.loads(response.text) - async def get_notebooks_async( + def list_notebooks( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get recent notebooks Get recent notebooks. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetNotebooks`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/notebooks" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def get_sections_in_notebook_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_sections_in_notebook( self, notebook_key: str, *, @@ -865,11 +1125,31 @@ async def get_sections_in_notebook_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get sections in notebook Get sections in a specific notebook. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetSectionsInNotebook`. + + Args: + notebook_key: A key identifying the notebook. Note this is specific + to the API and cannot be hand-typed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/notebooks/notebookKey/sections" @@ -881,27 +1161,48 @@ async def get_sections_in_notebook_async( query_params.append(f"notebookKey={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/orderful.py b/src/azure/connectors/orderful.py index 555074b..982e250 100644 --- a/src/azure/connectors/orderful.py +++ b/src/azure/connectors/orderful.py @@ -5,13 +5,13 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, Dict, Any, Mapping from urllib.parse import quote +import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, @@ -19,6 +19,16 @@ ConnectorResponseHook, ) +__all__ = [ + "OrderfulClient", + "CommunicationChannelCreationResponse", + "CommunicationChannelEventResponse", + "CommunicationChannelInput", + "CommunicationChannelRequestBody", + "CreateTransactionInput", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -28,7 +38,7 @@ class CreateTransactionInput: Create Transaction """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -41,18 +51,12 @@ class CommunicationChannelInput: Listen to Communication Channel """ - is_active: Optional[bool] = field( - default=None, - metadata={"wire_name": "isActive"}, - ) - name: Optional[str] = None + is_active: bool = dataclass_field(metadata={"wire_name": "isActive"}) + name: str """Communication Channel Name.""" - config: Optional[Dict[str, Any]] = None + config: Dict[str, Any] """Configuration of the Trigger""" - owner_id: Optional[int] = field( - default=None, - metadata={"wire_name": "ownerId"}, - ) + owner_id: int = dataclass_field(metadata={"wire_name": "ownerId"}) """Owner of the Orderful account.""" @@ -62,7 +66,7 @@ class CommunicationChannelCreationResponse: Response for Listen to Communication Channel """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) @dataclass @@ -71,7 +75,7 @@ class CommunicationChannelEventResponse: Definition: CommunicationChannelEventResponse """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -84,19 +88,13 @@ class CommunicationChannelRequestBody: Definition: CommunicationChannelRequestBody """ - is_active: Optional[bool] = field( - default=None, - metadata={"wire_name": "isActive"}, - ) + is_active: bool = dataclass_field(metadata={"wire_name": "isActive"}) """If the State of the Trigger is active.""" - name: Optional[str] = None + name: str """Communication Channel Name.""" - config: Optional[Dict[str, Any]] = None + config: Dict[str, Any] """Configuration of the Trigger.""" - owner_id: Optional[int] = field( - default=None, - metadata={"wire_name": "ownerId"}, - ) + owner_id: int = dataclass_field(metadata={"wire_name": "ownerId"}) """Owner of the Orderful account.""" @@ -108,16 +106,16 @@ class OrderfulClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -128,8 +126,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -137,8 +135,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -150,7 +148,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -165,23 +163,37 @@ def __init__( def connector_name(self) -> str: return "orderful" - async def list_transactions_async( + def list_transactions( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> None: + ) -> dict[str, Any] | None: """ List Transactions Fetches a list of transactions as specified by the filter/sort parameters supplied. + + Swagger operation ID: `ListTransactions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/transactions" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -195,11 +207,17 @@ async def list_transactions_async( request_url, response.status, response.text, + response=response, ) - async def create_transaction_async( + if not response.text: + return None + + return json.loads(response.text) + + def create_transaction( self, - input: CreateTransactionInput, + input: CreateTransactionInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -210,10 +228,26 @@ async def create_transaction_async( Create Transaction Create Transaction. + + Swagger operation ID: `CreateTransaction`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/transactions" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -227,9 +261,10 @@ async def create_transaction_async( request_url, response.status, response.text, + response=response, ) - async def get_transaction_by_id_async( + def get_transaction_by_id( self, transaction_id: int, *, @@ -242,13 +277,28 @@ async def get_transaction_by_id_async( Get Transaction by ID Get transaction by ID. + + Swagger operation ID: `GetTransactionById`. + + Args: + transaction_id: The transaction Id used to retrieve transaction.. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v2/transactions/{quote(str(transaction_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -262,6 +312,7 @@ async def get_transaction_by_id_async( request_url, response.status, response.text, + response=response, ) diff --git a/src/azure/connectors/outlook.py b/src/azure/connectors/outlook.py index 9e80793..56313d1 100644 --- a/src/azure/connectors/outlook.py +++ b/src/azure/connectors/outlook.py @@ -5,21 +5,97 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "OutlookClient", + "ApprovalEmailResponse", + "ApprovalEmailSubscription", + "ApprovalMessage", + "Attendee", + "BatchResponseClientReceiveMessage", + "BlobDataSetsMetadata", + "CalendarEventBackend", + "CalendarEventClient", + "CalendarEventClientReceive", + "CalendarEventClientReceiveStringEnums", + "CalendarEventClientWithActionType", + "CalendarEventHtmlClient", + "CalendarEventList", + "CalendarEventListClientReceive", + "CalendarEventListWithActionType", + "ClientReceiveFileAttachment", + "ClientReceiveMessage", + "ClientReceiveMessageStringEnums", + "ClientSendAttachment", + "ClientSendHtmlMessage", + "ClientSendMessage", + "ClientSubscription", + "Contact", + "ContactResponse", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "DirectForwardMessage", + "EmailAddress", + "EntityListResponseCalendarEventBackend", + "EntityListResponseCalendarEventClientReceiveStringEnums", + "EntityListResponseContactResponse", + "EntityListResponseFilePickerFile", + "EntityListResponseTable", + "FilePickerFile", + "GeoCoordinates", + "InternetMessageHeader", + "ItemBody", + "Location", + "MessageWithOptions", + "ObjectEntity", + "OptionsEmailSubscription", + "OutlookReceiveAttachment", + "OutlookReceiveMessage", + "PaginatedListResponseCalendarEventClientReceiveStringEnums", + "PassThroughNativeQuery", + "PatternedRecurrence", + "PhysicalAddress", + "Procedure", + "Recipient", + "RecurrencePattern", + "RecurrenceRange", + "ReplyHtmlMessage", + "ReplyMessage", + "ResponseStatus", + "ResponseToEventInvite", + "SubscriptionEvent", + "SubscriptionPayloadEntityOutlookReceiveMessage", + "SubscriptionPayloadEntitySubscriptionEvent", + "SubscriptionPayloadOutlookReceiveMessage", + "SubscriptionPayloadSubscriptionEvent", + "SubscriptionResponse", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TabularDataSetsMetadata", + "TriggerBatchResponseClientReceiveMessage", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,70 +105,107 @@ class ClientReceiveMessage: Response for Get email """ - from_: Optional[str] = field(default=None, metadata={"wire_name": "From"}) + from_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "From"}, + ) """The mailbox owner and sender of the message""" - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "To"}, + ) """The recipients for the message""" - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """The Cc recipients for the message""" - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """The Bcc recipients for the message""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """The email addresses to use when replying""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """The subject of the message""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """The body of the message""" - importance: Optional[int] = field( + importance: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the message (0 - Low, 1 - Normal, 2 - High)""" - body_preview: Optional[str] = field( + body_preview: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BodyPreview"}, ) """The preview of the message""" - has_attachment: Optional[bool] = field( + has_attachment: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HasAttachment"}, ) """Indicates whether the message has attachments""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique identifier of the message""" - internet_message_id: Optional[str] = field( + internet_message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InternetMessageId"}, ) """The message ID in the format specified by RFC2822""" - conversation_id: Optional[str] = field( + conversation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ConversationId"}, ) """The Id of the conversation the email belongs to""" - date_time_received: Optional[str] = field( + date_time_received: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeReceived"}, ) """The date and time the message was received""" - is_read: Optional[bool] = field( + is_read: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsRead"}, ) """Indicates whether the message has been read""" - attachments: Optional[List[ClientReceiveFileAttachment]] = field( + attachments: Optional[ + List[ClientReceiveFileAttachment | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """The file attachments for the message""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Is Html?""" @@ -104,70 +217,107 @@ class ClientReceiveMessageStringEnums: Response for Move email """ - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the message""" - from_: Optional[str] = field(default=None, metadata={"wire_name": "From"}) + from_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "From"}, + ) """The mailbox owner and sender of the message""" - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "To"}, + ) """The recipients for the message""" - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """The Cc recipients for the message""" - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """The Bcc recipients for the message""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """The email addresses to use when replying""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """The subject of the message""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """The body of the message""" - body_preview: Optional[str] = field( + body_preview: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BodyPreview"}, ) """The preview of the message""" - has_attachment: Optional[bool] = field( + has_attachment: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HasAttachment"}, ) """Indicates whether the message has attachments""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique identifier of the message""" - internet_message_id: Optional[str] = field( + internet_message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InternetMessageId"}, ) """The message ID in the format specified by RFC2822""" - conversation_id: Optional[str] = field( + conversation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ConversationId"}, ) """The Id of the conversation the email belongs to""" - date_time_received: Optional[str] = field( + date_time_received: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeReceived"}, ) """The date and time the message was received""" - is_read: Optional[bool] = field( + is_read: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsRead"}, ) """Indicates whether the message has been read""" - attachments: Optional[List[ClientReceiveFileAttachment]] = field( + attachments: Optional[ + List[ClientReceiveFileAttachment | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """The file attachments for the message""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Is Html?""" @@ -179,17 +329,19 @@ class SubscriptionResponse: Response for Send email with options """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id of the subscription""" - resource: Optional[str] = None + resource: Optional[str] = dataclass_field(default=None, kw_only=True) """Resource of the subscription request""" - notification_type: Optional[str] = field( + notification_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notificationType"}, ) """Notification Type""" - notification_url: Optional[str] = field( + notification_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notificationUrl"}, ) """Notification Url""" @@ -201,7 +353,12 @@ class EntityListResponseTable: Response for Get calendars """ - value: Optional[List[Table]] = None + value: Optional[ + List[Table | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -211,7 +368,12 @@ class EntityListResponseContactResponse: Response for Get contacts """ - value: Optional[List[ContactResponse]] = None + value: Optional[ + List[ContactResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -221,169 +383,210 @@ class ContactResponse: Response for Create contact """ - given_name: Optional[str] = field( + given_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GivenName"}, ) """The contact's given name""" - home_phones: Optional[List[str]] = field( + home_phones: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HomePhones"}, ) """The contact's home phone numbers""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The contact's unique identifier.""" - parent_folder_id: Optional[str] = field( + parent_folder_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ParentFolderId"}, ) """The ID of the contact's parent folder""" - birthday: Optional[str] = field( + birthday: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Birthday"}, ) """The contact's birthday""" - file_as: Optional[str] = field( + file_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileAs"}, ) """The name the contact is filed under""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The contact's display name""" - initials: Optional[str] = field( + initials: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Initials"}, ) """The contact's initials""" - middle_name: Optional[str] = field( + middle_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MiddleName"}, ) """The contact's middle name""" - nick_name: Optional[str] = field( + nick_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NickName"}, ) """The contact's nickname""" - surname: Optional[str] = field( + surname: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Surname"}, ) """The contact's surname""" - title: Optional[str] = field(default=None, metadata={"wire_name": "Title"}) + title: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Title"}, + ) """The contact's title""" - generation: Optional[str] = field( + generation: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Generation"}, ) """The contact's generation""" - email_addresses: Optional[List[EmailAddress]] = field( + email_addresses: Optional[List[EmailAddress | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmailAddresses"}, ) """The contact's email addresses""" - im_addresses: Optional[List[str]] = field( + im_addresses: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImAddresses"}, ) """The contact's instant messaging (IM) addresses""" - job_title: Optional[str] = field( + job_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JobTitle"}, ) """The contact's job title""" - company_name: Optional[str] = field( + company_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CompanyName"}, ) """The name of the contact's company""" - department: Optional[str] = field( + department: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Department"}, ) """The contact's department""" - office_location: Optional[str] = field( + office_location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfficeLocation"}, ) """The location of the contact's office""" - profession: Optional[str] = field( + profession: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Profession"}, ) """The contact's profession""" - business_home_page: Optional[str] = field( + business_home_page: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BusinessHomePage"}, ) """The business home page of the contact""" - assistant_name: Optional[str] = field( + assistant_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AssistantName"}, ) """The name of the contact's assistant""" - manager: Optional[str] = field( + manager: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Manager"}, ) """The name of the contact's manager""" - business_phones: Optional[List[str]] = field( + business_phones: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BusinessPhones"}, ) """The contact's business phone numbers""" - mobile_phone1: Optional[str] = field( + mobile_phone1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MobilePhone1"}, ) """The contact's mobile phone number""" - home_address: Optional[PhysicalAddress] = field( + home_address: Optional[PhysicalAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HomeAddress"}, ) - business_address: Optional[PhysicalAddress] = field( + business_address: Optional[PhysicalAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BusinessAddress"}, ) - other_address: Optional[PhysicalAddress] = field( + other_address: Optional[PhysicalAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OtherAddress"}, ) - yomi_company_name: Optional[str] = field( + yomi_company_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "YomiCompanyName"}, ) """The phonetic Japanese company name of the contact""" - yomi_given_name: Optional[str] = field( + yomi_given_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "YomiGivenName"}, ) """The phonetic Japanese given name (first name) of the contact""" - yomi_surname: Optional[str] = field( + yomi_surname: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "YomiSurname"}, ) """The phonetic Japanese surname (last name) of the contact""" - categories: Optional[List[str]] = field( + categories: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Categories"}, ) """The categories associated with the contact""" - change_key: Optional[str] = field( + change_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChangeKey"}, ) """Identifies the version of the event object""" - date_time_created: Optional[str] = field( + date_time_created: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeCreated"}, ) """The time the contact was created""" - date_time_last_modified: Optional[str] = field( + date_time_last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeLastModified"}, ) """The time the contact was modified""" @@ -395,137 +598,177 @@ class CalendarEventClientReceiveStringEnums: Response for Get event """ - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the event: Low, Normal, or High""" - response_type: Optional[str] = field( + response_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseType"}, ) """ The response type of the event: None, Organizer, TentativelyAccepted, Accepted, Declined or NotResponded """ - recurrence: Optional[str] = field( + recurrence: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Recurrence"}, ) """The recurrence pattern for the event""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowAs"}, ) """Status to show during the event""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Event subject""" - start: Optional[str] = field(default=None, metadata={"wire_name": "Start"}) + start: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Start"}, + ) """Start time of the event (example: '2016-11-01T14:30:00Z')""" - end: Optional[str] = field(default=None, metadata={"wire_name": "End"}) + end: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "End"}, + ) """End time of the event (example: '2016-11-01T15:30:00Z')""" - response_time: Optional[str] = field( + response_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseTime"}, ) """The response time of the event""" - i_cal_u_id: Optional[str] = field( + i_cal_u_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ICalUId"}, ) """ A unique identifier that is shared by all instances of an event across different calendars """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The event's unique identifier""" - date_time_created: Optional[str] = field( + date_time_created: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeCreated"}, ) """The date and time that the event was created""" - date_time_last_modified: Optional[str] = field( + date_time_last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeLastModified"}, ) """The date and time that the event was last modified""" - organizer: Optional[str] = field( + organizer: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Organizer"}, ) """The organizer of the event""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TimeZone"}, ) """Time zone of the event""" - series_master_id: Optional[str] = field( + series_master_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SeriesMasterId"}, ) """Unique identifier for Series Master event type""" - categories: Optional[List[str]] = field( + categories: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Categories"}, ) """The categories associated with the event""" - web_link: Optional[str] = field( + web_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebLink"}, ) """The URL to open the event in Outlook Web App""" - required_attendees: Optional[str] = field( + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequiredAttendees"}, ) """Required attendees for the event separated by semicolons""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OptionalAttendees"}, ) """Optional attendees for the event separated by semicolons""" - resource_attendees: Optional[str] = field( + resource_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceAttendees"}, ) """Resource attendees for the event separated by semicolons""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Body of the message associated with the event""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Set to true if the body is Html""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location of the event""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAllDay"}, ) """Set to true if the event lasts all day""" - recurrence_end: Optional[str] = field( + recurrence_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecurrenceEnd"}, ) """End time of the recurrence""" - number_of_occurrences: Optional[int] = field( + number_of_occurrences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfOccurrences"}, ) """How many times to repeat the event""" - reminder: Optional[int] = field( + reminder: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reminder"}, ) """Time in minutes before event start to remind""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseRequested"}, ) """ @@ -540,7 +783,12 @@ class CalendarEventListClientReceive: Response for Get events """ - value: Optional[List[CalendarEventClientReceive]] = None + value: Optional[ + List[CalendarEventClientReceive | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of calendar items""" @@ -550,7 +798,12 @@ class CalendarEventListWithActionType: Response for When an event is added, updated or deleted """ - value: Optional[List[CalendarEventClientWithActionType]] = None + value: Optional[ + List[CalendarEventClientWithActionType | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of calendar items""" @@ -560,7 +813,12 @@ class BatchResponseClientReceiveMessage: Response for Get emails """ - value: Optional[List[ClientReceiveMessage]] = None + value: Optional[ + List[ClientReceiveMessage | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A list of the response objects""" @@ -570,7 +828,12 @@ class EntityListResponseCalendarEventClientReceiveStringEnums: Response for Get calendar view of events """ - value: Optional[List[CalendarEventClientReceiveStringEnums]] = None + value: Optional[ + List[CalendarEventClientReceiveStringEnums | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -580,7 +843,12 @@ class TriggerBatchResponseClientReceiveMessage: Response for When an email is flagged """ - value: Optional[List[ClientReceiveMessage]] = None + value: Optional[ + List[ClientReceiveMessage | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A list of the response objects""" @@ -590,26 +858,30 @@ class TableMetadata: Definition: TableMetadata """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Table name""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Table title""" - x_ms_permission: Optional[str] = field( + x_ms_permission: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-permission"}, ) """Table permission""" - x_ms_capabilities: Optional[TableCapabilitiesMetadata] = field( + x_ms_capabilities: Optional[TableCapabilitiesMetadata | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-capabilities"}, ) - schema: Optional[ObjectEntity] = None - referenced_entities: Optional[ObjectEntity] = field( + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + referenced_entities: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "referencedEntities"}, ) - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webUrl"}, ) """Url link""" @@ -621,30 +893,42 @@ class TableCapabilitiesMetadata: Definition: TableCapabilitiesMetadata """ - sort_restrictions: Optional[TableSortRestrictionsMetadata] = field( + sort_restrictions: Optional[ + TableSortRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sortRestrictions"}, ) - filter_restrictions: Optional[TableFilterRestrictionsMetadata] = field( + filter_restrictions: Optional[ + TableFilterRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterRestrictions"}, ) - select_restrictions: Optional[TableSelectRestrictionsMetadata] = field( + select_restrictions: Optional[ + TableSelectRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selectRestrictions"}, ) - is_only_server_pagable: Optional[bool] = field( + is_only_server_pagable: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isOnlyServerPagable"}, ) """Server paging restrictions""" - filter_function_support: Optional[List[str]] = field( + filter_function_support: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterFunctionSupport"}, ) """List of supported filter capabilities""" - server_paging_options: Optional[List[str]] = field( + server_paging_options: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "serverPagingOptions"}, ) """List of supported server-driven paging capabilities""" @@ -656,7 +940,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -669,15 +953,17 @@ class TableSortRestrictionsMetadata: Definition: TableSortRestrictionsMetadata """ - sortable: Optional[bool] = None + sortable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has sortable columns""" - unsortable_properties: Optional[List[str]] = field( + unsortable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "unsortableProperties"}, ) """List of unsortable properties""" - ascending_only_properties: Optional[List[str]] = field( + ascending_only_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ascendingOnlyProperties"}, ) """List of properties which support ascending order only""" @@ -689,15 +975,17 @@ class TableFilterRestrictionsMetadata: Definition: TableFilterRestrictionsMetadata """ - filterable: Optional[bool] = None + filterable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has filterable columns""" - non_filterable_properties: Optional[List[str]] = field( + non_filterable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nonFilterableProperties"}, ) """List of non filterable properties""" - required_properties: Optional[List[str]] = field( + required_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredProperties"}, ) """List of required properties""" @@ -709,7 +997,7 @@ class TableSelectRestrictionsMetadata: Definition: TableSelectRestrictionsMetadata """ - selectable: Optional[bool] = None + selectable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has selectable columns""" @@ -719,7 +1007,12 @@ class CalendarEventList: Definition: CalendarEventList """ - value: Optional[List[CalendarEventBackend]] = None + value: Optional[ + List[CalendarEventBackend | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of calendar items""" @@ -729,153 +1022,183 @@ class CalendarEventBackend: Definition: CalendarEventBackend """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The Event's unique identifier""" - attendees: Optional[List[Attendee]] = field( + attendees: Optional[List[Attendee | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attendees"}, ) """List of attendees for the event""" - body: Optional[ItemBody] = field( + body: Optional[ItemBody | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Body"}, ) - body_preview: Optional[str] = field( + body_preview: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BodyPreview"}, ) """The preview of the message associated with the event""" - categories: Optional[List[str]] = field( + categories: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Categories"}, ) """The categories associated with the event""" - change_key: Optional[str] = field( + change_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChangeKey"}, ) """ This property identifies the version of the event object. Every time the event is changed, ChangeKey changes as well. """ - date_time_created: Optional[str] = field( + date_time_created: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeCreated"}, ) """The date and time that the event was created""" - date_time_last_modified: Optional[str] = field( + date_time_last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeLastModified"}, ) """The date and time that the event was last modified""" - end: Optional[str] = field(default=None, metadata={"wire_name": "End"}) + end: str = dataclass_field(metadata={"wire_name": "End"}) """The end time of the event""" - end_time_zone: Optional[str] = field( + end_time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EndTimeZone"}, ) """ This property specifies the time zone of the meeting end time. The value must be as defined in Windows (example: 'Pacific Standard Time'). """ - has_attachments: Optional[bool] = field( + has_attachments: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HasAttachments"}, ) """Set to true if the event has attachments""" - i_cal_u_id: Optional[str] = field( + i_cal_u_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ICalUId"}, ) """ A unique identifier that is shared by all instances of an event across different calendars """ - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the event: Low, Normal, or High""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAllDay"}, ) """Set to true if the event lasts all day""" - is_cancelled: Optional[bool] = field( + is_cancelled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsCancelled"}, ) """Set to true if the event has been canceled""" - is_organizer: Optional[bool] = field( + is_organizer: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsOrganizer"}, ) """Set to true if the message sender is also the organizer""" - location: Optional[Location] = field( + location: Optional[Location | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) - organizer: Optional[Recipient] = field( + organizer: Optional[Recipient | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Organizer"}, ) - recurrence: Optional[PatternedRecurrence] = field( + recurrence: Optional[PatternedRecurrence | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Recurrence"}, ) - reminder: Optional[int] = field( + reminder: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reminder"}, ) """Time in minutes before event start to remind""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseRequested"}, ) """ Set to true if the sender would like a response when the event is accepted or declined """ - response_status: Optional[ResponseStatus] = field( + response_status: Optional[ResponseStatus | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseStatus"}, ) - series_master_id: Optional[str] = field( + series_master_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SeriesMasterId"}, ) """Unique identifier for Series Master event type""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowAs"}, ) """Shows as free or busy""" - start: Optional[str] = field(default=None, metadata={"wire_name": "Start"}) + start: str = dataclass_field(metadata={"wire_name": "Start"}) """The start time of the event""" - start_time_zone: Optional[str] = field( + start_time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartTimeZone"}, ) """ This property specifies the time zone of the meeting start time. The value must be as defined in Windows (example: 'Pacific Standard Time'). """ - subject: Optional[str] = field( + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) + """Event subject""" + type_: Optional[str] = dataclass_field( default=None, - metadata={"wire_name": "Subject"}, + kw_only=True, + metadata={"wire_name": "Type"}, ) - """Event subject""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) """ The event type: Single Instance, Occurrence, Exception, or Series Master """ - web_link: Optional[str] = field( + web_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebLink"}, ) """The preview of the message associated with the event""" - reason: Optional[str] = field( + reason: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reason"}, ) """ @@ -890,13 +1213,19 @@ class Attendee: Definition: Attendee """ - status: Optional[ResponseStatus] = field( + status: Optional[ResponseStatus | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Status"}, ) - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) - email_address: Optional[EmailAddress] = field( + type_: Optional[str] = dataclass_field( default=None, + kw_only=True, + metadata={"wire_name": "Type"}, + ) + email_address: Optional[EmailAddress | Mapping[str, Any]] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "EmailAddress"}, ) @@ -907,12 +1236,14 @@ class ItemBody: Definition: ItemBody """ - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentType"}, ) - content: Optional[str] = field( + content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Content"}, ) @@ -923,16 +1254,19 @@ class Location: Definition: Location """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) - address: Optional[PhysicalAddress] = field( + address: Optional[PhysicalAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Address"}, ) - coordinates: Optional[GeoCoordinates] = field( + coordinates: Optional[GeoCoordinates | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Coordinates"}, ) @@ -943,8 +1277,9 @@ class Recipient: Definition: Recipient """ - email_address: Optional[EmailAddress] = field( + email_address: Optional[EmailAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmailAddress"}, ) @@ -955,12 +1290,14 @@ class PatternedRecurrence: Definition: PatternedRecurrence """ - pattern: Optional[RecurrencePattern] = field( + pattern: Optional[RecurrencePattern | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Pattern"}, ) - range: Optional[RecurrenceRange] = field( + range: Optional[RecurrenceRange | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Range"}, ) @@ -971,11 +1308,16 @@ class ResponseStatus: Definition: ResponseStatus """ - response: Optional[str] = field( + response: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Response"}, ) - time: Optional[str] = field(default=None, metadata={"wire_name": "Time"}) + time: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Time"}, + ) @dataclass @@ -984,9 +1326,14 @@ class EmailAddress: Definition: EmailAddress """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) - address: Optional[str] = field( + name: Optional[str] = dataclass_field( default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) + address: Optional[str] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "Address"}, ) @@ -997,18 +1344,29 @@ class PhysicalAddress: Definition: PhysicalAddress """ - street: Optional[str] = field( + street: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Street"}, ) - city: Optional[str] = field(default=None, metadata={"wire_name": "City"}) - state: Optional[str] = field(default=None, metadata={"wire_name": "State"}) - country_or_region: Optional[str] = field( + city: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "City"}, + ) + state: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "State"}, + ) + country_or_region: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CountryOrRegion"}, ) - postal_code: Optional[str] = field( + postal_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PostalCode"}, ) @@ -1019,24 +1377,29 @@ class GeoCoordinates: Definition: GeoCoordinates """ - altitude: Optional[float] = field( + altitude: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Altitude"}, ) - latitude: Optional[float] = field( + latitude: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Latitude"}, ) - longitude: Optional[float] = field( + longitude: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Longitude"}, ) - accuracy: Optional[float] = field( + accuracy: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Accuracy"}, ) - altitude_accuracy: Optional[float] = field( + altitude_accuracy: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AltitudeAccuracy"}, ) @@ -1047,25 +1410,41 @@ class RecurrencePattern: Definition: RecurrencePattern """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) - interval: Optional[int] = field( + type_: Optional[str] = dataclass_field( default=None, + kw_only=True, + metadata={"wire_name": "Type"}, + ) + interval: Optional[int] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "Interval"}, ) - month: Optional[int] = field(default=None, metadata={"wire_name": "Month"}) - day_of_month: Optional[int] = field( + month: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Month"}, + ) + day_of_month: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DayOfMonth"}, ) - days_of_week: Optional[List[str]] = field( + days_of_week: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DaysOfWeek"}, ) - first_day_of_week: Optional[str] = field( + first_day_of_week: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FirstDayOfWeek"}, ) - index: Optional[str] = field(default=None, metadata={"wire_name": "Index"}) + index: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Index"}, + ) @dataclass @@ -1074,17 +1453,24 @@ class RecurrenceRange: Definition: RecurrenceRange """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) - start_date: Optional[str] = field( + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Type"}, + ) + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartDate"}, ) - end_date: Optional[str] = field( + end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EndDate"}, ) - number_of_occurrences: Optional[int] = field( + number_of_occurrences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfOccurrences"}, ) @@ -1095,143 +1481,183 @@ class CalendarEventClientReceive: Definition: CalendarEventClientReceive """ - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Event subject""" - start: Optional[str] = field(default=None, metadata={"wire_name": "Start"}) + start: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Start"}, + ) """Start time of the event (example: '2016-11-01T14:30:00Z')""" - end: Optional[str] = field(default=None, metadata={"wire_name": "End"}) + end: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "End"}, + ) """End time of the event (example: '2016-11-01T15:30:00Z')""" - show_as: Optional[int] = field( + show_as: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowAs"}, ) """ Status to show during the event (Unknown - -1, Free - 0, Tentative - 1, Busy - 2, Oof - 3, WorkingElsewhere - 4) """ - recurrence: Optional[int] = field( + recurrence: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Recurrence"}, ) """ The recurrence pattern for the event (None - 0, Daily - 1, Weekly - 2, Monthly - 3, Yearly - 4) """ - response_type: Optional[int] = field( + response_type: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseType"}, ) """ The response type of the event (None - 0, Organizer - 1, TentativelyAccepted - 2, Accepted - 3, Declined - 4, NotResponded - 5) """ - response_time: Optional[str] = field( + response_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseTime"}, ) """The response time of the event""" - i_cal_u_id: Optional[str] = field( + i_cal_u_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ICalUId"}, ) """ A unique identifier that is shared by all instances of an event across different calendars """ - importance: Optional[int] = field( + importance: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the event (0 - Low, 1 - Normal, 2 - High)""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The event's unique identifier""" - date_time_created: Optional[str] = field( + date_time_created: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeCreated"}, ) """The date and time that the event was created""" - date_time_last_modified: Optional[str] = field( + date_time_last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeLastModified"}, ) """The date and time that the event was last modified""" - organizer: Optional[str] = field( + organizer: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Organizer"}, ) """The organizer of the event""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TimeZone"}, ) """Time zone of the event""" - series_master_id: Optional[str] = field( + series_master_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SeriesMasterId"}, ) """Unique identifier for Series Master event type""" - categories: Optional[List[str]] = field( + categories: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Categories"}, ) """The categories associated with the event""" - web_link: Optional[str] = field( + web_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebLink"}, ) """The URL to open the event in Outlook Web App""" - required_attendees: Optional[str] = field( + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequiredAttendees"}, ) """Required attendees for the event separated by semicolons""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OptionalAttendees"}, ) """Optional attendees for the event separated by semicolons""" - resource_attendees: Optional[str] = field( + resource_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceAttendees"}, ) """Resource attendees for the event separated by semicolons""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Body of the message associated with the event""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Set to true if the body is Html""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location of the event""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAllDay"}, ) """Set to true if the event lasts all day""" - recurrence_end: Optional[str] = field( + recurrence_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecurrenceEnd"}, ) """End time of the recurrence""" - number_of_occurrences: Optional[int] = field( + number_of_occurrences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfOccurrences"}, ) """How many times to repeat the event""" - reminder: Optional[int] = field( + reminder: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reminder"}, ) """Time in minutes before event start to remind""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseRequested"}, ) """ @@ -1246,8 +1672,11 @@ class PaginatedListResponseCalendarEventClientReceiveStringEnums: Definition: PaginatedListResponse[CalendarEventClientReceiveStringEnums] """ - values: Optional[List[CalendarEventClientReceiveStringEnums]] = field( + values: Optional[ + List[CalendarEventClientReceiveStringEnums | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Values"}, ) """Values""" @@ -1259,8 +1688,7 @@ class ClientSubscription: Definition: ClientSubscription """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "NotificationUrl"}, ) """ @@ -1275,7 +1703,12 @@ class EntityListResponseFilePickerFile: Definition: EntityListResponse[FilePickerFile] """ - value: Optional[List[FilePickerFile]] = None + value: Optional[ + List[FilePickerFile | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -1285,19 +1718,29 @@ class FilePickerFile: Definition: FilePickerFile """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Uniquely identifies the file""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Display name for the file""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """Set to true if the file is a folder""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """Path of the file""" @@ -1307,42 +1750,51 @@ class ClientSendMessage: Definition: ClientSendMessage """ - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """ Specify email addresses separated by semicolons like someone@contoso.com """ - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """ Specify email addresses separated by semicolons like someone@contoso.com """ - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: str = dataclass_field(metadata={"wire_name": "To"}) """ Specify email addresses separated by semicolons like someone@contoso.com """ - subject: Optional[str] = field( - default=None, - metadata={"wire_name": "Subject"}, - ) + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) """Specify the subject of the mail""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: str = dataclass_field(metadata={"wire_name": "Body"}) """Specify the body of the mail""" - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Attachments""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """The email addresses to use when replying""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Importance""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Is Html?""" @@ -1354,10 +1806,9 @@ class ClientSendAttachment: Definition: ClientSendAttachment """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: str = dataclass_field(metadata={"wire_name": "Name"}) """Attachment name""" - content_bytes: Optional[str] = field( - default=None, + content_bytes: str = dataclass_field( metadata={"wire_name": "ContentBytes"}, ) """Attachment content""" @@ -1369,34 +1820,51 @@ class ClientReceiveFileAttachment: Definition: ClientReceiveFileAttachment """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Attachment Id""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Attachment name""" - content_bytes: Optional[str] = field( + content_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentBytes"}, ) """Attachment content""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentType"}, ) """Attachment content type""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size in bytes of the attachment""" - is_inline: Optional[bool] = field( + is_inline: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsInline"}, ) """Set to true if this is an inline attachment""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModifiedDateTime"}, ) """The date and time when the attachment was last modified""" - content_id: Optional[str] = field( + content_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentId"}, ) """Content Id""" @@ -1408,44 +1876,56 @@ class ClientSendHtmlMessage: Definition: ClientSendHtmlMessage """ - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: str = dataclass_field(metadata={"wire_name": "To"}) """ Specify email addresses separated by semicolons like someone@contoso.com """ - subject: Optional[str] = field( - default=None, - metadata={"wire_name": "Subject"}, - ) + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) """Specify the subject of the mail""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: str = dataclass_field(metadata={"wire_name": "Body"}) """Specify the body of the mail""" - from_: Optional[str] = field(default=None, metadata={"wire_name": "From"}) + from_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "From"}, + ) """ Email address to send mail from (requires \"Send as\" or \"Send on behalf of\" permission for that mailbox). For more info on granting permissions please refer https://docs.microsoft.com/office365/admin/manage/send-email-as-distribution-list """ - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """ Specify email addresses separated by semicolons like someone@contoso.com """ - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """ Specify email addresses separated by semicolons like someone@contoso.com """ - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Attachments""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """The email addresses to use when replying""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Importance""" @@ -1457,36 +1937,57 @@ class ReplyMessage: Definition: ReplyMessage """ - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "To"}, + ) """Example: recipient1@domain.com; recipient2@domain.com""" - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """Example: recipient1@domain.com; recipient2@domain.com""" - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """Example: recipient1@domain.com; recipient2@domain.com""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Email subject (if empty, the original subject used).""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Content of the email.""" - reply_all: Optional[bool] = field( + reply_all: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyAll"}, ) """True to reply to all recipients. (default: False)""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """True to send the reply as HTML. (default: True)""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Pick an importance. (default: Low)""" - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Details of attachments to be sent along with the reply.""" @@ -1498,31 +1999,51 @@ class ReplyHtmlMessage: Definition: ReplyHtmlMessage """ - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "To"}, + ) """Example: recipient1@domain.com; recipient2@domain.com""" - cc: Optional[str] = field(default=None, metadata={"wire_name": "Cc"}) + cc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cc"}, + ) """Example: recipient1@domain.com; recipient2@domain.com""" - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """Example: recipient1@domain.com; recipient2@domain.com""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Email subject (if empty, the original subject used).""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Content of the email.""" - reply_all: Optional[bool] = field( + reply_all: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyAll"}, ) """True to reply to all recipients. (default: False)""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Pick an importance. (default: Low)""" - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Details of attachments to be sent along with the reply.""" @@ -1534,8 +2055,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1544,25 +2075,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -1574,15 +2109,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -1594,15 +2131,13 @@ class OptionsEmailSubscription: Definition: OptionsEmailSubscription """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "NotificationUrl"}, ) """ Gets or sets callback url to flow engine. It is expected as part of request """ - message: Optional[MessageWithOptions] = field( - default=None, + message: MessageWithOptions | Mapping[str, Any] = dataclass_field( metadata={"wire_name": "Message"}, ) @@ -1613,49 +2148,61 @@ class MessageWithOptions: Definition: MessageWithOptions """ - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: str = dataclass_field(metadata={"wire_name": "To"}) """ Specify email addresses separated by semicolons like someone@contoso.com """ - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Subject of the email""" - options: Optional[str] = field( + options: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Options"}, ) """List of comma separated options for the email response""" - header_text: Optional[str] = field( + header_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HeaderText"}, ) """Header text for email body""" - selection_text: Optional[str] = field( + selection_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SelectionText"}, ) """Header text for users options selection""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Body of the email""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Importance""" - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Attachments""" - use_only_h_t_m_l_message: Optional[bool] = field( + use_only_h_t_m_l_message: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UseOnlyHTMLMessage"}, ) """Use only HTML message""" - hide_h_t_m_l_message: Optional[bool] = field( + hide_h_t_m_l_message: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HideHTMLMessage"}, ) """ @@ -1663,8 +2210,9 @@ class MessageWithOptions: displayed. Email clients which do not support actionable messages will display HTML message regardless of the parameter value. """ - show_h_t_m_l_confirmation_dialog: Optional[bool] = field( + show_h_t_m_l_confirmation_dialog: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowHTMLConfirmationDialog"}, ) """ @@ -1679,8 +2227,9 @@ class ApprovalEmailResponse: Definition: ApprovalEmailResponse """ - selected_option: Optional[str] = field( + selected_option: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SelectedOption"}, ) """User response""" @@ -1692,15 +2241,13 @@ class ApprovalEmailSubscription: Definition: ApprovalEmailSubscription """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "NotificationUrl"}, ) """ Gets or sets callback url to flow engine. It is expected as part of request """ - message: Optional[ApprovalMessage] = field( - default=None, + message: ApprovalMessage | Mapping[str, Any] = dataclass_field( metadata={"wire_name": "Message"}, ) @@ -1711,49 +2258,61 @@ class ApprovalMessage: Definition: ApprovalMessage """ - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: str = dataclass_field(metadata={"wire_name": "To"}) """ Specify email addresses separated by semicolons like someone@contoso.com """ - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Subject""" - options: Optional[str] = field( + options: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Options"}, ) """User Options""" - header_text: Optional[str] = field( + header_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HeaderText"}, ) """Header text for email body""" - selection_text: Optional[str] = field( + selection_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SelectionText"}, ) """Header text for users options selection""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Body""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Importance""" - attachments: Optional[List[ClientSendAttachment]] = field( + attachments: Optional[List[ClientSendAttachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Attachments""" - use_only_h_t_m_l_message: Optional[bool] = field( + use_only_h_t_m_l_message: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UseOnlyHTMLMessage"}, ) """Use only HTML message""" - hide_h_t_m_l_message: Optional[bool] = field( + hide_h_t_m_l_message: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HideHTMLMessage"}, ) """ @@ -1761,8 +2320,9 @@ class ApprovalMessage: displayed. Email clients which do not support actionable messages will display HTML message regardless of the parameter value. """ - show_h_t_m_l_confirmation_dialog: Optional[bool] = field( + show_h_t_m_l_confirmation_dialog: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowHTMLConfirmationDialog"}, ) """ @@ -1777,7 +2337,12 @@ class SubscriptionPayloadOutlookReceiveMessage: Definition: SubscriptionPayload[OutlookReceiveMessage] """ - value: Optional[List[SubscriptionPayloadEntityOutlookReceiveMessage]] = None + value: Optional[ + List[SubscriptionPayloadEntityOutlookReceiveMessage | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -1787,28 +2352,33 @@ class SubscriptionPayloadEntityOutlookReceiveMessage: Definition: SubscriptionPayloadEntity[OutlookReceiveMessage] """ - sequence_number: Optional[int] = field( + sequence_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SequenceNumber"}, ) """Sequence number""" - change_type: Optional[str] = field( + change_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChangeType"}, ) """Change type""" - client_state: Optional[str] = field( + client_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClientState"}, ) """Client state""" - resource: Optional[str] = field( + resource: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Resource"}, ) """Resource""" - resource_data: Optional[OutlookReceiveMessage] = field( + resource_data: Optional[OutlookReceiveMessage | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceData"}, ) @@ -1819,93 +2389,119 @@ class OutlookReceiveMessage: Definition: OutlookReceiveMessage """ - internet_message_id: Optional[str] = field( + internet_message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InternetMessageId"}, ) """Internet Message Id""" - body_preview: Optional[str] = field( + body_preview: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BodyPreview"}, ) """Body preview""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Id""" - conversation_id: Optional[str] = field( + conversation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ConversationId"}, ) """Conversation Id""" - has_attachments: Optional[bool] = field( + has_attachments: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HasAttachments"}, ) """Has attachments""" - is_read: Optional[bool] = field( + is_read: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsRead"}, ) """Is read""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CreatedDateTime"}, ) """Created date and time""" - received_date_time: Optional[str] = field( + received_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDateTime"}, ) """Received date and time""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModifiedDateTime"}, ) """Last modified date and time""" - attachments: Optional[List[OutlookReceiveAttachment]] = field( + attachments: Optional[ + List[OutlookReceiveAttachment | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Attachments""" - to_recipients: Optional[List[Recipient]] = field( + to_recipients: Optional[List[Recipient | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ToRecipients"}, ) """To Recipient""" - cc_recipients: Optional[List[Recipient]] = field( + cc_recipients: Optional[List[Recipient | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CcRecipients"}, ) """Cc Recipients""" - bcc_recipients: Optional[List[Recipient]] = field( + bcc_recipients: Optional[List[Recipient | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BccRecipients"}, ) """Bcc Recipients""" - reply_to: Optional[List[Recipient]] = field( + reply_to: Optional[List[Recipient | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """The email addresses to use when replying""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Subject""" - body: Optional[ItemBody] = field( + body: Optional[ItemBody | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Body"}, ) - from_: Optional[Recipient] = field( + from_: Optional[Recipient | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "From"}, ) - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Importance""" - internet_message_headers: Optional[List[InternetMessageHeader]] = field( + internet_message_headers: Optional[ + List[InternetMessageHeader | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InternetMessageHeaders"}, ) """Internet message headers""" @@ -1917,54 +2513,75 @@ class OutlookReceiveAttachment: Definition: OutlookReceiveAttachment """ - type_: Optional[str] = field( + type_: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.type"}, ) """OData type""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Attachment Id""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Attachment name""" - content_bytes: Optional[str] = field( + content_bytes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentBytes"}, ) """Attachment content""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentType"}, ) """Attachment content type""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """Attachment size in bytes""" - permission: Optional[str] = field( + permission: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Permission"}, ) """Permission associated with a reference attachment""" - provider_type: Optional[str] = field( + provider_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ProviderType"}, ) """Provider for the reference attachment""" - source_url: Optional[str] = field( + source_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SourceUrl"}, ) """Reference attachment source url""" - is_inline: Optional[bool] = field( + is_inline: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsInline"}, ) """Set to true if this is an inline attachment""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModifiedDateTime"}, ) """The date and time when the attachment was last modified""" - content_id: Optional[str] = field( + content_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentId"}, ) """Content Id""" @@ -1976,9 +2593,17 @@ class InternetMessageHeader: Definition: InternetMessageHeader """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Header name""" - value: Optional[str] = field(default=None, metadata={"wire_name": "Value"}) + value: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Value"}, + ) """Header value""" @@ -1988,7 +2613,12 @@ class SubscriptionPayloadSubscriptionEvent: Definition: SubscriptionPayload[SubscriptionEvent] """ - value: Optional[List[SubscriptionPayloadEntitySubscriptionEvent]] = None + value: Optional[ + List[SubscriptionPayloadEntitySubscriptionEvent | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -1998,28 +2628,33 @@ class SubscriptionPayloadEntitySubscriptionEvent: Definition: SubscriptionPayloadEntity[SubscriptionEvent] """ - sequence_number: Optional[int] = field( + sequence_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SequenceNumber"}, ) """Sequence number""" - change_type: Optional[str] = field( + change_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChangeType"}, ) """Change type""" - client_state: Optional[str] = field( + client_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClientState"}, ) """Client state""" - resource: Optional[str] = field( + resource: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Resource"}, ) """Resource""" - resource_data: Optional[SubscriptionEvent] = field( + resource_data: Optional[SubscriptionEvent | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceData"}, ) @@ -2030,7 +2665,11 @@ class SubscriptionEvent: Definition: SubscriptionEvent """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The Event's unique identifier""" @@ -2040,15 +2679,21 @@ class Table: Definition: Table """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the table. The name is used at runtime.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the table.""" - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DynamicProperties"}, ) """Additional table properties provided by the connector to the clients.""" @@ -2060,7 +2705,12 @@ class EntityListResponseCalendarEventBackend: Definition: EntityListResponse[CalendarEventBackend] """ - value: Optional[List[CalendarEventBackend]] = None + value: Optional[ + List[CalendarEventBackend | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -2070,84 +2720,99 @@ class CalendarEventClient: Definition: CalendarEventClient """ - subject: Optional[str] = field( - default=None, - metadata={"wire_name": "Subject"}, - ) + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) """Event subject""" - start: Optional[str] = field(default=None, metadata={"wire_name": "Start"}) + start: str = dataclass_field(metadata={"wire_name": "Start"}) """Start time of the event (example: '2016-11-01T14:30:00Z')""" - end: Optional[str] = field(default=None, metadata={"wire_name": "End"}) + end: str = dataclass_field(metadata={"wire_name": "End"}) """End time of the event (example: '2016-11-01T15:30:00Z')""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TimeZone"}, ) """Time zone of the event""" - required_attendees: Optional[str] = field( + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequiredAttendees"}, ) """Required attendees for the event separated by semicolons""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OptionalAttendees"}, ) """Optional attendees for the event separated by semicolons""" - resource_attendees: Optional[str] = field( + resource_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceAttendees"}, ) """Resource attendees for the event separated by semicolons""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Body of the message associated with the event""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Set to true if the body is Html""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location of the event""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the event: Low, Normal, or High""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAllDay"}, ) """Set to true if the event lasts all day""" - recurrence: Optional[str] = field( + recurrence: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Recurrence"}, ) """The recurrence pattern for the event""" - recurrence_end: Optional[str] = field( + recurrence_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecurrenceEnd"}, ) """End time of the recurrence""" - number_of_occurrences: Optional[int] = field( + number_of_occurrences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfOccurrences"}, ) """How many times to repeat the event""" - reminder: Optional[int] = field( + reminder: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reminder"}, ) """Time in minutes before event start to remind""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowAs"}, ) """Status to show during the event""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseRequested"}, ) """ @@ -2162,79 +2827,93 @@ class CalendarEventHtmlClient: Definition: CalendarEventHtmlClient """ - subject: Optional[str] = field( - default=None, - metadata={"wire_name": "Subject"}, - ) + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) """Event subject""" - start: Optional[str] = field(default=None, metadata={"wire_name": "Start"}) + start: str = dataclass_field(metadata={"wire_name": "Start"}) """Start time of the event (example: '2016-11-01T14:30:00Z')""" - end: Optional[str] = field(default=None, metadata={"wire_name": "End"}) + end: str = dataclass_field(metadata={"wire_name": "End"}) """End time of the event (example: '2016-11-01T15:30:00Z')""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TimeZone"}, ) """Time zone of the event""" - required_attendees: Optional[str] = field( + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequiredAttendees"}, ) """Required attendees for the event separated by semicolons""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OptionalAttendees"}, ) """Optional attendees for the event separated by semicolons""" - resource_attendees: Optional[str] = field( + resource_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceAttendees"}, ) """Resource attendees for the event separated by semicolons""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Body of the message associated with the event""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location of the event""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the event: Low, Normal, or High""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAllDay"}, ) """Set to true if the event lasts all day""" - recurrence: Optional[str] = field( + recurrence: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Recurrence"}, ) """The recurrence pattern for the event""" - recurrence_end: Optional[str] = field( + recurrence_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecurrenceEnd"}, ) """End time of the recurrence""" - number_of_occurrences: Optional[int] = field( + number_of_occurrences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfOccurrences"}, ) """How many times to repeat the event""" - reminder: Optional[int] = field( + reminder: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reminder"}, ) """Time in minutes before event start to remind""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowAs"}, ) """Status to show during the event""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseRequested"}, ) """ @@ -2249,164 +2928,207 @@ class CalendarEventClientWithActionType: Definition: CalendarEventClientWithActionType """ - action_type: Optional[str] = field( + action_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ActionType"}, ) """Changed action type of the event - added, updated or deleted.""" - is_added: Optional[bool] = field( + is_added: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAdded"}, ) """ Flag that indicates whether the event was added since the last poll of the trigger. """ - is_updated: Optional[bool] = field( + is_updated: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsUpdated"}, ) """ Flag that indicates whether the event was updated since the last poll of the trigger. """ - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Event subject""" - start: Optional[str] = field(default=None, metadata={"wire_name": "Start"}) + start: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Start"}, + ) """Start time of the event (example: '2016-11-01T14:30:00Z')""" - end: Optional[str] = field(default=None, metadata={"wire_name": "End"}) + end: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "End"}, + ) """End time of the event (example: '2016-11-01T15:30:00Z')""" - show_as: Optional[int] = field( + show_as: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ShowAs"}, ) """ Status to show during the event (Unknown - -1, Free - 0, Tentative - 1, Busy - 2, Oof - 3, WorkingElsewhere - 4) """ - recurrence: Optional[int] = field( + recurrence: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Recurrence"}, ) """ The recurrence pattern for the event (None - 0, Daily - 1, Weekly - 2, Monthly - 3, Yearly - 4) """ - response_type: Optional[int] = field( + response_type: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseType"}, ) """ The response type of the event (None - 0, Organizer - 1, TentativelyAccepted - 2, Accepted - 3, Declined - 4, NotResponded - 5) """ - response_time: Optional[str] = field( + response_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseTime"}, ) """The response time of the event""" - i_cal_u_id: Optional[str] = field( + i_cal_u_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ICalUId"}, ) """ A unique identifier that is shared by all instances of an event across different calendars """ - importance: Optional[int] = field( + importance: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """The importance of the event (0 - Low, 1 - Normal, 2 - High)""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The event's unique identifier""" - date_time_created: Optional[str] = field( + date_time_created: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeCreated"}, ) """The date and time that the event was created""" - date_time_last_modified: Optional[str] = field( + date_time_last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeLastModified"}, ) """The date and time that the event was last modified""" - organizer: Optional[str] = field( + organizer: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Organizer"}, ) """The organizer of the event""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TimeZone"}, ) """Time zone of the event""" - series_master_id: Optional[str] = field( + series_master_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SeriesMasterId"}, ) """Unique identifier for Series Master event type""" - categories: Optional[List[str]] = field( + categories: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Categories"}, ) """The categories associated with the event""" - web_link: Optional[str] = field( + web_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebLink"}, ) """The URL to open the event in Outlook Web App""" - required_attendees: Optional[str] = field( + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequiredAttendees"}, ) """Required attendees for the event separated by semicolons""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OptionalAttendees"}, ) """Optional attendees for the event separated by semicolons""" - resource_attendees: Optional[str] = field( + resource_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResourceAttendees"}, ) """Resource attendees for the event separated by semicolons""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Body of the message associated with the event""" - is_html: Optional[bool] = field( + is_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsHtml"}, ) """Set to true if the body is Html""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location of the event""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsAllDay"}, ) """Set to true if the event lasts all day""" - recurrence_end: Optional[str] = field( + recurrence_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecurrenceEnd"}, ) """End time of the recurrence""" - number_of_occurrences: Optional[int] = field( + number_of_occurrences: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfOccurrences"}, ) """How many times to repeat the event""" - reminder: Optional[int] = field( + reminder: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reminder"}, ) """Time in minutes before event start to remind""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResponseRequested"}, ) """ @@ -2421,169 +3143,204 @@ class Contact: Definition: Contact """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The contact's unique identifier.""" - parent_folder_id: Optional[str] = field( + parent_folder_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ParentFolderId"}, ) """The ID of the contact's parent folder""" - birthday: Optional[str] = field( + birthday: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Birthday"}, ) """The contact's birthday""" - file_as: Optional[str] = field( + file_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileAs"}, ) """The name the contact is filed under""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The contact's display name""" - given_name: Optional[str] = field( - default=None, - metadata={"wire_name": "GivenName"}, - ) + given_name: str = dataclass_field(metadata={"wire_name": "GivenName"}) """The contact's given name""" - initials: Optional[str] = field( + initials: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Initials"}, ) """The contact's initials""" - middle_name: Optional[str] = field( + middle_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MiddleName"}, ) """The contact's middle name""" - nick_name: Optional[str] = field( + nick_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NickName"}, ) """The contact's nickname""" - surname: Optional[str] = field( + surname: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Surname"}, ) """The contact's surname""" - title: Optional[str] = field(default=None, metadata={"wire_name": "Title"}) + title: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Title"}, + ) """The contact's title""" - generation: Optional[str] = field( + generation: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Generation"}, ) """The contact's generation""" - email_addresses: Optional[List[EmailAddress]] = field( + email_addresses: Optional[List[EmailAddress | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmailAddresses"}, ) """The contact's email addresses""" - im_addresses: Optional[List[str]] = field( + im_addresses: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImAddresses"}, ) """The contact's instant messaging (IM) addresses""" - job_title: Optional[str] = field( + job_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JobTitle"}, ) """The contact's job title""" - company_name: Optional[str] = field( + company_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CompanyName"}, ) """The name of the contact's company""" - department: Optional[str] = field( + department: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Department"}, ) """The contact's department""" - office_location: Optional[str] = field( + office_location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfficeLocation"}, ) """The location of the contact's office""" - profession: Optional[str] = field( + profession: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Profession"}, ) """The contact's profession""" - business_home_page: Optional[str] = field( + business_home_page: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BusinessHomePage"}, ) """The business home page of the contact""" - assistant_name: Optional[str] = field( + assistant_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AssistantName"}, ) """The name of the contact's assistant""" - manager: Optional[str] = field( + manager: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Manager"}, ) """The name of the contact's manager""" - home_phones: Optional[List[str]] = field( - default=None, + home_phones: List[str] = dataclass_field( metadata={"wire_name": "HomePhones"}, ) """The contact's home phone numbers""" - business_phones: Optional[List[str]] = field( + business_phones: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BusinessPhones"}, ) """The contact's business phone numbers""" - mobile_phone1: Optional[str] = field( + mobile_phone1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MobilePhone1"}, ) """The contact's mobile phone number""" - home_address: Optional[PhysicalAddress] = field( + home_address: Optional[PhysicalAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HomeAddress"}, ) - business_address: Optional[PhysicalAddress] = field( + business_address: Optional[PhysicalAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BusinessAddress"}, ) - other_address: Optional[PhysicalAddress] = field( + other_address: Optional[PhysicalAddress | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OtherAddress"}, ) - yomi_company_name: Optional[str] = field( + yomi_company_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "YomiCompanyName"}, ) """The phonetic Japanese company name of the contact""" - yomi_given_name: Optional[str] = field( + yomi_given_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "YomiGivenName"}, ) """The phonetic Japanese given name (first name) of the contact""" - yomi_surname: Optional[str] = field( + yomi_surname: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "YomiSurname"}, ) """The phonetic Japanese surname (last name) of the contact""" - categories: Optional[List[str]] = field( + categories: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Categories"}, ) """The categories associated with the contact""" - change_key: Optional[str] = field( + change_key: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChangeKey"}, ) """Identifies the version of the event object""" - date_time_created: Optional[str] = field( + date_time_created: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeCreated"}, ) """The time the contact was created""" - date_time_last_modified: Optional[str] = field( + date_time_last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateTimeLastModified"}, ) """The time the contact was modified""" @@ -2595,7 +3352,12 @@ class DataSetsList: Definition: DataSetsList """ - value: Optional[List[DataSet]] = None + value: Optional[ + List[DataSet | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of datasets""" @@ -2605,14 +3367,24 @@ class DataSet: Definition: DataSet """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Dataset name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Dataset display name""" - query: Optional[List[PassThroughNativeQuery]] = None + query: Optional[ + List[PassThroughNativeQuery | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Pass-through Native Queries""" @@ -2622,10 +3394,15 @@ class Procedure: Definition: Procedure """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Procedure name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Procedure display name""" @@ -2637,8 +3414,9 @@ class PassThroughNativeQuery: Definition: PassThroughNativeQuery """ - language: Optional[str] = field( + language: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Language"}, ) """Query language""" @@ -2650,13 +3428,15 @@ class ResponseToEventInvite: Definition: ResponseToEventInvite """ - comment: Optional[str] = field( + comment: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comment"}, ) """Comment""" - send_response: Optional[bool] = field( + send_response: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SendResponse"}, ) """Send response to organizer?""" @@ -2668,13 +3448,13 @@ class DirectForwardMessage: Definition: DirectForwardMessage """ - comment: Optional[str] = field( + comment: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comment"}, ) """Comment""" - to_recipients: Optional[str] = field( - default=None, + to_recipients: str = dataclass_field( metadata={"wire_name": "ToRecipients"}, ) """Semicolon separated list of recipients to forward the message to""" @@ -2688,16 +3468,16 @@ class OutlookClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -2708,8 +3488,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -2717,8 +3497,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -2730,7 +3510,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -2745,12 +3525,51 @@ def __init__( def connector_name(self) -> str: return "outlook" - async def get_email_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def get_email( self, message_id: str, + *, include_attachments: Optional[bool] = None, internet_message_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2760,6 +3579,24 @@ async def get_email_async( Get email This operation gets an email by id. + + Swagger operation ID: `GetEmail`. + + Args: + message_id: Id of the email. + include_attachments: If set to true, attachments content will also + be retrieved along with the email. + internet_message_id: Internet Message Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2779,7 +3616,7 @@ async def get_email_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2793,6 +3630,7 @@ async def get_email_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2800,7 +3638,7 @@ async def get_email_async( return json.loads(response.text) - async def delete_email_async( + def delete_email( self, message_id: str, *, @@ -2813,13 +3651,28 @@ async def delete_email_async( Delete email This operation deletes an email by id. + + Swagger operation ID: `DeleteEmail`. + + Args: + message_id: Id of the email to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/Mail/{quote(str(message_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2833,9 +3686,10 @@ async def delete_email_async( request_url, response.status, response.text, + response=response, ) - async def move_async( + def move( self, message_id: str, folder_path: str, @@ -2849,6 +3703,22 @@ async def move_async( Move email This operation moves an email to the specified folder. + + Swagger operation ID: `Move`. + + Args: + message_id: Id of the email to be moved. + folder_path: Mail folder to move the email to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2862,7 +3732,7 @@ async def move_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -2876,6 +3746,7 @@ async def move_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2883,7 +3754,7 @@ async def move_async( return json.loads(response.text) - async def flag_async( + def flag( self, message_id: str, *, @@ -2896,13 +3767,28 @@ async def flag_async( Flag email This operation flags an email. + + Swagger operation ID: `Flag`. + + Args: + message_id: Id of the email to be flagged. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/Mail/Flag/{quote(str(message_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -2916,9 +3802,10 @@ async def flag_async( request_url, response.status, response.text, + response=response, ) - async def mark_as_read_async( + def mark_as_read( self, message_id: str, *, @@ -2931,13 +3818,28 @@ async def mark_as_read_async( Mark as read This operation marks an email as having been read. + + Swagger operation ID: `MarkAsRead`. + + Args: + message_id: Id of the email to be marked as read. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/Mail/MarkAsRead/{quote(str(message_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -2951,9 +3853,10 @@ async def mark_as_read_async( request_url, response.status, response.text, + response=response, ) - async def get_attachment_async( + def get_attachment( self, message_id: str, attachment_id: str, @@ -2967,6 +3870,22 @@ async def get_attachment_async( Get attachment This operation gets an email attachment by id. + + Swagger operation ID: `GetAttachment`. + + Args: + message_id: Id of the email. + attachment_id: Id of the attachment to download. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2976,7 +3895,7 @@ async def get_attachment_async( f"/{quote(str(attachment_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2990,13 +3909,14 @@ async def get_attachment_async( request_url, response.status, response.text, + response=response, ) return response.content - async def send_mail_with_options_async( + def send_mail_with_options( self, - input: OptionsEmailSubscription, + input: OptionsEmailSubscription | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -3011,12 +3931,28 @@ async def send_mail_with_options_async( following link regarding the support of actionable messages in different mail clients: https://docs.microsoft.com/outlook/actionable-messages/#outlook-version-requirements-for-actionable-messages. + + Swagger operation ID: `SendMailWithOptions`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/mailwithoptions/$subscriptions" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3030,6 +3966,7 @@ async def send_mail_with_options_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3037,9 +3974,9 @@ async def send_mail_with_options_async( return json.loads(response.text) - async def send_approval_mail_async( + def send_approval_mail( self, - input: ApprovalEmailSubscription, + input: ApprovalEmailSubscription | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -3053,12 +3990,28 @@ async def send_approval_mail_async( the recipient. Please refer to the following link regarding the support of actionable messages in different mail clients: https://docs.microsoft.com/outlook/actionable-messages/#outlook-version-requirements-for-actionable-messages. + + Swagger operation ID: `SendApprovalMail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/approvalmail/$subscriptions" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3072,6 +4025,7 @@ async def send_approval_mail_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3079,45 +4033,84 @@ async def send_approval_mail_async( return json.loads(response.text) - async def calendar_get_tables_async( + def list_calendar_get_tables( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get calendars This operation lists available calendars. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `CalendarGetTables`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/calendars/tables" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def calendar_delete_item_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def calendar_delete_item( self, table: str, id: str, @@ -3131,6 +4124,22 @@ async def calendar_delete_item_async( Delete event This operation deletes an event in a calendar. + + Swagger operation ID: `CalendarDeleteItem`. + + Args: + table: Select a calendar. + id: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3142,7 +4151,7 @@ async def calendar_delete_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -3156,63 +4165,128 @@ async def calendar_delete_item_async( request_url, response.status, response.text, + response=response, ) - async def contact_get_tables_async( + def list_contact_get_tables( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get contact folders This operation lists available contacts folders. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ContactGetTables`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/contacts/tables" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def contact_get_items_async( + def list_contact_get_items( self, table: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get contacts This operation gets contacts from a contacts folder. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ContactGetItems`. + + Args: + table: Unique identifier of the contacts folder to retrieve. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3245,31 +4319,52 @@ async def contact_get_items_async( query_params.append(f"$skip={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def contact_post_item_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def contact_post_item( self, - input: Contact, + input: Contact | Mapping[str, Any], table: str, *, timeout: Optional[float] = None, @@ -3281,6 +4376,23 @@ async def contact_post_item_async( Create contact This operation creates a new contact in a contacts folder. + + Swagger operation ID: `ContactPostItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Select a contacts folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3291,7 +4403,7 @@ async def contact_post_item_async( f"/items" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3305,6 +4417,7 @@ async def contact_post_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3312,7 +4425,7 @@ async def contact_post_item_async( return json.loads(response.text) - async def contact_get_item_async( + def contact_get_item( self, table: str, id: str, @@ -3326,6 +4439,22 @@ async def contact_get_item_async( Get contact This operation gets a specific contact from a contacts folder. + + Swagger operation ID: `ContactGetItem`. + + Args: + table: Select a contacts folder. + id: Unique identifier of a contact to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3337,7 +4466,7 @@ async def contact_get_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3351,6 +4480,7 @@ async def contact_get_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3358,7 +4488,7 @@ async def contact_get_item_async( return json.loads(response.text) - async def contact_delete_item_async( + def contact_delete_item( self, table: str, id: str, @@ -3372,6 +4502,22 @@ async def contact_delete_item_async( Delete contact This operation deletes a contact from a contacts folder. + + Swagger operation ID: `ContactDeleteItem`. + + Args: + table: Select a contacts folder. + id: Unique identifier of contact to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3383,7 +4529,7 @@ async def contact_delete_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -3397,11 +4543,12 @@ async def contact_delete_item_async( request_url, response.status, response.text, + response=response, ) - async def contact_patch_item_async( + def contact_patch_item( self, - input: Contact, + input: Contact | Mapping[str, Any], table: str, id: str, *, @@ -3414,6 +4561,24 @@ async def contact_patch_item_async( Update contact This operation updates a contact in a contacts folder. + + Swagger operation ID: `ContactPatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Select a contacts folder. + id: Unique identifier of contact to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3425,7 +4590,7 @@ async def contact_patch_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -3439,6 +4604,7 @@ async def contact_patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3446,9 +4612,9 @@ async def contact_patch_item_async( return json.loads(response.text) - async def respond_to_event_async( + def respond_to_event( self, - input: ResponseToEventInvite, + input: ResponseToEventInvite | Mapping[str, Any], event_id: str, response: str, *, @@ -3461,6 +4627,24 @@ async def respond_to_event_async( Respond to an event invite Respond to an event invite. + + Swagger operation ID: `RespondToEvent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + event_id: Id of the event to respond to. + response: Response for the event invite. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3473,7 +4657,7 @@ async def respond_to_event_async( f"/{quote(str(response), safe='')}" ) - http_response = await self.http_client.send_async( + http_response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3487,11 +4671,12 @@ async def respond_to_event_async( request_url, http_response.status, http_response.text, + response=http_response, ) - async def forward_email_async( + def forward_email( self, - input: DirectForwardMessage, + input: DirectForwardMessage | Mapping[str, Any], message_id: str, *, timeout: Optional[float] = None, @@ -3503,6 +4688,23 @@ async def forward_email_async( Forward an email Forward an email. + + Swagger operation ID: `ForwardEmail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Id of the message to forward. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3515,7 +4717,7 @@ async def forward_email_async( f"/forward" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3529,9 +4731,10 @@ async def forward_email_async( request_url, response.status, response.text, + response=response, ) - async def calendar_get_item_async( + def calendar_get_item( self, table: str, id: str, @@ -3545,6 +4748,22 @@ async def calendar_get_item_async( Get event This operation gets a specific event from a calendar. + + Swagger operation ID: `V2CalendarGetItem`. + + Args: + table: Select a calendar. + id: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3557,7 +4776,7 @@ async def calendar_get_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3571,6 +4790,7 @@ async def calendar_get_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3578,23 +4798,48 @@ async def calendar_get_item_async( return json.loads(response.text) - async def calendar_get_items_async( + def list_calendar_get_items( self, table: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get events This operation gets events from a calendar. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `V3CalendarGetItems`. + + Args: + table: Select a calendar. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3628,31 +4873,52 @@ async def calendar_get_items_async( query_params.append(f"$skip={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def calendar_patch_item_async( + def calendar_patch_item( self, - input: CalendarEventHtmlClient, + input: CalendarEventHtmlClient | Mapping[str, Any], table: str, id: str, *, @@ -3665,6 +4931,24 @@ async def calendar_patch_item_async( Update event This operation updates an event in a calendar. + + Swagger operation ID: `V3CalendarPatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Select a calendar. + id: Select an event. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3677,7 +4961,7 @@ async def calendar_patch_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -3691,6 +4975,7 @@ async def calendar_patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3698,9 +4983,9 @@ async def calendar_patch_item_async( return json.loads(response.text) - async def calendar_post_item_async( + def calendar_post_item( self, - input: CalendarEventHtmlClient, + input: CalendarEventHtmlClient | Mapping[str, Any], table: str, *, timeout: Optional[float] = None, @@ -3712,6 +4997,23 @@ async def calendar_post_item_async( Create event This operation creates a new event in a calendar. + + Swagger operation ID: `V3CalendarPostItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Select a calendar. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3723,7 +5025,7 @@ async def calendar_post_item_async( f"/items" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3737,6 +5039,7 @@ async def calendar_post_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3744,8 +5047,9 @@ async def calendar_post_item_async( return json.loads(response.text) - async def get_emails_async( + def list_emails( self, + *, folder_path: Optional[str] = None, to: Optional[str] = None, cc: Optional[str] = None, @@ -3758,16 +5062,55 @@ async def get_emails_async( include_attachments: Optional[bool] = None, search_query: Optional[str] = None, top: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get emails This operation gets emails from a folder. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetEmailsV2`. + + Args: + folder_path: Mail folder to retrieve emails from (default: + 'Inbox'). + to: Recipient email addresses separated by semicolons (If any + match, the trigger will run). + cc: CC recipient email addresses separated by semicolons (If any + match, the trigger will run). + to_or_cc: To or CC recipient email addresses separated by + semicolons (If any match, the trigger will run). + from_: Sender email addresses separated by semicolons (If any + match, the trigger will run). + importance: Importance of the email (Any, High, Normal, Low). + fetch_only_with_attachment: If set to true, only emails with an + attachment will be retrieved. Emails without any attachments + will be skipped. If set to false, all emails will be retrieved. + subject_filter: String to look for in the subject line. + fetch_only_unread: Retrieve only unread emails?. + include_attachments: If set to true, attachments content will also + be retrieved along with the email. + search_query: Search query to filter emails. How to use '$search' + parameter please refer to: + https://docs.microsoft.com/previous-versions/office/office-365-api/api/version-2.0/complex-types-for-mail-contacts-calendar#search-requests. + top: Number of emails to retrieve (default: 10). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/Mail" query_params = [] @@ -3834,49 +5177,100 @@ async def get_emails_async( query_params.append(f"top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_events_calendar_view_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_events_calendar_view( self, calendar_id: str, start_date_time_offset: str, end_date_time_offset: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, search: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get calendar view of events This operation gets all events (including instances of recurrences) in a calendar. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetEventsCalendarViewV2`. + + Args: + calendar_id: Select a calendar. + start_date_time_offset: Start time (example: + '2017-01-01T08:00:00-07:00'). + end_date_time_offset: End time (example: + '2017-02-01T08:00:00-07:00'). + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + search: Search text for matching event body and subject. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3922,31 +5316,52 @@ async def get_events_calendar_view_async( query_params.append(f"search={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def reply_to_async( + def reply_to( self, - input: ReplyHtmlMessage, + input: ReplyHtmlMessage | Mapping[str, Any], message_id: str, *, timeout: Optional[float] = None, @@ -3958,13 +5373,30 @@ async def reply_to_async( Reply to email This operation replies to an email. + + Swagger operation ID: `ReplyToV3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Id of the email to reply to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v3/Mail/ReplyTo/{quote(str(message_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3978,11 +5410,12 @@ async def reply_to_async( request_url, response.status, response.text, + response=response, ) - async def send_email_async( + def send_email( self, - input: ClientSendHtmlMessage, + input: ClientSendHtmlMessage | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -3993,10 +5426,26 @@ async def send_email_async( Send an email This operation sends an email message. + + Swagger operation ID: `SendEmailV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/Mail" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4010,6 +5459,7 @@ async def send_email_async( request_url, response.status, response.text, + response=response, ) diff --git a/src/azure/connectors/pdfco.py b/src/azure/connectors/pdfco.py index eb7179f..738c689 100644 --- a/src/azure/connectors/pdfco.py +++ b/src/azure/connectors/pdfco.py @@ -5,13 +5,12 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, Dict, List, Any, Mapping import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, @@ -19,6 +18,116 @@ ConnectorResponseHook, ) +__all__ = [ + "PdfcoClient", + "BarcodeGeneratorInput", + "BarcodeGeneratorResponse", + "BarcodeReaderInput", + "BarcodeReaderResponse", + "DocumentParserInput", + "DocumentParserResponse", + "EmailAttachmentExtractionInput", + "EmailAttachmentExtractionResponse", + "EmailDecodeInput", + "EmailDecodeResponse", + "EmailSendInput", + "EmailSendResponse", + "HtmlToPdfInput", + "HtmlToPdfResponse", + "JobCheckInput", + "JobCheckResponse", + "MergePdfInput", + "MergePdfResponse", + "MergePdfSimplifiedInput", + "MergePdfSimplifiedResponse", + "PDFAddSecurityInput", + "PDFAddSecurityResponse", + "PDFAttachmentExtractionInput", + "PDFAttachmentExtractionResponse", + "PDFAutoRotatePagesInput", + "PDFAutoRotatePagesResponse", + "PDFClassifierInput", + "PDFClassifierResponse", + "PDFCompressInput", + "PDFCompressResponse", + "PDFDeletePagesInput", + "PDFDeletePagesResponse", + "PDFFindTableInput", + "PDFFindTableResponse", + "PDFFormsInfoReaderInput", + "PDFFormsInfoReaderResponse", + "PDFFromCSVInput", + "PDFFromCSVResponse", + "PDFFromDocInput", + "PDFFromDocResponse", + "PDFFromEmailInput", + "PDFFromEmailResponse", + "PDFFromImagesInput", + "PDFFromImagesResponse", + "PDFFromXLSXLSXInput", + "PDFFromXLSXLSXResponse", + "PDFInfoReaderInput", + "PDFInfoReaderResponse", + "PDFRotatePagesInput", + "PDFRotatePagesResponse", + "PDFSearchTextInput", + "PDFSearchTextResponse", + "PDFSearchableInput", + "PDFSearchableResponse", + "PDFSecurityRemoveInput", + "PDFSecurityRemoveResponse", + "PDFToCSVInput", + "PDFToCSVResponse", + "PDFToJPGInput", + "PDFToJPGResponse", + "PDFToJSONInput", + "PDFToJSONMetaInput", + "PDFToJSONMetaResponse", + "PDFToJSONResponse", + "PDFToPNGInput", + "PDFToPNGResponse", + "PDFToTIFFInput", + "PDFToTIFFResponse", + "PDFToTextInput", + "PDFToTextResponse", + "PDFToTextSimpleInput", + "PDFToTextSimpleResponse", + "PDFToWEBPInput", + "PDFToWEBPResponse", + "PDFToXLSInput", + "PDFToXLSResponse", + "PDFToXLSXInput", + "PDFToXLSXResponse", + "PDFToXMLInput", + "PDFToXMLResponse", + "PDFUnSearchableInput", + "PDFUnSearchableResponse", + "PdfFillerInput", + "PdfFillerResponse", + "SearchAndDeleteTextInput", + "SearchAndDeleteTextResponse", + "SearchAndReplaceInput", + "SearchAndReplaceResponse", + "SearchAndReplaceWithImageInput", + "SearchAndReplaceWithImageResponse", + "SplitPdf2Input", + "SplitPdf2Response", + "SplitPdfInput", + "SplitPdfResponse", + "UrlToPdfInput", + "UrlToPdfResponse", + "XLStoCSVInput", + "XLStoCSVResponse", + "XLStoHTMLInput", + "XLStoHTMLResponse", + "XLStoJSONInput", + "XLStoJSONResponse", + "XLStoTXTInput", + "XLStoTXTResponse", + "XLStoXMLInput", + "XLStoXMLResponse", +] + # Type Definitions @@ -28,17 +137,18 @@ class HtmlToPdfInput: HTML to PDF """ - html: Optional[str] = None + html: str """Input HTML code to be converted.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Base file name for new PDF files.""" - margins: Optional[str] = None + margins: Optional[str] = dataclass_field(default=None, kw_only=True) """ Override default margins with custom values (the order is `top right bottom left`). You can als set all margins: `10px`, `5mm`, `5in` for all sides. """ - paper_size: Optional[str] = field( + paper_size: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "paperSize"}, ) """ @@ -47,18 +157,19 @@ class HtmlToPdfInput: or in (inches) with width and height separated by space like this: 200 300, 200px 300px, 200mm 300mm, 20cm 30cm or 6in 8in. """ - orientation: Optional[str] = None + orientation: Optional[str] = dataclass_field(default=None, kw_only=True) """PDF page orientation.""" - print_background: Optional[bool] = field( + print_background: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "printBackground"}, ) """Enable or disable printing of document background""" - header: Optional[str] = None + header: Optional[str] = dataclass_field(default=None, kw_only=True) """Set to HTML for header to be applied on every page at the header.""" - footer: Optional[str] = None + footer: Optional[str] = dataclass_field(default=None, kw_only=True) """Set to HTML for footer to be applied on every page at the bottom.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -66,15 +177,16 @@ class HtmlToPdfInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ This parameter can be used to set additional configurations for fine-tuning and to enable more options. Visit PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples and more. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -91,30 +203,33 @@ class HtmlToPdfResponse: Response for HTML to PDF """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document URL.""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """Number of pages in the output document.""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether the operation is successful or not.""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """Status code for HTTP response""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """PDF.co credits used for this request""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """Request execution duration""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """PDF.co account remaining credits""" @@ -126,20 +241,21 @@ class UrlToPdfInput: URL to PDF """ - url: Optional[str] = None + url: str """ Link to input HTML file or website page to be converted. You can pass link to file from Google Drive, Dropbox or another online file service that can generate shareable links. """ - margins: Optional[str] = None + margins: Optional[str] = dataclass_field(default=None, kw_only=True) """ Margins to be used in output document. Set to css style margins like 10px, 5mm, 5in for all sides or 5px 5px 5px 5px (the order of margins is top, right, bottom, left). """ - paper_size: Optional[str] = field( + paper_size: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "paperSize"}, ) """ @@ -148,18 +264,19 @@ class UrlToPdfInput: mm or in (inches) with width and height separated by space like this: 200 300, 200px 300px, 200mm 300mm, 20cm 30cm or 6in 8in. """ - orientation: Optional[str] = None + orientation: Optional[str] = dataclass_field(default=None, kw_only=True) """Output page orientation""" - print_background: Optional[bool] = field( + print_background: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "printBackground"}, ) """Enable or disable printing of document background""" - header: Optional[str] = None + header: Optional[str] = dataclass_field(default=None, kw_only=True) """Set to HTML for header to be applied on every page at the header.""" - footer: Optional[str] = None + footer: Optional[str] = dataclass_field(default=None, kw_only=True) """Set to HTML for footer to be applied on every page at the bottom.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -167,15 +284,16 @@ class UrlToPdfInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ This parameter can be used to set additional configurations for fine-tuning and to enable more options. Visit PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples and more. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -192,30 +310,33 @@ class UrlToPdfResponse: Response for URL to PDF """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document URL.""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """Number of pages in the output document.""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether the operation is successful or not.""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """Status code for HTTP response""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """PDF.co credits used for this request""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """Request execution duration""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """PDF.co account remaining credits""" @@ -227,10 +348,11 @@ class PdfFillerInput: Add Text, Images, Form Fields to PDF """ - url: Optional[str] = None + url: str """Url to the input PDF document""" - annotations_string: Optional[str] = field( + annotations_string: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "annotationsString"}, ) """ @@ -238,8 +360,9 @@ class PdfFillerInput: \"x;y;page;text\". Refer to PDF.co documentations for more advanced formats and examples. """ - images_string: Optional[str] = field( + images_string: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "imagesString"}, ) """ @@ -247,21 +370,22 @@ class PdfFillerInput: \"x;y;page;urltoimage;link;width;height\". Refer to PDF.co documentations for more advanced formats and examples. """ - fields_string: Optional[str] = field( + fields_string: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fieldsString"}, ) """ Fill PDF form fields. Format should be like \"page;fieldName;value\". Refer to PDF.co documentations for more advanced formats and examples. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Output PDF Name""" - inline: Optional[bool] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Determines whether to return output in response or link to output file. """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -269,15 +393,16 @@ class PdfFillerInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ This parameter can be used to set additional configurations for fine-tuning and to enable more options. Visit PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples and more. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -294,30 +419,33 @@ class PdfFillerResponse: Response for Add Text, Images, Form Fields to PDF """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document URL.""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """Number of pages in the output document.""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether the operation is successful or not.""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """Status code for HTTP response""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """PDF.co credits used for this request""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """Request execution duration""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """PDF.co account remaining credits""" @@ -329,7 +457,7 @@ class MergePdfSimplifiedInput: Merge PDF """ - url: Optional[str] = None + url: str """ The comma-separated list of links to PDFs files. Supports links to external sites, `filetoken://..` from PDF.co Files storage and links to G Drive, @@ -337,7 +465,7 @@ class MergePdfSimplifiedInput: For password protected PDF files, use PDF Security module first to unlock input pdf. """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -345,14 +473,15 @@ class MergePdfSimplifiedInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -369,30 +498,33 @@ class MergePdfSimplifiedResponse: Response for Merge PDF """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document URL.""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """Number of pages in the output document.""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether the operation is successful or not.""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """Status code for HTTP response""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """PDF.co credits used for this request""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """Request execution duration""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """PDF.co account remaining credits""" @@ -404,7 +536,7 @@ class MergePdfInput: Merge PDF (Advanced) """ - url: Optional[str] = None + url: str """ The comma-separated list of links to PDFs, documents, spreadsheets, images. Supports links to external sites, `filetoken://..` from PDF.co Files @@ -412,7 +544,7 @@ class MergePdfInput: accessible without password. For password protected PDF files, use PDF Security module first to unlock input pdf. """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -420,14 +552,15 @@ class MergePdfInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -444,30 +577,33 @@ class MergePdfResponse: Response for Merge PDF (Advanced) """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document URL.""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """Number of pages in the output document.""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether the operation is successful or not.""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """Status code for HTTP response""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """PDF.co credits used for this request""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """Request execution duration""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """PDF.co account remaining credits""" @@ -479,21 +615,21 @@ class SplitPdfInput: Split PDF """ - url: Optional[str] = None + url: str """Url to the source PDF document""" - pages: Optional[str] = None + pages: str """ Comma-separated list of page indices (or ranges) to split into. First page is 1 (one). Example: \"1,2-5,7-\". Special cases: to extract each page into separate PDF use to `*`. """ - inline: Optional[bool] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Determines whether to return output in response or link to output file. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Base file name for new PDF files""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -501,14 +637,15 @@ class SplitPdfInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """Creates a background processing job.""" @@ -520,32 +657,35 @@ class SplitPdfResponse: Response for Split PDF """ - urls: Optional[List[str]] = None + urls: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """urls""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document URL.""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """Number of pages in the output document.""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether the operation is successful or not.""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """Status code for HTTP response""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """PDF.co credits used for this request""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """Request execution duration""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """PDF.co account remaining credits""" @@ -557,10 +697,9 @@ class SplitPdf2Input: Split PDF (Advanced) """ - url: Optional[str] = None + url: str """Url to the source PDF document""" - search_string: Optional[str] = field( - default=None, + search_string: str = dataclass_field( metadata={"wire_name": "searchString"}, ) """ @@ -568,22 +707,25 @@ class SplitPdf2Input: visit https://developer.pdf.co/api/pdf-split/index.html?utm_source=api-docs#post-tag-pdf-split2 """ - exclude_key_pages: Optional[bool] = field( + exclude_key_pages: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "excludeKeyPages"}, ) """Set to true if you want to exclude pages where text was found""" - regex_search: Optional[bool] = field( + regex_search: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "regexSearch"}, ) """Set to true to enable regular expressions for the search string""" - case_sensitive: Optional[bool] = field( + case_sensitive: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "caseSensitive"}, ) """Set to true to enable case-sensitive search.""" - lang: Optional[str] = None + lang: Optional[str] = dataclass_field(default=None, kw_only=True) """ the language for OCR (text from image) to use for scanned PDF, PNG, and JPG documents input when extracting text. The default is \"eng\". Other @@ -593,13 +735,13 @@ class SplitPdf2Input: You can also use 2 languages simultaneously like this: eng+deu or jpn+kor (any combination). """ - inline: Optional[bool] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Determines whether to return output in response or link to output file. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Base file name for new PDF files""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -607,14 +749,15 @@ class SplitPdf2Input: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """Creates a background processing job.""" @@ -626,32 +769,35 @@ class SplitPdf2Response: Response for Split PDF (Advanced) """ - urls: Optional[List[str]] = None + urls: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """urls""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document URL.""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """Number of pages in the output document.""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether the operation is successful or not.""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """Status code for HTTP response""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """PDF.co credits used for this request""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """Request execution duration""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """PDF.co account remaining credits""" @@ -663,26 +809,26 @@ class PDFSearchTextInput: PDF Search Text """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - search_string: Optional[str] = field( - default=None, + search_string: str = dataclass_field( metadata={"wire_name": "searchString"}, ) """ Text to search can support regular expressions if you set the \"Regex Search\" parameter to true. """ - regex_search: Optional[bool] = field( + regex_search: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "regexSearch"}, ) - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. IMPORTANT: the very first page starts at 0 (zero). To set a range use the dash -, for @@ -693,16 +839,18 @@ class PDFSearchTextInput: from the 8th (index = 7) page till the end of the document, The input must be in string format. """ - inline: Optional[bool] = None - word_matching_mode: Optional[str] = field( + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) + word_matching_mode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "wordMatchingMode"}, ) """Values can be either 'SmartMatch', 'ExactMatch', or 'None'.""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password of the PDF file""" - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -711,7 +859,7 @@ class PDFSearchTextInput: status of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase @@ -725,33 +873,36 @@ class PDFSearchTextResponse: Response for PDF Search Text """ - body: Optional[List[Dict[str, Any]]] = None + body: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """body""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -761,42 +912,42 @@ class DocumentParserInput: Document Parser """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. To upload files via API, Check out the Files Upload section at https://developer.pdf.co/api/file-upload/index.html """ - template_id: Optional[str] = field( + template_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "templateId"}, ) """ Set ID of document parser template to be used. View and manage your templates at https://app.pdf.co/document-parser """ - output_format: Optional[str] = field( - default=None, + output_format: str = dataclass_field( metadata={"wire_name": "outputFormat"}, ) """ Default is JSON. You can override the default output format to CSV or XML to generate CSV or XML output accordingly. """ - inline: Optional[bool] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Set to true to return results inside the response. Otherwise, the endpoint will return a link to the output file generated """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password of PDF file""" - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase https://developer.pdf.co/api/profiles/index.html for profile examples, """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -804,8 +955,9 @@ class DocumentParserInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -822,28 +974,31 @@ class DocumentParserResponse: Response for Document Parser """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Output URL""" - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """body""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) - error: Optional[bool] = None - job_id: Optional[str] = field( + error: Optional[bool] = dataclass_field(default=None, kw_only=True) + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) - status: Optional[int] = None - name: Optional[str] = None - credits: Optional[int] = None - remaining_credits: Optional[int] = field( + status: Optional[int] = dataclass_field(default=None, kw_only=True) + name: Optional[str] = dataclass_field(default=None, kw_only=True) + credits: Optional[int] = dataclass_field(default=None, kw_only=True) + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) - duration: Optional[int] = None - message: Optional[str] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) + message: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -852,7 +1007,7 @@ class JobCheckInput: Background Jobs Check """ - jobid: Optional[str] = None + jobid: str """PDF.co background Job Id""" @@ -862,40 +1017,45 @@ class JobCheckResponse: Response for Background Jobs Check """ - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """status""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """message""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - job_duration: Optional[int] = field( + job_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobDuration"}, ) """jobDuration""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - error_code: Optional[int] = field( + error_code: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "errorCode"}, ) """errorCode""" @@ -907,27 +1067,29 @@ class BarcodeGeneratorInput: Barcode Generator """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Set async to true for long processes to run in the background, API will then return a jobId which you can use with /job/check endpoint to check the status of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - value: Optional[str] = None + value: str """Set the string value to encode inside the barcode.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """Set the barcode type, QRCode By default.""" - decoration_image: Optional[str] = field( + decoration_image: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "decorationImage"}, ) """ Set this to the image that you want to be inserted the logo inside the QR-Code barcode. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -936,7 +1098,7 @@ class BarcodeGeneratorInput: status of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -944,7 +1106,7 @@ class BarcodeGeneratorInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co Knowledgebase @@ -958,27 +1120,29 @@ class BarcodeGeneratorResponse: Response for Barcode Generator """ - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -988,12 +1152,12 @@ class BarcodeReaderInput: Barcode Reader """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - types: Optional[str] = None + types: str """ Set the barcode type, QRCode is default. You can also combine types by comma, example \"QRCode,Code128,Code39,Interleaved2of5,EAN13\". All @@ -1008,7 +1172,7 @@ class BarcodeReaderInput: QRCode, Rectangle, RoyalMail, RoyalMailKIX, Segment, Trioptic, UnderlinedField, UPCA, UPCE, UPU, VerticalLine. """ - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-Separated list of page indices (or ranges) to process. IMPORTANT: the very first page starts at 0 (zero). To set a range use the dash -, for @@ -1018,16 +1182,17 @@ class BarcodeReaderInput: means the first page, then the 3rd page to the 6th page, and then the range from the 8th (index = 7) page till the end of the document. """ - encrypt: Optional[bool] = None + encrypt: Optional[bool] = dataclass_field(default=None, kw_only=True) """encrypt""" - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -1044,32 +1209,35 @@ class BarcodeReaderResponse: Response for Barcode Reader """ - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - barcodes: Optional[List[Dict[str, Any]]] = None + barcodes: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """barcodes""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -1079,13 +1247,14 @@ class PDFInfoReaderInput: PDF Info Reader """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -1094,9 +1263,9 @@ class PDFInfoReaderInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password of the PDF file""" - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configuration for fine-tuning and extra options, Explore PDF.co knowledgebase @@ -1110,27 +1279,29 @@ class PDFInfoReaderResponse: Response for PDF Info Reader """ - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - info: Optional[Dict[str, Any]] = None + info: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """info""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -1140,13 +1311,14 @@ class PDFFormsInfoReaderInput: PDF Forms Info Reader """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -1155,9 +1327,9 @@ class PDFFormsInfoReaderInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password of the PDF file""" - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configuration for fine-tuning and extra options, Explore PDF.co knowledgebase @@ -1171,27 +1343,29 @@ class PDFFormsInfoReaderResponse: Response for PDF Forms Info Reader """ - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - info: Optional[Dict[str, Any]] = None + info: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """info""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -1201,12 +1375,12 @@ class PDFFindTableInput: PDF Find Table """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. IMPORTANT: the very first page starts at 0 (zero). To set a range use the dash -, for @@ -1216,16 +1390,16 @@ class PDFFindTableInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - inline: Optional[bool] = None - password: Optional[str] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password of PDF file""" - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -1233,8 +1407,9 @@ class PDFFindTableInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -1251,34 +1426,37 @@ class PDFFindTableResponse: Response for PDF Find Table """ - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """body""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """Credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -1288,27 +1466,29 @@ class SearchAndReplaceInput: PDF Search and Replace Text """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - search_strings: Optional[List[str]] = field( - default=None, + search_strings: List[str] = dataclass_field( metadata={"wire_name": "searchStrings"}, ) """Search Strings""" - replace_strings: Optional[List[str]] = field( + replace_strings: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "replaceStrings"}, ) """Replacement Strings""" - case_sensitive: Optional[bool] = field( + case_sensitive: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "caseSensitive"}, ) - replacement_limit: Optional[int] = field( + replacement_limit: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "replacementLimit"}, ) """ @@ -1316,9 +1496,9 @@ class SearchAndReplaceInput: value is 0 which means unlimited searches and replacements so every found occurrence will be replaced. """ - regex: Optional[bool] = None + regex: Optional[bool] = dataclass_field(default=None, kw_only=True) """Set to true to use regular expression for a search string(s).""" - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -1328,11 +1508,11 @@ class SearchAndReplaceInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """The password of the PDF file""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -1340,8 +1520,9 @@ class SearchAndReplaceInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -1358,31 +1539,34 @@ class SearchAndReplaceResponse: Response for PDF Search and Replace Text """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1391,26 +1575,25 @@ class SearchAndReplaceWithImageInput: PDF Search and Replace Text with Image """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - case_sensitive: Optional[bool] = field( + case_sensitive: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "caseSensitive"}, ) - search_string: Optional[str] = field( - default=None, + search_string: str = dataclass_field( metadata={"wire_name": "searchString"}, ) """Single text replacement. Word or phrase to be replaced""" - replace_image: Optional[str] = field( - default=None, + replace_image: str = dataclass_field( metadata={"wire_name": "replaceImage"}, ) """Image URL to be inserted in the doc.""" - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -1420,8 +1603,9 @@ class SearchAndReplaceWithImageInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -1430,9 +1614,10 @@ class SearchAndReplaceWithImageInput: status of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish.. """ - regex: Optional[bool] = None - replacement_limit: Optional[int] = field( + regex: Optional[bool] = dataclass_field(default=None, kw_only=True) + replacement_limit: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "replacementLimit"}, ) """ @@ -1440,7 +1625,7 @@ class SearchAndReplaceWithImageInput: value is 0 which means unlimited searches and replacements so every found occurrence will be replaced. """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -1448,7 +1633,7 @@ class SearchAndReplaceWithImageInput: The maximum duration for link expiration varies based on your current subscription plan. """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password of the PDF file""" @@ -1458,32 +1643,35 @@ class SearchAndReplaceWithImageResponse: Response for PDF Search and Replace Text with Image """ - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -1493,24 +1681,25 @@ class SearchAndDeleteTextInput: PDF Search and Delete Text from PDF """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - search_strings: Optional[List[str]] = field( - default=None, + search_strings: List[str] = dataclass_field( metadata={"wire_name": "searchStrings"}, ) """searchStrings""" - case_sensitive: Optional[bool] = field( + case_sensitive: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "caseSensitive"}, ) - regex: Optional[bool] = None + regex: Optional[bool] = dataclass_field(default=None, kw_only=True) """Set to true to use regular expression for a search string(s).""" - replacement_limit: Optional[int] = field( + replacement_limit: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "replacementLimit"}, ) """ @@ -1518,7 +1707,7 @@ class SearchAndDeleteTextInput: value is 0 which means unlimited searches and replacements so every found occurrence will be replaced. """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -1526,11 +1715,11 @@ class SearchAndDeleteTextInput: The maximum duration for link expiration varies based on your current subscription plan. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password of the PDF file""" - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -1540,14 +1729,15 @@ class SearchAndDeleteTextInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -1564,32 +1754,35 @@ class SearchAndDeleteTextResponse: Response for PDF Search and Delete Text from PDF """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -1599,12 +1792,12 @@ class PDFSearchableInput: Make Scanned PDF to Text Searchable """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - lang: Optional[str] = None + lang: Optional[str] = dataclass_field(default=None, kw_only=True) """ the language for OCR (text from image) to use for scanned PDF, PNG, and JPG documents input when extracting text. The default is \"eng\". Other @@ -1614,7 +1807,7 @@ class PDFSearchableInput: You can also use 2 languages simultaneously like this: eng+deu or jpn+kor (any combination). """ - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -1624,10 +1817,11 @@ class PDFSearchableInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password of PDF file""" - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -1636,7 +1830,7 @@ class PDFSearchableInput: status of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase @@ -1650,32 +1844,35 @@ class PDFSearchableResponse: Response for Make Scanned PDF to Text Searchable """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -1685,12 +1882,12 @@ class PDFUnSearchableInput: PDF to Scanned PDF """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -1700,10 +1897,11 @@ class PDFUnSearchableInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password of PDF file""" - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -1712,7 +1910,7 @@ class PDFUnSearchableInput: status of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase @@ -1726,32 +1924,35 @@ class PDFUnSearchableResponse: Response for PDF to Scanned PDF """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -1761,12 +1962,12 @@ class PDFToCSVInput: PDF To CSV """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - lang: Optional[str] = None + lang: Optional[str] = dataclass_field(default=None, kw_only=True) """ Set the language for OCR (text from image) to use for scanned PDF, PNG, and JPG documents input when extracting text. The default is \"eng\". Other @@ -1776,13 +1977,13 @@ class PDFToCSVInput: You can also use 2 languages simultaneously like this: eng+deu or jpn+kor (any combination). """ - inline: Optional[bool] = None - unwrap: Optional[str] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) + unwrap: Optional[str] = dataclass_field(default=None, kw_only=True) """ Unwrap lines into a single line within table cells when lineGrouping is enabled. """ - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -1792,14 +1993,15 @@ class PDFToCSVInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - rect: Optional[str] = None + rect: Optional[str] = dataclass_field(default=None, kw_only=True) """ Defines coordinates for extraction, e.g. 51.8, 114.8, 235.5, 204.0. Use PDF.co PDF Edit Add Helper (https://app.pdf.co/pdf-edit-add-helper) to get or measure pdf coordinates. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -1808,16 +2010,17 @@ class PDFToCSVInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """password""" - line_grouping: Optional[str] = field( + line_grouping: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lineGrouping"}, ) """Line grouping within table cells. Set to 1 to enable the grouping.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -1825,7 +2028,7 @@ class PDFToCSVInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ This parameter can be used to set additional configurations for fine-tuning and to enable more options. Visit PDF.co knowledgebase @@ -1840,29 +2043,31 @@ class PDFToCSVResponse: Response for PDF To CSV """ - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """body""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -1872,12 +2077,12 @@ class PDFToJSONInput: PDF To JSON """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - lang: Optional[str] = None + lang: Optional[str] = dataclass_field(default=None, kw_only=True) """ Set the language for OCR (text from image) to use for scanned PDF, PNG, and JPG documents input when extracting text. The default is \"eng\". Other @@ -1887,13 +2092,13 @@ class PDFToJSONInput: You can also use 2 languages simultaneously like this: eng+deu or jpn+kor (any combination). """ - inline: Optional[bool] = None - unwrap: Optional[str] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) + unwrap: Optional[str] = dataclass_field(default=None, kw_only=True) """ Unwrap lines into a single line within table cells when lineGrouping is enabled. """ - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -1903,14 +2108,15 @@ class PDFToJSONInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - rect: Optional[str] = None + rect: Optional[str] = dataclass_field(default=None, kw_only=True) """ Defines coordinates for extraction, e.g. 51.8, 114.8, 235.5, 204.0. Use PDF.co PDF Edit Add Helper (https://app.pdf.co/pdf-edit-add-helper) to get or measure pdf coordinates. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -1919,16 +2125,17 @@ class PDFToJSONInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """password""" - line_grouping: Optional[str] = field( + line_grouping: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lineGrouping"}, ) """Line grouping within table cells. Set to 1 to enable the grouping.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -1936,7 +2143,7 @@ class PDFToJSONInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ This parameter can be used to set additional configurations for fine-tuning and to enable more options. Visit PDF.co knowledgebase @@ -1951,34 +2158,37 @@ class PDFToJSONResponse: Response for PDF To JSON """ - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """body""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -1988,12 +2198,12 @@ class PDFToJSONMetaInput: PDF To JSON (AI Powered) """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - lang: Optional[str] = None + lang: Optional[str] = dataclass_field(default=None, kw_only=True) """ Set the language for OCR (text from image) to use for scanned PDF, PNG, and JPG documents input when extracting text. The default is \"eng\". Other @@ -2003,13 +2213,13 @@ class PDFToJSONMetaInput: You can also use 2 languages simultaneously like this: eng+deu or jpn+kor (any combination). """ - inline: Optional[bool] = None - unwrap: Optional[str] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) + unwrap: Optional[str] = dataclass_field(default=None, kw_only=True) """ Unwrap lines into a single line within table cells when lineGrouping is enabled. """ - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -2019,14 +2229,15 @@ class PDFToJSONMetaInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - rect: Optional[str] = None + rect: Optional[str] = dataclass_field(default=None, kw_only=True) """ Defines coordinates for extraction, e.g. 51.8, 114.8, 235.5, 204.0. Use PDF.co PDF Edit Add Helper (https://app.pdf.co/pdf-edit-add-helper) to get or measure pdf coordinates. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -2035,16 +2246,17 @@ class PDFToJSONMetaInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """password""" - line_grouping: Optional[str] = field( + line_grouping: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lineGrouping"}, ) """Line grouping within table cells. Set to 1 to enable the grouping.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -2052,7 +2264,7 @@ class PDFToJSONMetaInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ This parameter can be used to set additional configurations for fine-tuning and to enable more options. Visit PDF.co knowledgebase @@ -2067,34 +2279,37 @@ class PDFToJSONMetaResponse: Response for PDF To JSON (AI Powered) """ - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """body""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -2104,12 +2319,12 @@ class PDFToTextInput: PDF To Text (with layout and ocr) """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - lang: Optional[str] = None + lang: Optional[str] = dataclass_field(default=None, kw_only=True) """ Set the language for OCR (text from image) to use for scanned PDF, PNG, and JPG documents input when extracting text. The default is \"eng\". Other @@ -2119,13 +2334,13 @@ class PDFToTextInput: You can also use 2 languages simultaneously like this: eng+deu or jpn+kor (any combination). """ - inline: Optional[bool] = None - unwrap: Optional[str] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) + unwrap: Optional[str] = dataclass_field(default=None, kw_only=True) """ Unwrap lines into a single line within table cells when lineGrouping is enabled. """ - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -2135,14 +2350,15 @@ class PDFToTextInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - rect: Optional[str] = None + rect: Optional[str] = dataclass_field(default=None, kw_only=True) """ Defines coordinates for extraction, e.g. 51.8, 114.8, 235.5, 204.0. Use PDF.co PDF Edit Add Helper (https://app.pdf.co/pdf-edit-add-helper) to get or measure pdf coordinates. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -2151,16 +2367,17 @@ class PDFToTextInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """password""" - line_grouping: Optional[str] = field( + line_grouping: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lineGrouping"}, ) """Line grouping within table cells. Set to 1 to enable the grouping.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -2168,7 +2385,7 @@ class PDFToTextInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ This parameter can be used to set additional configurations for fine-tuning and to enable more options. Visit PDF.co knowledgebase @@ -2183,34 +2400,37 @@ class PDFToTextResponse: Response for PDF To Text (with layout and ocr) """ - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """body""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -2220,13 +2440,13 @@ class PDFToTextSimpleInput: PDF To Text (without layout and ocr) """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - inline: Optional[bool] = None - pages: Optional[str] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -2236,8 +2456,9 @@ class PDFToTextSimpleInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -2246,11 +2467,11 @@ class PDFToTextSimpleInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """password""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -2266,34 +2487,37 @@ class PDFToTextSimpleResponse: Response for PDF To Text (without layout and ocr) """ - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """body""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -2303,12 +2527,12 @@ class PDFToXLSInput: PDF To XLS """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - lang: Optional[str] = None + lang: Optional[str] = dataclass_field(default=None, kw_only=True) """ Set the language for OCR (text from image) to use for scanned PDF, PNG, and JPG documents input when extracting text. The default is \"eng\". Other @@ -2318,12 +2542,12 @@ class PDFToXLSInput: You can also use 2 languages simultaneously like this: eng+deu or jpn+kor (any combination). """ - unwrap: Optional[str] = None + unwrap: Optional[str] = dataclass_field(default=None, kw_only=True) """ Unwrap lines into a single line within table cells when lineGrouping is enabled. """ - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -2333,14 +2557,15 @@ class PDFToXLSInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - rect: Optional[str] = None + rect: Optional[str] = dataclass_field(default=None, kw_only=True) """ Defines coordinates for extraction, e.g. 51.8, 114.8, 235.5, 204.0. Use PDF.co PDF Edit Add Helper (https://app.pdf.co/pdf-edit-add-helper) to get or measure pdf coordinates. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -2349,16 +2574,17 @@ class PDFToXLSInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """password""" - line_grouping: Optional[str] = field( + line_grouping: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lineGrouping"}, ) """Line grouping within table cells. Set to 1 to enable the grouping.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -2366,7 +2592,7 @@ class PDFToXLSInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ This parameter can be used to set additional configurations for fine-tuning and to enable more options. Visit PDF.co knowledgebase @@ -2381,32 +2607,35 @@ class PDFToXLSResponse: Response for PDF To XLS """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -2416,12 +2645,12 @@ class PDFToXLSXInput: PDF To XLSX """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - lang: Optional[str] = None + lang: Optional[str] = dataclass_field(default=None, kw_only=True) """ Set the language for OCR (text from image) to use for scanned PDF, PNG, and JPG documents input when extracting text. The default is \"eng\". Other @@ -2431,12 +2660,12 @@ class PDFToXLSXInput: You can also use 2 languages simultaneously like this: eng+deu or jpn+kor (any combination). """ - unwrap: Optional[str] = None + unwrap: Optional[str] = dataclass_field(default=None, kw_only=True) """ Unwrap lines into a single line within table cells when lineGrouping is enabled. """ - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -2446,14 +2675,15 @@ class PDFToXLSXInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - rect: Optional[str] = None + rect: Optional[str] = dataclass_field(default=None, kw_only=True) """ Defines coordinates for extraction, e.g. 51.8, 114.8, 235.5, 204.0. Use PDF.co PDF Edit Add Helper (https://app.pdf.co/pdf-edit-add-helper) to get or measure pdf coordinates. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -2462,16 +2692,17 @@ class PDFToXLSXInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """password""" - line_grouping: Optional[str] = field( + line_grouping: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lineGrouping"}, ) """Line grouping within table cells. Set to 1 to enable the grouping.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -2479,7 +2710,7 @@ class PDFToXLSXInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ This parameter can be used to set additional configurations for fine-tuning and to enable more options. Visit PDF.co knowledgebase @@ -2494,32 +2725,35 @@ class PDFToXLSXResponse: Response for PDF To XLSX """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -2529,13 +2763,13 @@ class PDFToXMLInput: PDF To XML """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - inline: Optional[bool] = None - lang: Optional[str] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) + lang: Optional[str] = dataclass_field(default=None, kw_only=True) """ Set the language for OCR (text from image) to use for scanned PDF, PNG, and JPG documents input when extracting text. The default is \"eng\". Other @@ -2545,12 +2779,12 @@ class PDFToXMLInput: You can also use 2 languages simultaneously like this: eng+deu or jpn+kor (any combination). """ - unwrap: Optional[str] = None + unwrap: Optional[str] = dataclass_field(default=None, kw_only=True) """ Unwrap lines into a single line within table cells when lineGrouping is enabled. """ - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -2560,14 +2794,15 @@ class PDFToXMLInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - rect: Optional[str] = None + rect: Optional[str] = dataclass_field(default=None, kw_only=True) """ Defines coordinates for extraction, e.g. 51.8, 114.8, 235.5, 204.0. Use PDF.co PDF Edit Add Helper (https://app.pdf.co/pdf-edit-add-helper) to get or measure pdf coordinates. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -2576,16 +2811,17 @@ class PDFToXMLInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """password""" - line_grouping: Optional[str] = field( + line_grouping: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lineGrouping"}, ) """Line grouping within table cells. Set to 1 to enable the grouping.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -2593,7 +2829,7 @@ class PDFToXMLInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ This parameter can be used to set additional configurations for fine-tuning and to enable more options. Visit PDF.co knowledgebase @@ -2608,34 +2844,37 @@ class PDFToXMLResponse: Response for PDF To XML """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """body""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -2645,14 +2884,14 @@ class PDFToJPGInput: PDF to JPG """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - inline: Optional[bool] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) """inline""" - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -2662,13 +2901,13 @@ class PDFToJPGInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - rect: Optional[str] = None + rect: Optional[str] = dataclass_field(default=None, kw_only=True) """ Defines coordinates for extraction, e.g. 51.8, 114.8, 235.5, 204.0. Use PDF.co PDF Edit Add Helper (https://app.pdf.co/pdf-edit-add-helper) to get or measure pdf coordinates. """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -2676,8 +2915,9 @@ class PDFToJPGInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -2686,7 +2926,7 @@ class PDFToJPGInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -2700,32 +2940,35 @@ class PDFToJPGResponse: Response for PDF to JPG """ - urls: Optional[List[str]] = None + urls: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """urls""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -2735,14 +2978,14 @@ class PDFToPNGInput: PDF to PNG """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - inline: Optional[bool] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) """inline""" - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -2752,13 +2995,13 @@ class PDFToPNGInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - rect: Optional[str] = None + rect: Optional[str] = dataclass_field(default=None, kw_only=True) """ Defines coordinates for extraction, e.g. 51.8, 114.8, 235.5, 204.0. Use PDF.co PDF Edit Add Helper (https://app.pdf.co/pdf-edit-add-helper) to get or measure pdf coordinates. """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -2766,8 +3009,9 @@ class PDFToPNGInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -2776,7 +3020,7 @@ class PDFToPNGInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -2790,32 +3034,35 @@ class PDFToPNGResponse: Response for PDF to PNG """ - urls: Optional[List[str]] = None + urls: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """urls""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -2825,14 +3072,14 @@ class PDFToWEBPInput: PDF to WEBP """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - inline: Optional[bool] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) """inline""" - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -2842,13 +3089,13 @@ class PDFToWEBPInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - rect: Optional[str] = None + rect: Optional[str] = dataclass_field(default=None, kw_only=True) """ Defines coordinates for extraction, e.g. 51.8, 114.8, 235.5, 204.0. Use PDF.co PDF Edit Add Helper (https://app.pdf.co/pdf-edit-add-helper) to get or measure pdf coordinates. """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -2856,8 +3103,9 @@ class PDFToWEBPInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -2866,7 +3114,7 @@ class PDFToWEBPInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -2880,32 +3128,35 @@ class PDFToWEBPResponse: Response for PDF to WEBP """ - urls: Optional[List[str]] = None + urls: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """urls""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -2915,14 +3166,14 @@ class PDFToTIFFInput: PDF to TIFF """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - inline: Optional[bool] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) """inline""" - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -2932,13 +3183,13 @@ class PDFToTIFFInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - rect: Optional[str] = None + rect: Optional[str] = dataclass_field(default=None, kw_only=True) """ Defines coordinates for extraction, e.g. 51.8, 114.8, 235.5, 204.0. Use PDF.co PDF Edit Add Helper (https://app.pdf.co/pdf-edit-add-helper) to get or measure pdf coordinates. """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -2946,8 +3197,9 @@ class PDFToTIFFInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -2956,7 +3208,7 @@ class PDFToTIFFInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -2970,31 +3222,34 @@ class PDFToTIFFResponse: Response for PDF to TIFF """ - url: Optional[str] = None - job_id: Optional[str] = field( + url: Optional[str] = dataclass_field(default=None, kw_only=True) + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -3004,12 +3259,12 @@ class PDFFromCSVInput: PDF from CSV """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -3019,9 +3274,9 @@ class PDFFromCSVInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -3029,8 +3284,9 @@ class PDFFromCSVInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -3039,7 +3295,7 @@ class PDFFromCSVInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -3053,31 +3309,34 @@ class PDFFromCSVResponse: Response for PDF from CSV """ - url: Optional[str] = None - job_id: Optional[str] = field( + url: Optional[str] = dataclass_field(default=None, kw_only=True) + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -3087,12 +3346,12 @@ class PDFFromDocInput: PDF from Document (Doc, DocX, RTF, TXT, XPS) """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -3102,9 +3361,9 @@ class PDFFromDocInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -3112,8 +3371,9 @@ class PDFFromDocInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -3122,7 +3382,7 @@ class PDFFromDocInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -3136,31 +3396,34 @@ class PDFFromDocResponse: Response for PDF from Document (Doc, DocX, RTF, TXT, XPS) """ - url: Optional[str] = None - job_id: Optional[str] = field( + url: Optional[str] = dataclass_field(default=None, kw_only=True) + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -3170,15 +3433,15 @@ class PDFFromImagesInput: PDF from Image """ - url: Optional[str] = None + url: str """ URL to the source file. Provide multiple URLS in comma separated format. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -3186,8 +3449,9 @@ class PDFFromImagesInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -3196,7 +3460,7 @@ class PDFFromImagesInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -3210,31 +3474,34 @@ class PDFFromImagesResponse: Response for PDF from Image """ - url: Optional[str] = None - job_id: Optional[str] = field( + url: Optional[str] = dataclass_field(default=None, kw_only=True) + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -3244,13 +3511,14 @@ class PDFFromEmailInput: PDF from Email """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - embed_attachments: Optional[bool] = field( + embed_attachments: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "embedAttachments"}, ) """ @@ -3259,8 +3527,9 @@ class PDFFromEmailInput: don't want to embed attachments so it will convert only the body of the input email. """ - convert_attachments: Optional[bool] = field( + convert_attachments: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "convertAttachments"}, ) """ @@ -3271,13 +3540,14 @@ class PDFFromEmailInput: Non-supported file types are added as PDF attachments (Adobe Reader or another viewer may be required to view PDF attachments). """ - margins: Optional[str] = None + margins: Optional[str] = dataclass_field(default=None, kw_only=True) """ set to CSS style margins like 10px, 5mm, 5in for all sides or 5px 5px 5px 5px (the order of margins is top, right, bottom, left). """ - paper_size: Optional[str] = field( + paper_size: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "paperSize"}, ) """ @@ -3286,10 +3556,10 @@ class PDFFromEmailInput: mm or in (inches) with width and height separated by space like this: 200 300, 200px 300px, 200mm 300mm, 20cm 30cm or 6in 8in. """ - orientation: Optional[str] = None - name: Optional[str] = None + orientation: Optional[str] = dataclass_field(default=None, kw_only=True) + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -3297,8 +3567,9 @@ class PDFFromEmailInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -3307,7 +3578,7 @@ class PDFFromEmailInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -3321,31 +3592,34 @@ class PDFFromEmailResponse: Response for PDF from Email """ - url: Optional[str] = None - job_id: Optional[str] = field( + url: Optional[str] = dataclass_field(default=None, kw_only=True) + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -3355,36 +3629,38 @@ class PDFAddSecurityInput: PDF Add Security """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - owner_password: Optional[str] = field( - default=None, + owner_password: str = dataclass_field( metadata={"wire_name": "ownerPassword"}, ) """ The main owner password that is used for document encryption and for setting/removing restrictions. """ - user_password: Optional[str] = field( + user_password: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userPassword"}, ) """ The optional user password will be asked for viewing and printing document. """ - encryption_algorithm: Optional[str] = field( + encryption_algorithm: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "encryptionAlgorithm"}, ) """ Encryption algorithm. Valid values: RC4_40bit, RC4_128bit, AES_128bit, AES_256bit. AES_128bit or higher is recommended """ - allow_accessibility_support: Optional[bool] = field( + allow_accessibility_support: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowAccessibilitySupport"}, ) """ @@ -3392,8 +3668,9 @@ class PDFAddSecurityInput: restriction applies when userPassword (if any) is entered. This restriction does not apply if the user enters Owner Password. """ - allow_assembly_document: Optional[bool] = field( + allow_assembly_document: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowAssemblyDocument"}, ) """ @@ -3401,8 +3678,9 @@ class PDFAddSecurityInput: when userPassword (if any) is entered. This restriction does not apply if the user enters Owner Password. """ - allow_print_document: Optional[bool] = field( + allow_print_document: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowPrintDocument"}, ) """ @@ -3410,8 +3688,9 @@ class PDFAddSecurityInput: when userPassword (if any) is entered. This restriction does not apply if the user enters Owner Password. """ - allow_fill_forms: Optional[bool] = field( + allow_fill_forms: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowFillForms"}, ) """ @@ -3420,8 +3699,9 @@ class PDFAddSecurityInput: userPassword (if any) is entered. This restriction does not apply if the user enters Owner Password. """ - allow_modify_document: Optional[bool] = field( + allow_modify_document: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowModifyDocument"}, ) """ @@ -3429,8 +3709,9 @@ class PDFAddSecurityInput: applies when userPassword (if any) is entered. This restriction does not apply if the user enters Owner Password. """ - allow_content_extraction: Optional[bool] = field( + allow_content_extraction: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowContentExtraction"}, ) """ @@ -3438,8 +3719,9 @@ class PDFAddSecurityInput: applies when userPassword (if any) is entered. This restriction does not apply if the user enters Owner Password. """ - allow_modify_annotations: Optional[bool] = field( + allow_modify_annotations: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowModifyAnnotations"}, ) """ @@ -3447,8 +3729,9 @@ class PDFAddSecurityInput: document. Note: this restriction applies when userPassword (if any) is entered. This restriction does not apply if the user enters Owner Password. """ - print_quality: Optional[str] = field( + print_quality: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "printQuality"}, ) """ @@ -3456,9 +3739,9 @@ class PDFAddSecurityInput: Note: this restriction applies when userPassword (if any) is entered. This restriction does not apply if the user enters Owner Password. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -3466,8 +3749,9 @@ class PDFAddSecurityInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -3476,7 +3760,7 @@ class PDFAddSecurityInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -3490,31 +3774,34 @@ class PDFAddSecurityResponse: Response for PDF Add Security """ - url: Optional[str] = None - job_id: Optional[str] = field( + url: Optional[str] = dataclass_field(default=None, kw_only=True) + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -3524,16 +3811,16 @@ class PDFSecurityRemoveInput: PDF Remove Security """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - password: Optional[str] = None + password: str """The owner/user password to open files and remove security features.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -3541,8 +3828,9 @@ class PDFSecurityRemoveInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -3551,7 +3839,7 @@ class PDFSecurityRemoveInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -3565,31 +3853,34 @@ class PDFSecurityRemoveResponse: Response for PDF Remove Security """ - url: Optional[str] = None - job_id: Optional[str] = field( + url: Optional[str] = dataclass_field(default=None, kw_only=True) + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -3599,19 +3890,20 @@ class PDFFromXLSXLSXInput: PDF From Spreadsheet """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - worksheet_index: Optional[str] = field( + worksheet_index: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "worksheetIndex"}, ) """Set the WorkSheet index (Default is 0).""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -3619,8 +3911,9 @@ class PDFFromXLSXLSXInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -3629,7 +3922,7 @@ class PDFFromXLSXLSXInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -3643,31 +3936,34 @@ class PDFFromXLSXLSXResponse: Response for PDF From Spreadsheet """ - url: Optional[str] = None - job_id: Optional[str] = field( + url: Optional[str] = dataclass_field(default=None, kw_only=True) + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -3677,29 +3973,32 @@ class XLStoCSVInput: Spreadsheet to CSV """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - worksheet_index: Optional[str] = field( + worksheet_index: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "worksheetIndex"}, ) """Set the WorkSheet index (Default is 0).""" - quotation_symbol: Optional[str] = field( + quotation_symbol: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "quotationSymbol"}, ) """Set the CSV Quotation Symbol""" - separator_symbol: Optional[str] = field( + separator_symbol: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "separatorSymbol"}, ) """Set the CSV Separator Symbol""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -3707,8 +4006,9 @@ class XLStoCSVInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -3717,7 +4017,7 @@ class XLStoCSVInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -3731,27 +4031,29 @@ class XLStoCSVResponse: Response for Spreadsheet to CSV """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -3761,19 +4063,20 @@ class XLStoJSONInput: Spreadsheet to JSON """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - worksheet_index: Optional[str] = field( + worksheet_index: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "worksheetIndex"}, ) """Set the WorkSheet index (Default is 0).""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -3781,8 +4084,9 @@ class XLStoJSONInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -3791,7 +4095,7 @@ class XLStoJSONInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -3805,27 +4109,29 @@ class XLStoJSONResponse: Response for Spreadsheet to JSON """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -3835,19 +4141,20 @@ class XLStoHTMLInput: Spreadsheet to HTML """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - worksheet_index: Optional[str] = field( + worksheet_index: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "worksheetIndex"}, ) """Set the WorkSheet index (Default is 0).""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -3855,8 +4162,9 @@ class XLStoHTMLInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -3865,7 +4173,7 @@ class XLStoHTMLInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -3879,27 +4187,29 @@ class XLStoHTMLResponse: Response for Spreadsheet to HTML """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -3909,19 +4219,20 @@ class XLStoTXTInput: Spreadsheet to TXT """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - worksheet_index: Optional[str] = field( + worksheet_index: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "worksheetIndex"}, ) """Set the WorkSheet index (Default is 0).""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -3929,8 +4240,9 @@ class XLStoTXTInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -3939,7 +4251,7 @@ class XLStoTXTInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -3953,27 +4265,29 @@ class XLStoTXTResponse: Response for Spreadsheet to TXT """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -3983,19 +4297,20 @@ class XLStoXMLInput: Spreadsheet to XML """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - worksheet_index: Optional[str] = field( + worksheet_index: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "worksheetIndex"}, ) """Set the WorkSheet index (Default is 0).""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output.""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -4003,8 +4318,9 @@ class XLStoXMLInput: The maximum duration for link expiration varies based on your current subscription plan. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -4013,7 +4329,7 @@ class XLStoXMLInput: of the process and retrieve the output while you can proceed with other tasks without waiting for this process to finish. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ You can set additional and extra options using this parameter that allows you to set custom configuration. Explore PDF.co knowledgebase @@ -4027,27 +4343,29 @@ class XLStoXMLResponse: Response for Spreadsheet to XML """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -4057,14 +4375,14 @@ class PDFRotatePagesInput: Rotate PDF Pages """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - angle: Optional[int] = None + angle: Optional[int] = dataclass_field(default=None, kw_only=True) """Angle in degrees. Supported values 90, 180, and 270.""" - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -4074,7 +4392,7 @@ class PDFRotatePagesInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -4082,16 +4400,17 @@ class PDFRotatePagesInput: The maximum duration for link expiration varies based on your current subscription plan. """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password of the PDF file""" - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -4108,32 +4427,35 @@ class PDFRotatePagesResponse: Response for Rotate PDF Pages """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -4143,12 +4465,12 @@ class PDFAutoRotatePagesInput: Rotate PDF Pages (Auto) """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - lang: Optional[str] = None + lang: Optional[str] = dataclass_field(default=None, kw_only=True) """ the language for OCR (text from image) to use for scanned PDF, PNG, and JPG documents input when extracting text. The default is \"eng\". Other @@ -4158,7 +4480,7 @@ class PDFAutoRotatePagesInput: You can also use 2 languages simultaneously like this: eng+deu or jpn+kor (any combination). """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -4166,16 +4488,17 @@ class PDFAutoRotatePagesInput: The maximum duration for link expiration varies based on your current subscription plan. """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password of the PDF file""" - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -4192,32 +4515,35 @@ class PDFAutoRotatePagesResponse: Response for Rotate PDF Pages (Auto) """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -4227,12 +4553,12 @@ class PDFDeletePagesInput: PDF Delete Pages """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Comma-separated list of page indices (or ranges) to process. The very first page starts at 0 (zero). To set a range use the dash -, for example: @@ -4242,9 +4568,9 @@ class PDFDeletePagesInput: means first page, then 3rd page to 6th page, and then the range from 8th (index = 7) page till the end of the document. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -4252,14 +4578,15 @@ class PDFDeletePagesInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -4276,32 +4603,35 @@ class PDFDeletePagesResponse: Response for PDF Delete Pages """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -4311,14 +4641,14 @@ class PDFCompressInput: PDF Compress and Optimize """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """File name for the generated output""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -4326,16 +4656,17 @@ class PDFCompressInput: The maximum duration for link expiration varies based on your current subscription plan. """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password of the PDF file""" - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -4352,32 +4683,35 @@ class PDFCompressResponse: Response for PDF Compress and Optimize """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -4387,34 +4721,35 @@ class PDFClassifierInput: Document Classifier """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - rulescsv: Optional[str] = None + rulescsv: Optional[str] = dataclass_field(default=None, kw_only=True) """ Define custom classification rules in CSV format. Rules are in CSV format where each row contains: \"class name, logic (AND or OR (default)), and keywords\" separated by a comma. Each row is separated by the \\n symbol. """ - rulescsvurl: Optional[str] = None + rulescsvurl: Optional[str] = dataclass_field(default=None, kw_only=True) """ Instead of inline CSV you can use this parameter and set the URL to a CSV file with classification rules. This is useful if you have a separate developer working on CSV rules. """ - case_sensitive: Optional[bool] = field( + case_sensitive: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "caseSensitive"}, ) """Defines if keywords in rules are case-sensitive or not.""" - inline: Optional[bool] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Set to true to return results inside the response. Otherwise, the endpoint will return a link to the output file generated. """ - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -4422,16 +4757,17 @@ class PDFClassifierInput: The maximum duration for link expiration varies based on your current subscription plan. """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password of the PDF file""" - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -4448,34 +4784,37 @@ class PDFClassifierResponse: Response for Document Classifier """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """body""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """pageCount""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -4485,47 +4824,48 @@ class EmailSendInput: Send Email with Attachments """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - from_: Optional[str] = field(default=None, metadata={"wire_name": "from"}) + from_: str = dataclass_field(metadata={"wire_name": "from"}) """ The \"From\" field with sender name and email. Example: John Doe """ - to: Optional[str] = None + to: str """ The \"To\" field with receiver name and email. Example: Partner """ - subject: Optional[str] = None + subject: str """The subject for the outgoing email""" - bodytext: Optional[str] = None + bodytext: Optional[str] = dataclass_field(default=None, kw_only=True) """Plain text version of the outgoing email message.""" - bodyhtml: Optional[str] = None + bodyhtml: Optional[str] = dataclass_field(default=None, kw_only=True) """HTML version of the outgoing email message.""" - smtpserver: Optional[str] = None + smtpserver: str """SMTP server address""" - smtpport: Optional[str] = None + smtpport: str """SMTP port""" - smtpusername: Optional[str] = None + smtpusername: str """SMTP server username""" - smtppassword: Optional[str] = None + smtppassword: str """ SMTP server password, If you use Gmail then you need to generate an app-specific password as instructed at https://support.google.com/accounts/answer/185833. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -4542,23 +4882,25 @@ class EmailSendResponse: Response for Send Email with Attachments """ - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -4568,19 +4910,20 @@ class EmailDecodeInput: Email Information """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -4597,29 +4940,31 @@ class EmailDecodeResponse: Response for Email Information """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """body""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -4629,19 +4974,20 @@ class EmailAttachmentExtractionInput: Email Attachment Extraction """ - url: Optional[str] = None + url: str """ URL to the source file. Supports links from Google Drive, Dropbox, and PDF.co built-in files storage. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """ @@ -4658,29 +5004,31 @@ class EmailAttachmentExtractionResponse: Response for Email Attachment Extraction """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """url""" - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """body""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """error""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """status""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """credits""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """remainingCredits""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """duration""" @@ -4690,15 +5038,15 @@ class PDFAttachmentExtractionInput: PDF Attachment Extraction """ - url: Optional[str] = None + url: str """Url to the source PDF document""" - inline: Optional[bool] = None + inline: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Determines whether to return output in response or link to output file. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Base file name for new PDF files""" - expiration: Optional[int] = None + expiration: Optional[int] = dataclass_field(default=None, kw_only=True) """ Set the expiration time for the output link in minutes (default is 60 i.e 60 minutes or 1 hour), After this specified duration, any generated output @@ -4706,14 +5054,15 @@ class PDFAttachmentExtractionInput: The maximum duration for link expiration varies based on your current subscription plan. """ - profiles: Optional[str] = None + profiles: Optional[str] = dataclass_field(default=None, kw_only=True) """ Use this parameter to set additional configurations for fine-tuning and extra options. Explore PDF.co knowledgebase (https://developer.pdf.co/api/profiles/index.html) for profile examples. """ - async_: Optional[bool] = field( + async_: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "async"}, ) """Creates a background processing job.""" @@ -4725,32 +5074,35 @@ class PDFAttachmentExtractionResponse: Response for PDF Attachment Extraction """ - urls: Optional[List[str]] = None + urls: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """urls""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document URL.""" - job_id: Optional[str] = field( + job_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobId"}, ) """jobId""" - page_count: Optional[int] = field( + page_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageCount"}, ) """Number of pages in the output document.""" - error: Optional[bool] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether the operation is successful or not.""" - status: Optional[int] = None + status: Optional[int] = dataclass_field(default=None, kw_only=True) """Status code for HTTP response""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Output document name""" - credits: Optional[int] = None + credits: Optional[int] = dataclass_field(default=None, kw_only=True) """PDF.co credits used for this request""" - duration: Optional[int] = None + duration: Optional[int] = dataclass_field(default=None, kw_only=True) """Request execution duration""" - remaining_credits: Optional[int] = field( + remaining_credits: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "remainingCredits"}, ) """PDF.co account remaining credits""" @@ -4764,16 +5116,16 @@ class PdfcoClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -4784,8 +5136,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -4793,8 +5145,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -4806,7 +5158,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -4821,9 +5173,9 @@ def __init__( def connector_name(self) -> str: return "pdfco" - async def html_to_pdf_async( + def html_to_pdf( self, - input: HtmlToPdfInput, + input: HtmlToPdfInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -4836,12 +5188,28 @@ async def html_to_pdf_async( Convert HTML code snippet into full featured PDF. Please see api documentation at https://developer.pdf.co/api/pdf-to-html/index.html for comprehensive guidelines. + + Swagger operation ID: `HtmlToPdf`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1/pdf/convert/from/html" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4855,6 +5223,7 @@ async def html_to_pdf_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4862,9 +5231,9 @@ async def html_to_pdf_async( return json.loads(response.text) - async def url_to_pdf_async( + def url_to_pdf( self, - input: UrlToPdfInput, + input: UrlToPdfInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -4877,10 +5246,26 @@ async def url_to_pdf_async( Create PDF from URL. Please see api documentation at https://developer.pdf.co/api/pdf-from-url/index.html for comprehensive guidelines. + + Swagger operation ID: `UrlToPdf`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/convert/from/url" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4894,6 +5279,7 @@ async def url_to_pdf_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4901,9 +5287,9 @@ async def url_to_pdf_async( return json.loads(response.text) - async def pdf_filler_async( + def pdf_filler( self, - input: PdfFillerInput, + input: PdfFillerInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -4917,10 +5303,26 @@ async def pdf_filler_async( new pdf from templates. Please see api documentation at https://developer.pdf.co/api/pdf-add/index.html for comprehensive guidelines. + + Swagger operation ID: `PdfFiller`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/edit/add" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4934,6 +5336,7 @@ async def pdf_filler_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4941,9 +5344,9 @@ async def pdf_filler_async( return json.loads(response.text) - async def merge_pdf_simplified_async( + def merge_pdf_simplified( self, - input: MergePdfSimplifiedInput, + input: MergePdfSimplifiedInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -4956,10 +5359,26 @@ async def merge_pdf_simplified_async( Merge PDF from two or more PDF files into a new one. Please see api documentation at https://developer.pdf.co/api/pdf-merge/index.html for comprehensive guidelines. + + Swagger operation ID: `MergePdfSimplified`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/merge" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4973,6 +5392,7 @@ async def merge_pdf_simplified_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4980,9 +5400,9 @@ async def merge_pdf_simplified_async( return json.loads(response.text) - async def merge_pdf_async( + def merge_pdf( self, - input: MergePdfInput, + input: MergePdfInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -4997,10 +5417,26 @@ async def merge_pdf_async( xlsx, rtf, txt, png, jpg. Please see api documentation at https://developer.pdf.co/api/pdf-merge/index.html#post-tag-pdf-merge2 for comprehensive guidelines. + + Swagger operation ID: `MergePdf`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/merge2" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5014,6 +5450,7 @@ async def merge_pdf_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5021,9 +5458,9 @@ async def merge_pdf_async( return json.loads(response.text) - async def split_pdf_async( + def split_pdf( self, - input: SplitPdfInput, + input: SplitPdfInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5037,10 +5474,26 @@ async def split_pdf_async( numbers and page ranges. Please see api documentation at https://developer.pdf.co/api/pdf-split/index.html for comprehensive guidelines. + + Swagger operation ID: `SplitPdf`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/split" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5054,6 +5507,7 @@ async def split_pdf_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5061,9 +5515,9 @@ async def split_pdf_async( return json.loads(response.text) - async def split_pdf2_async( + def split_pdf2( self, - input: SplitPdf2Input, + input: SplitPdf2Input | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5077,10 +5531,26 @@ async def split_pdf2_async( expressions) or barcode. Please see api documentation at https://developer.pdf.co/api/pdf-split/index.html#post-tag-pdf-split2 for comprehensive guidelines. + + Swagger operation ID: `SplitPdf2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/split2" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5094,6 +5564,7 @@ async def split_pdf2_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5101,9 +5572,9 @@ async def split_pdf2_async( return json.loads(response.text) - async def pdf_search_text_async( + def pdf_search_text( self, - input: PDFSearchTextInput, + input: PDFSearchTextInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5117,10 +5588,26 @@ async def pdf_search_text_async( Please see api documentation at https://developer.pdf.co/api/pdf-find/index.html for comprehensive guidelines. + + Swagger operation ID: `PDFSearchText`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/find" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5134,6 +5621,7 @@ async def pdf_search_text_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5141,9 +5629,9 @@ async def pdf_search_text_async( return json.loads(response.text) - async def document_parser_async( + def document_parser( self, - input: DocumentParserInput, + input: DocumentParserInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5159,10 +5647,26 @@ async def document_parser_async( documentation at https://developer.pdf.co/api/document-parser/index.html for comprehensive guidelines. + + Swagger operation ID: `DocumentParser`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/documentparser" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5176,6 +5680,7 @@ async def document_parser_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5183,9 +5688,9 @@ async def document_parser_async( return json.loads(response.text) - async def job_check_async( + def job_check( self, - input: JobCheckInput, + input: JobCheckInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5199,10 +5704,26 @@ async def job_check_async( API. Please see api documentation at https://developer.pdf.co/api/background-job-check/index.html for comprehensive guidelines. + + Swagger operation ID: `JobCheck`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/job/check" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5216,6 +5737,7 @@ async def job_check_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5223,9 +5745,9 @@ async def job_check_async( return json.loads(response.text) - async def barcode_generator_async( + def barcode_generator( self, - input: BarcodeGeneratorInput, + input: BarcodeGeneratorInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5240,10 +5762,26 @@ async def barcode_generator_async( documentation at https://developer.pdf.co/api/barcode-generator/index.html for comprehensive guidelines. + + Swagger operation ID: `BarcodeGenerator`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/barcode/generate" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5257,6 +5795,7 @@ async def barcode_generator_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5264,9 +5803,9 @@ async def barcode_generator_async( return json.loads(response.text) - async def barcode_reader_async( + def barcode_reader( self, - input: BarcodeReaderInput, + input: BarcodeReaderInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5281,12 +5820,28 @@ async def barcode_reader_async( other barcodes. Please see api documentation at https://developer.pdf.co/api/barcode-reader/index.html for comprehensive guidelines. + + Swagger operation ID: `BarcodeReader`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1/barcode/read/from/url" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5300,6 +5855,7 @@ async def barcode_reader_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5307,9 +5863,9 @@ async def barcode_reader_async( return json.loads(response.text) - async def pdf_info_reader_async( + def pdf_info_reader( self, - input: PDFInfoReaderInput, + input: PDFInfoReaderInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5323,10 +5879,26 @@ async def pdf_info_reader_async( security permissions. Please see api documentation at https://developer.pdf.co/api/pdf-info-reader/index.html for comprehensive guidelines. + + Swagger operation ID: `PDFInfoReader`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/info" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5340,6 +5912,7 @@ async def pdf_info_reader_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5347,9 +5920,9 @@ async def pdf_info_reader_async( return json.loads(response.text) - async def pdf_forms_info_reader_async( + def pdf_forms_info_reader( self, - input: PDFFormsInfoReaderInput, + input: PDFFormsInfoReaderInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5363,10 +5936,26 @@ async def pdf_forms_info_reader_async( api documentation at https://developer.pdf.co/api/pdf-forms-info-reader/index.html for comprehensive guidelines. + + Swagger operation ID: `PDFFormsInfoReader`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/info/fields" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5380,6 +5969,7 @@ async def pdf_forms_info_reader_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5387,9 +5977,9 @@ async def pdf_forms_info_reader_async( return json.loads(response.text) - async def pdf_find_table_async( + def pdf_find_table( self, - input: PDFFindTableInput, + input: PDFFindTableInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5404,10 +5994,26 @@ async def pdf_find_table_async( about columns detected in these tables. Please see api documentation at https://developer.pdf.co/api/pdf-find/index.html#post-tag-pdf-find-table for comprehensive guidelines. + + Swagger operation ID: `PDFFindTable`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/find/table" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5421,6 +6027,7 @@ async def pdf_find_table_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5428,9 +6035,9 @@ async def pdf_find_table_async( return json.loads(response.text) - async def search_and_replace_async( + def search_and_replace( self, - input: SearchAndReplaceInput, + input: SearchAndReplaceInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5444,12 +6051,28 @@ async def search_and_replace_async( new text. Please see api documentation at https://developer.pdf.co/api/pdf-search-and-replace-text/index.html#post-tag-pdf-edit-replace-text for comprehensive guidelines. + + Swagger operation ID: `SearchAndReplace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1/pdf/edit/replace-text" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5463,6 +6086,7 @@ async def search_and_replace_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5470,9 +6094,9 @@ async def search_and_replace_async( return json.loads(response.text) - async def search_and_replace_with_image_async( + def search_and_replace_with_image( self, - input: SearchAndReplaceWithImageInput, + input: SearchAndReplaceWithImageInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5486,13 +6110,29 @@ async def search_and_replace_with_image_async( documentation at https://developer.pdf.co/api/pdf-search-and-replace-text/index.html#post-tag-pdf-edit-replace-text-with-image for comprehensive guidelines. + + Swagger operation ID: `SearchAndReplaceWithImage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1/pdf/edit/replace-text-with-image" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5506,6 +6146,7 @@ async def search_and_replace_with_image_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5513,9 +6154,9 @@ async def search_and_replace_with_image_async( return json.loads(response.text) - async def search_and_delete_text_async( + def search_and_delete_text( self, - input: SearchAndDeleteTextInput, + input: SearchAndDeleteTextInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5529,10 +6170,26 @@ async def search_and_delete_text_async( documentation at https://developer.pdf.co/api/pdf-search-and-delete-text/index.html for comprehensive guidelines. + + Swagger operation ID: `SearchAndDeleteText`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/edit/delete-text" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5546,6 +6203,7 @@ async def search_and_delete_text_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5553,9 +6211,9 @@ async def search_and_delete_text_async( return json.loads(response.text) - async def pdf_searchable_async( + def pdf_searchable( self, - input: PDFSearchableInput, + input: PDFSearchableInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5569,10 +6227,26 @@ async def pdf_searchable_async( see api documentation at https://developer.pdf.co/api/pdf-make-text-searchable-or-unsearchable/index.html#post-tag-pdf-makesearchable for comprehensive guidelines. + + Swagger operation ID: `PDFSearchable`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/makesearchable" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5586,6 +6260,7 @@ async def pdf_searchable_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5593,9 +6268,9 @@ async def pdf_searchable_async( return json.loads(response.text) - async def pdf_unsearchable_async( + def pdf_unsearchable( self, - input: PDFUnSearchableInput, + input: PDFUnSearchableInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5609,10 +6284,26 @@ async def pdf_unsearchable_async( then scanned your PDF. Please see api documentation at https://developer.pdf.co/api/pdf-make-text-searchable-or-unsearchable/index.html#post-tag-pdf-makeunsearchable for comprehensive guidelines. + + Swagger operation ID: `PDFUnSearchable`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/makeunsearchable" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5626,6 +6317,7 @@ async def pdf_unsearchable_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5633,9 +6325,9 @@ async def pdf_unsearchable_async( return json.loads(response.text) - async def pdf_to_csv_async( + def pdf_to_csv( self, - input: PDFToCSVInput, + input: PDFToCSVInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5649,10 +6341,26 @@ async def pdf_to_csv_async( columns, rows, and tables. Please see api documentation at https://developer.pdf.co/api/pdf-to-csv/index.html for comprehensive guidelines. + + Swagger operation ID: `PDFToCSV`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/csv" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5666,6 +6374,7 @@ async def pdf_to_csv_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5673,9 +6382,9 @@ async def pdf_to_csv_async( return json.loads(response.text) - async def pdf_to_json_async( + def pdf_to_json( self, - input: PDFToJSONInput, + input: PDFToJSONInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5689,10 +6398,26 @@ async def pdf_to_json_async( fonts, images, vectors, and formatting preserved. Please see api documentation at https://developer.pdf.co/api/pdf-to-json/index.html for comprehensive guidelines. + + Swagger operation ID: `PDFToJSON`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/json2" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5706,6 +6431,7 @@ async def pdf_to_json_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5713,9 +6439,9 @@ async def pdf_to_json_async( return json.loads(response.text) - async def pdf_to_json_meta_async( + def pdf_to_json_meta( self, - input: PDFToJSONMetaInput, + input: PDFToJSONMetaInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5730,12 +6456,28 @@ async def pdf_to_json_meta_async( documentation at https://developer.pdf.co/api/pdf-to-json/index.html#post-tag-pdf-convert-to-json-meta for comprehensive guidelines. + + Swagger operation ID: `PDFToJSONMeta`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1/pdf/convert/to/json-meta" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5749,6 +6491,7 @@ async def pdf_to_json_meta_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5756,9 +6499,9 @@ async def pdf_to_json_meta_async( return json.loads(response.text) - async def pdf_to_text_async( + def pdf_to_text( self, - input: PDFToTextInput, + input: PDFToTextInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5772,10 +6515,26 @@ async def pdf_to_text_async( see api documentation at https://developer.pdf.co/api/pdf-to-text/index.html for comprehensive guidelines. + + Swagger operation ID: `PDFToText`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/text" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5789,6 +6548,7 @@ async def pdf_to_text_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5796,9 +6556,9 @@ async def pdf_to_text_async( return json.loads(response.text) - async def pdf_to_text_simple_async( + def pdf_to_text_simple( self, - input: PDFToTextSimpleInput, + input: PDFToTextSimpleInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5812,12 +6572,28 @@ async def pdf_to_text_simple_async( Please see api documentation at https://developer.pdf.co/api/pdf-to-text/index.html#post-tag-pdf-convert-to-text-simple for comprehensive guidelines. + + Swagger operation ID: `PDFToTextSimple`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1/pdf/convert/to/text-simple" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5831,6 +6607,7 @@ async def pdf_to_text_simple_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5838,9 +6615,9 @@ async def pdf_to_text_simple_async( return json.loads(response.text) - async def pdf_to_xls_async( + def pdf_to_xls( self, - input: PDFToXLSInput, + input: PDFToXLSInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5854,10 +6631,26 @@ async def pdf_to_xls_async( preserved. Please see api documentation at https://developer.pdf.co/api/pdf-to-excel/index.html#post-tag-pdf-convert-to-xls for comprehensive guidelines. + + Swagger operation ID: `PDFToXLS`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/xls" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5871,6 +6664,7 @@ async def pdf_to_xls_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5878,9 +6672,9 @@ async def pdf_to_xls_async( return json.loads(response.text) - async def pdf_to_xlsx_async( + def pdf_to_xlsx( self, - input: PDFToXLSXInput, + input: PDFToXLSXInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5894,10 +6688,26 @@ async def pdf_to_xlsx_async( preserved. Please see api documentation at https://developer.pdf.co/api/pdf-to-excel/index.html#post-tag-pdf-convert-to-xlsx for comprehensive guidelines. + + Swagger operation ID: `PDFToXLSX`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/xlsx" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5911,6 +6721,7 @@ async def pdf_to_xlsx_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5918,9 +6729,9 @@ async def pdf_to_xlsx_async( return json.loads(response.text) - async def pdf_to_xml_async( + def pdf_to_xml( self, - input: PDFToXMLInput, + input: PDFToXMLInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5934,10 +6745,26 @@ async def pdf_to_xml_async( images, objects positions. Please see api documentation at https://developer.pdf.co/api/pdf-to-xml/index.html for comprehensive guidelines. + + Swagger operation ID: `PDFToXML`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/xml" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5951,6 +6778,7 @@ async def pdf_to_xml_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5958,9 +6786,9 @@ async def pdf_to_xml_async( return json.loads(response.text) - async def pdf_to_jpg_async( + def pdf_to_jpg( self, - input: PDFToJPGInput, + input: PDFToJPGInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -5974,10 +6802,26 @@ async def pdf_to_jpg_async( thumbnail generation and previews. Please see api documentation at https://developer.pdf.co/api/pdf-to-image/index.html#post-tag-pdf-convert-to-jpg for comprehensive guidelines. + + Swagger operation ID: `PDFToJPG`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/jpg" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5991,6 +6835,7 @@ async def pdf_to_jpg_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5998,9 +6843,9 @@ async def pdf_to_jpg_async( return json.loads(response.text) - async def pdf_to_png_async( + def pdf_to_png( self, - input: PDFToPNGInput, + input: PDFToPNGInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6014,10 +6859,26 @@ async def pdf_to_png_async( thumbnail generation and previews. Please see api documentation at https://developer.pdf.co/api/pdf-to-image/index.html#post-tag-pdf-convert-to-png for comprehensive guidelines. + + Swagger operation ID: `PDFToPNG`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/png" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6031,6 +6892,7 @@ async def pdf_to_png_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6038,9 +6900,9 @@ async def pdf_to_png_async( return json.loads(response.text) - async def pdf_to_webp_async( + def pdf_to_webp( self, - input: PDFToWEBPInput, + input: PDFToWEBPInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6054,10 +6916,26 @@ async def pdf_to_webp_async( thumbnail generation and previews. Please see api documentation at https://developer.pdf.co/api/pdf-to-image/index.html#post-tag-pdf-convert-to-webp for comprehensive guidelines. + + Swagger operation ID: `PDFToWEBP`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/webp" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6071,6 +6949,7 @@ async def pdf_to_webp_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6078,9 +6957,9 @@ async def pdf_to_webp_async( return json.loads(response.text) - async def pdf_to_tiff_async( + def pdf_to_tiff( self, - input: PDFToTIFFInput, + input: PDFToTIFFInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6095,10 +6974,26 @@ async def pdf_to_tiff_async( documentation at https://developer.pdf.co/api/pdf-to-image/index.html#post-tag-pdf-convert-to-tiff for comprehensive guidelines. + + Swagger operation ID: `PDFToTIFF`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/convert/to/tiff" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6112,6 +7007,7 @@ async def pdf_to_tiff_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6119,9 +7015,9 @@ async def pdf_to_tiff_async( return json.loads(response.text) - async def pdf_from_csv_async( + def pdf_from_csv( self, - input: PDFFromCSVInput, + input: PDFFromCSVInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6135,10 +7031,26 @@ async def pdf_from_csv_async( see api documentation at https://developer.pdf.co/api/pdf-from-document/index.html#post-tag-pdf-convert-from-csv for comprehensive guidelines. + + Swagger operation ID: `PDFFromCSV`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/convert/from/csv" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6152,6 +7064,7 @@ async def pdf_from_csv_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6159,9 +7072,9 @@ async def pdf_from_csv_async( return json.loads(response.text) - async def pdf_from_doc_async( + def pdf_from_doc( self, - input: PDFFromDocInput, + input: PDFFromDocInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6175,10 +7088,26 @@ async def pdf_from_doc_async( documentation at https://developer.pdf.co/api/pdf-from-document/index.html#post-tag-pdf-convert-from-doc for comprehensive guidelines. + + Swagger operation ID: `PDFFromDoc`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/convert/from/doc" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6192,6 +7121,7 @@ async def pdf_from_doc_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6199,9 +7129,9 @@ async def pdf_from_doc_async( return json.loads(response.text) - async def pdf_from_images_async( + def pdf_from_images( self, - input: PDFFromImagesInput, + input: PDFFromImagesInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6215,12 +7145,28 @@ async def pdf_from_images_async( api documentation at https://developer.pdf.co/api/pdf-from-image/index.html for comprehensive guidelines. + + Swagger operation ID: `PDFFromImages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1/pdf/convert/from/image" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6234,6 +7180,7 @@ async def pdf_from_images_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6241,9 +7188,9 @@ async def pdf_from_images_async( return json.loads(response.text) - async def pdf_from_email_async( + def pdf_from_email( self, - input: PDFFromEmailInput, + input: PDFFromEmailInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6258,12 +7205,28 @@ async def pdf_from_email_async( Please see api documentation at https://developer.pdf.co/api/pdf-from-email/index.html for comprehensive guidelines. + + Swagger operation ID: `PDFFromEmail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1/pdf/convert/from/email" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6277,6 +7240,7 @@ async def pdf_from_email_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6284,9 +7248,9 @@ async def pdf_from_email_async( return json.loads(response.text) - async def pdf_add_security_async( + def pdf_add_security( self, - input: PDFAddSecurityInput, + input: PDFAddSecurityInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6300,10 +7264,26 @@ async def pdf_add_security_async( documentation at https://developer.pdf.co/api/password-and-security/index.html#post-tag-pdf-security-add for comprehensive guidelines. + + Swagger operation ID: `PDFAddSecurity`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/security/add" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6317,6 +7297,7 @@ async def pdf_add_security_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6324,9 +7305,9 @@ async def pdf_add_security_async( return json.loads(response.text) - async def pdf_security_remove_async( + def pdf_security_remove( self, - input: PDFSecurityRemoveInput, + input: PDFSecurityRemoveInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6340,10 +7321,26 @@ async def pdf_security_remove_async( documentation at https://developer.pdf.co/api/password-and-security/index.html#post-tag-pdf-security-remove for comprehensive guidelines. + + Swagger operation ID: `PDFSecurityRemove`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/security/remove" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6357,6 +7354,7 @@ async def pdf_security_remove_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6364,9 +7362,9 @@ async def pdf_security_remove_async( return json.loads(response.text) - async def pdf_from_xls_xlsx_async( + def pdf_from_xls_xlsx( self, - input: PDFFromXLSXLSXInput, + input: PDFFromXLSXLSXInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6379,10 +7377,26 @@ async def pdf_from_xls_xlsx_async( Create PDF from XLS, XLSX spreadsheet. Please see api documentation at https://developer.pdf.co/api/convert-excel/index.html#post-tag-xls-convert-to-pdf for comprehensive guidelines. + + Swagger operation ID: `PDFFromXLSXLSX`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/xls/convert/to/pdf" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6396,6 +7410,7 @@ async def pdf_from_xls_xlsx_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6403,9 +7418,9 @@ async def pdf_from_xls_xlsx_async( return json.loads(response.text) - async def xls_to_csv_async( + def xls_to_csv( self, - input: XLStoCSVInput, + input: XLStoCSVInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6419,10 +7434,26 @@ async def xls_to_csv_async( documentation at https://developer.pdf.co/api/convert-excel/index.html#post-tag-xls-convert-to-csv for comprehensive guidelines. + + Swagger operation ID: `XLStoCSV`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/xls/convert/to/csv" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6436,6 +7467,7 @@ async def xls_to_csv_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6443,9 +7475,9 @@ async def xls_to_csv_async( return json.loads(response.text) - async def xls_to_json_async( + def xls_to_json( self, - input: XLStoJSONInput, + input: XLStoJSONInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6458,10 +7490,26 @@ async def xls_to_json_async( Convert XLS/XLSX into JSON file. Please see api documentation at https://developer.pdf.co/api/convert-excel/index.html#post-tag-xls-convert-to-json for comprehensive guidelines. + + Swagger operation ID: `XLStoJSON`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/xls/convert/to/json" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6475,6 +7523,7 @@ async def xls_to_json_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6482,9 +7531,9 @@ async def xls_to_json_async( return json.loads(response.text) - async def xls_to_html_async( + def xls_to_html( self, - input: XLStoHTMLInput, + input: XLStoHTMLInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6497,10 +7546,26 @@ async def xls_to_html_async( Convert XLS/XLSX into HTML file. Please see api documentation at https://developer.pdf.co/api/convert-excel/index.html#post-tag-xls-convert-to-html for comprehensive guidelines. + + Swagger operation ID: `XLStoHTML`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/xls/convert/to/html" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6514,6 +7579,7 @@ async def xls_to_html_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6521,9 +7587,9 @@ async def xls_to_html_async( return json.loads(response.text) - async def xls_to_txt_async( + def xls_to_txt( self, - input: XLStoTXTInput, + input: XLStoTXTInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6536,10 +7602,26 @@ async def xls_to_txt_async( Convert XLS/XLSX or CSV into Text file. Please see api documentation at https://developer.pdf.co/api/convert-excel/index.html#post-tag-xls-convert-to-txt for comprehensive guidelines. + + Swagger operation ID: `XLStoTXT`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/xls/convert/to/txt" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6553,6 +7635,7 @@ async def xls_to_txt_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6560,9 +7643,9 @@ async def xls_to_txt_async( return json.loads(response.text) - async def xls_to_xml_async( + def xls_to_xml( self, - input: XLStoXMLInput, + input: XLStoXMLInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6575,10 +7658,26 @@ async def xls_to_xml_async( Convert XLS/XLSX or CSV into XML file. Please see api documentation at https://developer.pdf.co/api/convert-excel/index.html#post-tag-xls-convert-to-xml for comprehensive guidelines. + + Swagger operation ID: `XLStoXML`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/xls/convert/to/xml" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6592,6 +7691,7 @@ async def xls_to_xml_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6599,9 +7699,9 @@ async def xls_to_xml_async( return json.loads(response.text) - async def pdf_rotate_pages_async( + def pdf_rotate_pages( self, - input: PDFRotatePagesInput, + input: PDFRotatePagesInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6614,10 +7714,26 @@ async def pdf_rotate_pages_async( Rotate PDF Pages. Please see api documentation at https://developer.pdf.co/api/pdf-rotate-pages/index.html for comprehensive guidelines. + + Swagger operation ID: `PDFRotatePages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/edit/rotate" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6631,6 +7747,7 @@ async def pdf_rotate_pages_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6638,9 +7755,9 @@ async def pdf_rotate_pages_async( return json.loads(response.text) - async def pdf_auto_rotate_pages_async( + def pdf_auto_rotate_pages( self, - input: PDFAutoRotatePagesInput, + input: PDFAutoRotatePagesInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6654,10 +7771,26 @@ async def pdf_auto_rotate_pages_async( based on text analysis. Please see api documentation at https://developer.pdf.co/api/pdf-rotate-pages/index.html#post-tag-pdf-edit-rotate-auto for comprehensive guidelines. + + Swagger operation ID: `PDFAutoRotatePages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/edit/rotate/auto" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6671,6 +7804,7 @@ async def pdf_auto_rotate_pages_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6678,9 +7812,9 @@ async def pdf_auto_rotate_pages_async( return json.loads(response.text) - async def pdf_delete_pages_async( + def pdf_delete_pages( self, - input: PDFDeletePagesInput, + input: PDFDeletePagesInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6693,12 +7827,28 @@ async def pdf_delete_pages_async( Delete pages in PDF. Please see api documentation at https://developer.pdf.co/api/pdf-delete-pages/index.html for comprehensive guidelines. + + Swagger operation ID: `PDFDeletePages`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1/pdf/edit/delete-pages" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6712,6 +7862,7 @@ async def pdf_delete_pages_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6719,9 +7870,9 @@ async def pdf_delete_pages_async( return json.loads(response.text) - async def pdf_compress_async( + def pdf_compress( self, - input: PDFCompressInput, + input: PDFCompressInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6734,10 +7885,26 @@ async def pdf_compress_async( Optimize PDF document to reduce its size. Please see api documentation at https://developer.pdf.co/api/pdf-optimize/index.html for comprehensive guidelines. + + Swagger operation ID: `PDFCompress`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/optimize" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6751,6 +7918,7 @@ async def pdf_compress_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6758,9 +7926,9 @@ async def pdf_compress_async( return json.loads(response.text) - async def pdf_classifier_async( + def pdf_classifier( self, - input: PDFClassifierInput, + input: PDFClassifierInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6776,10 +7944,26 @@ async def pdf_classifier_async( api documentation at https://developer.pdf.co/api/document-classifier/index.html for comprehensive guidelines. + + Swagger operation ID: `PDFClassifier`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/pdf/classifier" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6793,6 +7977,7 @@ async def pdf_classifier_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6800,9 +7985,9 @@ async def pdf_classifier_async( return json.loads(response.text) - async def email_send_async( + def email_send( self, - input: EmailSendInput, + input: EmailSendInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6815,10 +8000,26 @@ async def email_send_async( Send Email with Attachments. Please see api documentation at https://developer.pdf.co/api/email-send-and-decode/index.html for comprehensive guidelines. + + Swagger operation ID: `EmailSend`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/email/send" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6832,6 +8033,7 @@ async def email_send_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6839,9 +8041,9 @@ async def email_send_async( return json.loads(response.text) - async def email_decode_async( + def email_decode( self, - input: EmailDecodeInput, + input: EmailDecodeInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6855,10 +8057,26 @@ async def email_decode_async( Please see api documentation at https://developer.pdf.co/api/email-send-and-decode/index.html#post-tag-email-decode for comprehensive guidelines. + + Swagger operation ID: `EmailDecode`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/email/decode" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6872,6 +8090,7 @@ async def email_decode_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6879,9 +8098,9 @@ async def email_decode_async( return json.loads(response.text) - async def email_attachment_extraction_async( + def email_attachment_extraction( self, - input: EmailAttachmentExtractionInput, + input: EmailAttachmentExtractionInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6895,12 +8114,28 @@ async def email_attachment_extraction_async( documentation at https://developer.pdf.co/api/email-send-and-decode/index.html#post-tag-email-extract-attachments for comprehensive guidelines. + + Swagger operation ID: `EmailAttachmentExtraction`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1/email/extract-attachments" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6914,6 +8149,7 @@ async def email_attachment_extraction_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6921,9 +8157,9 @@ async def email_attachment_extraction_async( return json.loads(response.text) - async def pdf_attachment_extraction_async( + def pdf_attachment_extraction( self, - input: PDFAttachmentExtractionInput, + input: PDFAttachmentExtractionInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6937,12 +8173,28 @@ async def pdf_attachment_extraction_async( documentation at https://developer.pdf.co/api/extract-attachments/index.html for comprehensive guidelines. + + Swagger operation ID: `PDFAttachmentExtraction`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1/pdf/attachments/extract" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6956,6 +8208,7 @@ async def pdf_attachment_extraction_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/pipedrive.py b/src/azure/connectors/pipedrive.py index d5546d3..e8edc73 100644 --- a/src/azure/connectors/pipedrive.py +++ b/src/azure/connectors/pipedrive.py @@ -5,25 +5,48 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "PipedriveClient", + "ActivityResponse", + "AddActivityRequest", + "AddDealRequest", + "DealResponse", + "DealResponseV2", + "ListActivityTypesResponse", + "ListCurrenciesResponse", + "ListDealsResponse", + "ListOrganizationsResponse", + "ListPersonsResponse", + "ListPipelinesResponse", + "ListStagesResponse", + "StageResponse", + "TrigNewActivityResponse", + "TrigNewDealResponse", + "UpdateDealStageRequest", + "UpdateDealStatusRequest", + "TRIGGER_OPERATIONS", +] + # Type Definitions -TrigNewActivityResponse = List["ActivityResponse"] +TrigNewActivityResponse = List["ActivityResponse | Mapping[str, Any]"] @dataclass @@ -32,81 +55,81 @@ class DealResponse: Response for Get deal by id """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the deal.""" - creator_user_id: Optional[Dict[str, Any]] = None - user_id: Optional[Dict[str, Any]] = None - person_id: Optional[Dict[str, Any]] = None - org_id: Optional[Dict[str, Any]] = None - status: Optional[str] = None + creator_user_id: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + user_id: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + person_id: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + org_id: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Open, won, lost or deleted.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of the deal.""" - value: Optional[float] = None + value: Optional[float] = dataclass_field(default=None, kw_only=True) """Monetary value of the deal.""" - currency: Optional[str] = None + currency: Optional[str] = dataclass_field(default=None, kw_only=True) """Currency associated with the deal value.""" - add_time: Optional[str] = None + add_time: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - update_time: Optional[str] = None + update_time: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - stage_id: Optional[int] = None + stage_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ID of stage the deal is placed in a pipeline.""" - stage_name: Optional[str] = None + stage_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of stage the deal is placed in a pipeline""" - stage_change_time: Optional[str] = None + stage_change_time: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - active: Optional[bool] = None + active: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the deal is active.""" - deleted: Optional[bool] = None + deleted: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the deal has been deleted.""" - next_activity_date: Optional[str] = None + next_activity_date: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-dd""" - next_activity_time: Optional[str] = None + next_activity_time: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - next_activity_id: Optional[int] = None + next_activity_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the next activity.""" - last_activity_id: Optional[int] = None + last_activity_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the last activity.""" - last_activity_date: Optional[str] = None + last_activity_date: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-dd""" - lost_reason: Optional[str] = None + lost_reason: Optional[str] = dataclass_field(default=None, kw_only=True) """Message about why the deal was lost (to be used when status=lost).""" - visible_to: Optional[str] = None + visible_to: Optional[str] = dataclass_field(default=None, kw_only=True) """Owner, followers or entire company.""" - close_time: Optional[str] = None + close_time: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - pipeline_id: Optional[int] = None + pipeline_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of pipeline the deal is associated with.""" - products_count: Optional[int] = None + products_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of products associated with the deal.""" - files_count: Optional[int] = None + files_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of files associated with the deal.""" - notes_count: Optional[int] = None + notes_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of notes associated with the deal.""" - followers_count: Optional[int] = None + followers_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of followers associated with the deal.""" - email_messages_count: Optional[int] = None + email_messages_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of email messages associated with the deal.""" - activities_count: Optional[int] = None + activities_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of activities associated with the deal.""" - done_activities_count: Optional[int] = None + done_activities_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of done activities associated with the deal.""" - undone_activities_count: Optional[int] = None + undone_activities_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of undone activities associated with the deals.""" - reference_activities_count: Optional[int] = None + reference_activities_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of referenced activities associated with the deal.""" - participants_count: Optional[int] = None + participants_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of participants associated with the deal.""" - expected_close_date: Optional[str] = None + expected_close_date: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-dd""" - next_activity_subject: Optional[str] = None + next_activity_subject: Optional[str] = dataclass_field(default=None, kw_only=True) """Subject of next activity associated with the deal.""" - next_activity_type: Optional[str] = None + next_activity_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Type of next activity associated with the deal.""" - next_activity_duration: Optional[str] = None + next_activity_duration: Optional[str] = dataclass_field(default=None, kw_only=True) """Duration of next activity associated with the deal.""" - next_activity_note: Optional[str] = None + next_activity_note: Optional[str] = dataclass_field(default=None, kw_only=True) """Notes for next activity associated with the deal""" @@ -116,51 +139,55 @@ class ActivityResponse: Response for Add activity """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique id of the activity.""" - user_id: Optional[int] = None + user_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the user whom the activity is assigned to.""" - done: Optional[bool] = None + done: Optional[bool] = dataclass_field(default=None, kw_only=True) """0 = Not done, 1 = Done""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type of the activity.""" - due_date: Optional[str] = None + due_date: Optional[str] = dataclass_field(default=None, kw_only=True) """YYYY-MM-DD""" - due_time: Optional[str] = None + due_time: Optional[str] = dataclass_field(default=None, kw_only=True) """HH:MM""" - duration: Optional[str] = None + duration: Optional[str] = dataclass_field(default=None, kw_only=True) """HH:MM""" - subject: Optional[str] = None + subject: Optional[str] = dataclass_field(default=None, kw_only=True) """Subject of the activity.""" - deal_id: Optional[int] = None + deal_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of deal the activity is associated with.""" - deal_title: Optional[str] = None + deal_title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of deal the activity is associated with.""" - org_id: Optional[int] = None + org_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of organization the activity is associated with.""" - org_name: Optional[str] = None + org_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of organization the activity is associated with.""" - person_id: Optional[int] = None + person_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of person the activity is associated with.""" - person_name: Optional[str] = None + person_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of person the activity is associated with.""" - add_time: Optional[str] = None + add_time: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - update_time: Optional[str] = None + update_time: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - marked_as_done_time: Optional[str] = None + marked_as_done_time: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - gcal_event_id: Optional[str] = None + gcal_event_id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id of the google calendar event.""" - google_calendar_id: Optional[str] = None + google_calendar_id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id of the google calendar.""" - note: Optional[str] = None + note: Optional[str] = dataclass_field(default=None, kw_only=True) """Note of the activity (HTML format).""" - assigned_to_user_id: Optional[int] = None + assigned_to_user_id: Optional[int] = dataclass_field(default=None, kw_only=True) """User id of user whom the activity is assigned to.""" - created_by_user_id: Optional[int] = None + created_by_user_id: Optional[int] = dataclass_field(default=None, kw_only=True) """User id of user that created the activity.""" - owner_name: Optional[str] = None + owner_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the activity owner.""" @@ -170,9 +197,9 @@ class StageResponse: Response for Get stage by id """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Stage Id""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Stage name""" @@ -182,83 +209,83 @@ class DealResponseV2: Response for Add deal (V2) """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the deal.""" - creator_user_id: Optional[Dict[str, Any]] = None - user_id: Optional[Dict[str, Any]] = None - person_id: Optional[Dict[str, Any]] = None - org_id: Optional[Dict[str, Any]] = None - status: Optional[str] = None + creator_user_id: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + user_id: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + person_id: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + org_id: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Open, won, lost or deleted.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of the deal.""" - value: Optional[float] = None + value: Optional[float] = dataclass_field(default=None, kw_only=True) """Monetary value of the deal.""" - currency: Optional[str] = None + currency: Optional[str] = dataclass_field(default=None, kw_only=True) """Currency associated with the deal value.""" - add_time: Optional[str] = None + add_time: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - update_time: Optional[str] = None + update_time: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - stage_id: Optional[int] = None + stage_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ID of stage the deal is placed in a pipeline.""" - stage_change_time: Optional[str] = None + stage_change_time: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - active: Optional[bool] = None + active: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the deal is active.""" - deleted: Optional[bool] = None + deleted: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the deal has been deleted.""" - next_activity_date: Optional[str] = None + next_activity_date: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-dd""" - next_activity_time: Optional[str] = None + next_activity_time: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - next_activity_id: Optional[int] = None + next_activity_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the next activity.""" - last_activity_id: Optional[int] = None + last_activity_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the last activity.""" - last_activity_date: Optional[str] = None + last_activity_date: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-dd""" - lost_reason: Optional[str] = None + lost_reason: Optional[str] = dataclass_field(default=None, kw_only=True) """Message about why the deal was lost (to be used when status=lost).""" - visible_to: Optional[str] = None + visible_to: Optional[str] = dataclass_field(default=None, kw_only=True) """Owner, followers or entire company.""" - close_time: Optional[str] = None + close_time: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-ddTHH:mm:ss.fffZ""" - pipeline_id: Optional[int] = None + pipeline_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of pipeline the deal is associated with.""" - products_count: Optional[int] = None + products_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of products associated with the deal.""" - files_count: Optional[int] = None + files_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of files associated with the deal.""" - notes_count: Optional[int] = None + notes_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of notes associated with the deal.""" - followers_count: Optional[int] = None + followers_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of followers associated with the deal.""" - email_messages_count: Optional[int] = None + email_messages_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of email messages associated with the deal.""" - activities_count: Optional[int] = None + activities_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of activities associated with the deal.""" - done_activities_count: Optional[int] = None + done_activities_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of done activities associated with the deal.""" - undone_activities_count: Optional[int] = None + undone_activities_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of undone activities associated with the deals.""" - reference_activities_count: Optional[int] = None + reference_activities_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of referenced activities associated with the deal.""" - participants_count: Optional[int] = None + participants_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of participants associated with the deal.""" - expected_close_date: Optional[str] = None + expected_close_date: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-dd""" - next_activity_subject: Optional[str] = None + next_activity_subject: Optional[str] = dataclass_field(default=None, kw_only=True) """Subject of next activity associated with the deal.""" - next_activity_type: Optional[str] = None + next_activity_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Type of next activity associated with the deal.""" - next_activity_duration: Optional[str] = None + next_activity_duration: Optional[str] = dataclass_field(default=None, kw_only=True) """Duration of next activity associated with the deal.""" - next_activity_note: Optional[str] = None + next_activity_note: Optional[str] = dataclass_field(default=None, kw_only=True) """Notes for next activity associated with the deal""" -TrigNewDealResponse = List["DealResponseV2"] +TrigNewDealResponse = List["DealResponseV2 | Mapping[str, Any]"] @dataclass @@ -267,7 +294,7 @@ class ListDealsResponse: Response for List deals """ - data: Optional[List[Dict[str, Any]]] = None + data: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """data""" @@ -277,24 +304,24 @@ class AddActivityRequest: Definition: AddActivityRequest """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """Activity type.""" - subject: Optional[str] = None + subject: str """Subject of the activity.""" - due_date: Optional[str] = None + due_date: Optional[str] = dataclass_field(default=None, kw_only=True) """YYYY-MM-DD""" - due_time: Optional[str] = None + due_time: Optional[str] = dataclass_field(default=None, kw_only=True) """HH:MM""" - duration: Optional[str] = None + duration: Optional[str] = dataclass_field(default=None, kw_only=True) """HH:MM""" - note: Optional[str] = None - user_id: Optional[int] = None + note: Optional[str] = dataclass_field(default=None, kw_only=True) + user_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the user whom the activity will be assigned to.""" - deal_id: Optional[int] = None + deal_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ID of deal the activity will be associated with.""" - person_id: Optional[int] = None + person_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of person the activity will be associated with.""" - org_id: Optional[int] = None + org_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ID of the organization the activity will be associated with.""" @@ -304,25 +331,25 @@ class AddDealRequest: Definition: AddDealRequest """ - title: Optional[str] = None + title: str """Title of the deal.""" - pipeline_id: Optional[str] = None + pipeline_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The id of the pipeline to fetch stages from.""" - stage_id: Optional[str] = None + stage_id: Optional[str] = dataclass_field(default=None, kw_only=True) """Stage of the deal.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status of the deal.""" - value: Optional[int] = None + value: Optional[int] = dataclass_field(default=None, kw_only=True) """Monetary value of the deal.""" - currency: Optional[str] = None + currency: Optional[str] = dataclass_field(default=None, kw_only=True) """Currency of the deal.""" - person_id: Optional[str] = None + person_id: Optional[str] = dataclass_field(default=None, kw_only=True) """User id of person the deal is associated with.""" - org_id: Optional[str] = None + org_id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id of the organization associated with the deal.""" - expected_close_date: Optional[str] = None + expected_close_date: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-dd""" - visible_to: Optional[str] = None + visible_to: Optional[str] = dataclass_field(default=None, kw_only=True) """Owner, followers or entire company.""" @@ -332,11 +359,11 @@ class UpdateDealStageRequest: Definition: UpdateDealStageRequest """ - pipeline_id: Optional[str] = None + pipeline_id: str """The id of the pipeline to fetch stages from.""" - stage_id: Optional[str] = None + stage_id: str """Stage of the deal.""" - expected_close_date: Optional[str] = None + expected_close_date: Optional[str] = dataclass_field(default=None, kw_only=True) """yyyy-MM-dd""" @@ -346,9 +373,9 @@ class UpdateDealStatusRequest: Definition: UpdateDealStatusRequest """ - status: Optional[str] = None + status: str """Status of the deal.""" - lost_reason: Optional[str] = None + lost_reason: Optional[str] = dataclass_field(default=None, kw_only=True) """Message about why the deal was lost.""" @@ -358,9 +385,9 @@ class ListActivityTypesResponse: Definition: ListActivityTypesResponse """ - success: Optional[bool] = None + success: Optional[bool] = dataclass_field(default=None, kw_only=True) """success""" - data: Optional[List[Dict[str, Any]]] = None + data: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """data""" @@ -370,7 +397,7 @@ class ListCurrenciesResponse: Definition: ListCurrenciesResponse """ - data: Optional[List[Dict[str, Any]]] = None + data: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """data""" @@ -380,7 +407,7 @@ class ListPipelinesResponse: Definition: ListPipelinesResponse """ - data: Optional[List[Dict[str, Any]]] = None + data: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """data""" @@ -390,7 +417,12 @@ class ListStagesResponse: Definition: ListStagesResponse """ - data: Optional[List[StageResponse]] = None + data: Optional[ + List[StageResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """data""" @@ -400,7 +432,7 @@ class ListPersonsResponse: Definition: ListPersonsResponse """ - data: Optional[List[Dict[str, Any]]] = None + data: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """data""" @@ -410,7 +442,7 @@ class ListOrganizationsResponse: Definition: ListOrganizationsResponse """ - data: Optional[List[Dict[str, Any]]] = None + data: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """data""" @@ -422,16 +454,16 @@ class PipedriveClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -442,8 +474,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -451,8 +483,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -464,7 +496,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -479,7 +511,46 @@ def __init__( def connector_name(self) -> str: return "pipedrive" - async def get_deal_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def get_deal( self, deal_id: int, *, @@ -492,13 +563,28 @@ async def get_deal_async( Get deal by id This operation retrieves all details of an existing deal, given its id. + + Swagger operation ID: `GetDeal`. + + Args: + deal_id: Deal. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1/deals/{quote(str(deal_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -512,6 +598,7 @@ async def get_deal_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -519,9 +606,9 @@ async def get_deal_async( return json.loads(response.text) - async def update_deal_status_async( + def update_deal_status( self, - input: UpdateDealStatusRequest, + input: UpdateDealStatusRequest | Mapping[str, Any], deal_id: int, *, timeout: Optional[float] = None, @@ -534,13 +621,30 @@ async def update_deal_status_async( This operation is used to update the status associated with a deal, given its id. + + Swagger operation ID: `UpdateDealStatus`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + deal_id: Deal. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/update_status_deal/v1/deals/{quote(str(deal_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -554,6 +658,7 @@ async def update_deal_status_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -561,9 +666,9 @@ async def update_deal_status_async( return json.loads(response.text) - async def add_activity_async( + def add_activity( self, - input: AddActivityRequest, + input: AddActivityRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -575,10 +680,26 @@ async def add_activity_async( This operation is used to create a new activity for the authorized account. + + Swagger operation ID: `AddActivity`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/activities" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -592,6 +713,7 @@ async def add_activity_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -599,7 +721,7 @@ async def add_activity_async( return json.loads(response.text) - async def get_stage_async( + def get_stage( self, stage_id: int, *, @@ -612,13 +734,28 @@ async def get_stage_async( Get stage by id This operation returns data about a specific stage. + + Swagger operation ID: `GetStage`. + + Args: + stage_id: Stage Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1/stages/{quote(str(stage_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -632,6 +769,7 @@ async def get_stage_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -639,9 +777,9 @@ async def get_stage_async( return json.loads(response.text) - async def add_deal_async( + def add_deal( self, - input: AddDealRequest, + input: AddDealRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -652,10 +790,26 @@ async def add_deal_async( Add deal This operation creates a new deal for the authorized account. + + Swagger operation ID: `AddDealV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/connector-v2/v1/deals" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -669,6 +823,7 @@ async def add_deal_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -676,9 +831,9 @@ async def add_deal_async( return json.loads(response.text) - async def update_deal_stage_async( + def update_deal_stage( self, - input: UpdateDealStageRequest, + input: UpdateDealStageRequest | Mapping[str, Any], deal_id: int, *, timeout: Optional[float] = None, @@ -691,6 +846,23 @@ async def update_deal_stage_async( This operation is used to update the stage associated with a deal, given its id. + + Swagger operation ID: `UpdateDealStageV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + deal_id: Deal. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -701,7 +873,7 @@ async def update_deal_stage_async( f"/{quote(str(deal_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -715,6 +887,7 @@ async def update_deal_stage_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -722,41 +895,80 @@ async def update_deal_stage_async( return json.loads(response.text) - async def list_deals_async( + def list_deals( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List deals List deals + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListDeals`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/deals" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("data", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/planner.py b/src/azure/connectors/planner.py index a64e9bc..9f487a7 100644 --- a/src/azure/connectors/planner.py +++ b/src/azure/connectors/planner.py @@ -5,21 +5,45 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "PlannerClient", + "AppliedCategories", + "AssignUsersInput", + "CreateBucketInput", + "CreateBucketResponse", + "CreateTaskRequest", + "ErrorResponse", + "GetPlanDetailsResponse", + "GetTaskDetailsResponse", + "GetTaskResponse", + "GetTaskResponseV2", + "GetTaskResponseV3", + "ListBucketsResponse", + "ListGroupsResponse", + "ListMyPlansResponse", + "ListTasksResponse", + "UnassignUsersInput", + "UpdateTaskDetailsRequest", + "UpdateTaskRequest", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +53,7 @@ class UnassignUsersInput: Remove assignees from a task """ - assignments: Optional[str] = None + assignments: str """ Semi-colon separated ids or email addresses of users who should be unassigned to this task. @@ -42,65 +66,77 @@ class GetTaskResponseV2: Response for Remove assignees from a task """ - created_by: Optional[Dict[str, Any]] = field( + created_by: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdBy"}, ) - plan_id: Optional[str] = field( + plan_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "planId"}, ) """The id of the plan this task belongs to.""" - bucket_id: Optional[str] = field( + bucket_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "bucketId"}, ) """The id of the bucket this task belongs to.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the task.""" - percent_complete: Optional[int] = field( + percent_complete: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "percentComplete"}, ) """The completion percentage of the task.""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """The start datetime of the task.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """The datetime the task was created.""" - due_date_time: Optional[str] = field( + due_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dueDateTime"}, ) """The datetime the task is due.""" - has_description: Optional[bool] = field( + has_description: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasDescription"}, ) """Set to true if the task has a description.""" - completed_date_time: Optional[str] = field( + completed_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "completedDateTime"}, ) """The datetime the task was completed.""" - reference_count: Optional[int] = field( + reference_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "referenceCount"}, ) """The number of external references that exist on the task.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The id of the task.""" - applied_categories: Optional[AppliedCategories] = field( + applied_categories: Optional[AppliedCategories | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "appliedCategories"}, ) - assignments: Optional[List[Dict[str, Any]]] = field( + assignments: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_assignments"}, ) @@ -111,7 +147,7 @@ class AssignUsersInput: Add assignees to a task """ - assignments: Optional[str] = None + assignments: str """ Semi-colon separated ids or email addresses of users who should be assigned to this task. @@ -124,7 +160,7 @@ class ListMyPlansResponse: Response for List plans for a group """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -133,11 +169,12 @@ class GetPlanDetailsResponse: Response for Get plan details """ - category_descriptions: Optional[Dict[str, Any]] = field( + category_descriptions: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "categoryDescriptions"}, ) - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the plan details""" @@ -147,17 +184,11 @@ class CreateBucketInput: Create a bucket """ - name: Optional[str] = None + name: str """Name of the bucket""" - group_id: Optional[str] = field( - default=None, - metadata={"wire_name": "groupId"}, - ) + group_id: str = dataclass_field(metadata={"wire_name": "groupId"}) """The group to retrieve the plan.""" - plan_id: Optional[str] = field( - default=None, - metadata={"wire_name": "planId"}, - ) + plan_id: str = dataclass_field(metadata={"wire_name": "planId"}) """The plan for the new bucket.""" @@ -167,19 +198,21 @@ class CreateBucketResponse: Response for Create a bucket """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the bucket""" - plan_id: Optional[str] = field( + plan_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "planId"}, ) """Plan ID to which the bucket belongs""" - order_hint: Optional[str] = field( + order_hint: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "orderHint"}, ) """Hint used to order items of this type in a list view""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID of the bucket""" @@ -189,64 +222,75 @@ class GetTaskResponseV3: Response for Create a task """ - created_by: Optional[Dict[str, Any]] = field( + created_by: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdBy"}, ) - plan_id: Optional[str] = field( + plan_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "planId"}, ) """The id of the plan this task belongs to.""" - bucket_id: Optional[str] = field( + bucket_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "bucketId"}, ) """The id of the bucket this task belongs to.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the task.""" - percent_complete: Optional[int] = field( + percent_complete: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "percentComplete"}, ) """The completion percentage of the task.""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """The start datetime of the task.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """The datetime the task was created.""" - due_date_time: Optional[str] = field( + due_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dueDateTime"}, ) """The datetime the task is due.""" - has_description: Optional[bool] = field( + has_description: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasDescription"}, ) """Set to true if the task has a description.""" - completed_date_time: Optional[str] = field( + completed_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "completedDateTime"}, ) """The datetime the task was completed.""" - reference_count: Optional[int] = field( + reference_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "referenceCount"}, ) """The number of external references that exist on the task.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The id of the task.""" - applied_categories: Optional[AppliedCategories] = field( + applied_categories: Optional[AppliedCategories | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "appliedCategories"}, ) - priority: Optional[int] = None + priority: Optional[int] = dataclass_field(default=None, kw_only=True) """ Priority of the task. Valid range of values is between 0 and 10 (inclusive), with increasing value being lower priority (0 has the highest @@ -256,8 +300,9 @@ class GetTaskResponseV3: value 1 for \"urgent\", 3 for \"important\", 5 for \"medium\", and 9 for \"low\". """ - assignments: Optional[List[Dict[str, Any]]] = field( + assignments: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_assignments"}, ) @@ -268,13 +313,13 @@ class GetTaskDetailsResponse: Response for Get task details """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the task.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The id of the task.""" - references: Optional[List[Dict[str, Any]]] = None + references: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """The collection of references on the task""" - checklist: Optional[List[Dict[str, Any]]] = None + checklist: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """The collection of checklist items on the task.""" @@ -284,7 +329,7 @@ class ListBucketsResponse: Response for List buckets """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -293,9 +338,15 @@ class ListTasksResponse: Response for List my tasks """ - value: Optional[List[GetTaskResponseV2]] = None - next_link: Optional[str] = field( + value: Optional[ + List[GetTaskResponseV2 | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, + ) + next_link: Optional[str] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """Link to get next page of results""" @@ -307,7 +358,7 @@ class ListGroupsResponse: Response for List groups that I am member of """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """value""" @@ -317,11 +368,11 @@ class UpdateTaskDetailsRequest: Definition: UpdateTaskDetails_Request """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the task.""" - references: Optional[List[Dict[str, Any]]] = None + references: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """The collection of references on the task""" - checklist: Optional[List[Dict[str, Any]]] = None + checklist: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """The collection of checklist items on the task""" @@ -331,30 +382,35 @@ class UpdateTaskRequest: Definition: UpdateTask_Request """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the plan (maximum of 255 chars).""" - due_date_time: Optional[str] = field( + due_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dueDateTime"}, ) """The datetime the task is due (Ex. '2018-04-13T00:42:19.284Z').""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """The datetime the task starts (Ex. '2018-04-13T00:42:19.284Z').""" - percent_complete: Optional[int] = field( + percent_complete: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "percentComplete"}, ) """The completion percentage of the task.""" - bucket_id: Optional[str] = field( + bucket_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "bucketId"}, ) """The bucket to place this task in.""" - applied_categories: Optional[AppliedCategories] = field( + applied_categories: Optional[AppliedCategories | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "appliedCategories"}, ) @@ -365,43 +421,41 @@ class CreateTaskRequest: Definition: CreateTask_Request """ - group_id: Optional[str] = field( - default=None, - metadata={"wire_name": "groupId"}, - ) + group_id: str = dataclass_field(metadata={"wire_name": "groupId"}) """The group to retrieve the plan.""" - plan_id: Optional[str] = field( - default=None, - metadata={"wire_name": "planId"}, - ) + plan_id: str = dataclass_field(metadata={"wire_name": "planId"}) """The plan for the new task.""" - title: Optional[str] = None + title: str """The title of the new task (maximum of 255 chars).""" - bucket_id: Optional[str] = field( + bucket_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "bucketId"}, ) """The bucket to place this task in.""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """The datetime the task starts (Ex. '2018-04-13T00:42:19.284Z').""" - due_date_time: Optional[str] = field( + due_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dueDateTime"}, ) """The datetime the task is due (Ex. '2018-04-13T00:42:19.284Z').""" - assignments: Optional[str] = None + assignments: Optional[str] = dataclass_field(default=None, kw_only=True) """ Semi-colon separated ids or email addresses of users to assign this task to. """ - applied_categories: Optional[AppliedCategories] = field( + applied_categories: Optional[AppliedCategories | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "appliedCategories"}, ) - priority: Optional[int] = None + priority: Optional[int] = dataclass_field(default=None, kw_only=True) """ Priority of the task. Valid range of values is between 0 and 10 (inclusive), with increasing value being lower priority (0 has the highest @@ -419,55 +473,55 @@ class AppliedCategories: Definition: AppliedCategories """ - category1: Optional[bool] = None + category1: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Pink category.""" - category2: Optional[bool] = None + category2: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Red category.""" - category3: Optional[bool] = None + category3: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Yellow category.""" - category4: Optional[bool] = None + category4: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Green category.""" - category5: Optional[bool] = None + category5: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Blue category.""" - category6: Optional[bool] = None + category6: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Purple category.""" - category7: Optional[bool] = None + category7: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Bronze category.""" - category8: Optional[bool] = None + category8: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Lime category.""" - category9: Optional[bool] = None + category9: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Aqua category.""" - category10: Optional[bool] = None + category10: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Gray category.""" - category11: Optional[bool] = None + category11: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Silver category.""" - category12: Optional[bool] = None + category12: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Brown category.""" - category13: Optional[bool] = None + category13: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Cranberry category.""" - category14: Optional[bool] = None + category14: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Orange category.""" - category15: Optional[bool] = None + category15: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Peach category.""" - category16: Optional[bool] = None + category16: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Marigold category.""" - category17: Optional[bool] = None + category17: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Light green category.""" - category18: Optional[bool] = None + category18: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Dark green category.""" - category19: Optional[bool] = None + category19: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Teal category.""" - category20: Optional[bool] = None + category20: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Light blue category.""" - category21: Optional[bool] = None + category21: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Dark blue category.""" - category22: Optional[bool] = None + category22: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Lavender category.""" - category23: Optional[bool] = None + category23: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Plum category.""" - category24: Optional[bool] = None + category24: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Light gray category.""" - category25: Optional[bool] = None + category25: Optional[bool] = dataclass_field(default=None, kw_only=True) """True if the task has the Dark gray category.""" @@ -477,58 +531,68 @@ class GetTaskResponse: Definition: GetTask_Response """ - created_by: Optional[Dict[str, Any]] = field( + created_by: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdBy"}, ) - plan_id: Optional[str] = field( + plan_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "planId"}, ) """The id of the plan this task belongs to.""" - bucket_id: Optional[str] = field( + bucket_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "bucketId"}, ) """The id of the bucket this task belongs to.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the task.""" - percent_complete: Optional[int] = field( + percent_complete: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "percentComplete"}, ) """The completion percentage of the task.""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """The start datetime of the task.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """The datetime the task was created.""" - due_date_time: Optional[str] = field( + due_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dueDateTime"}, ) """The datetime the task is due.""" - has_description: Optional[bool] = field( + has_description: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasDescription"}, ) """Set to true if the task has a description.""" - completed_date_time: Optional[str] = field( + completed_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "completedDateTime"}, ) """The datetime the task was completed.""" - reference_count: Optional[int] = field( + reference_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "referenceCount"}, ) """The number of external references that exist on the task.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The id of the task.""" @@ -538,8 +602,8 @@ class ErrorResponse: Definition: ErrorResponse """ - code: Optional[str] = None - message: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) + message: Optional[str] = dataclass_field(default=None, kw_only=True) # Client Class @@ -550,16 +614,16 @@ class PlannerClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -570,8 +634,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -579,8 +643,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -592,7 +656,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -614,7 +678,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -646,7 +710,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def delete_task_async( + def delete_task( self, id: str, *, @@ -659,13 +723,28 @@ async def delete_task_async( Delete a task Deletes an existing Planner task. + + Swagger operation ID: `DeleteTask`. + + Args: + id: The unique identifier of the task to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/planner/tasks/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -679,11 +758,12 @@ async def delete_task_async( request_url, response.status, response.text, + response=response, ) - async def unassign_users_async( + def unassign_users( self, - input: UnassignUsersInput, + input: UnassignUsersInput | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -695,13 +775,30 @@ async def unassign_users_async( Remove assignees from a task Remove assignees from an existing Planner task. + + Swagger operation ID: `UnassignUsers`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: The unique identifier of the task to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/planner/tasks/{quote(str(id), safe='')}/unassignusers" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -715,6 +812,7 @@ async def unassign_users_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -722,9 +820,9 @@ async def unassign_users_async( return json.loads(response.text) - async def assign_users_async( + def assign_users( self, - input: AssignUsersInput, + input: AssignUsersInput | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -736,13 +834,30 @@ async def assign_users_async( Add assignees to a task Add assignees to an existing Planner task. + + Swagger operation ID: `AssignUsers`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: The unique identifier of the task to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/planner/tasks/{quote(str(id), safe='')}/assignusers" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -756,6 +871,7 @@ async def assign_users_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -763,7 +879,7 @@ async def assign_users_async( return json.loads(response.text) - async def list_group_plans_async( + def list_group_plans( self, group_id: str, *, @@ -771,39 +887,79 @@ async def list_group_plans_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List plans for a group List plans owned by the group specified. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListGroupPlans`. + + Args: + group_id: Id of the group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/groups/{quote(str(group_id), safe='')}/planner/plans" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def get_plan_details_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_plan_details( self, id: str, *, @@ -816,13 +972,28 @@ async def get_plan_details_async( Get plan details Get plan details where the task belongs to + + Swagger operation ID: `GetPlanDetails`. + + Args: + id: The unique plan id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/planner/plans/{quote(str(id), safe='')}/details" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -836,6 +1007,7 @@ async def get_plan_details_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -843,9 +1015,9 @@ async def get_plan_details_async( return json.loads(response.text) - async def create_bucket_async( + def create_bucket( self, - input: CreateBucketInput, + input: CreateBucketInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -856,10 +1028,26 @@ async def create_bucket_async( Create a bucket Create a bucket in Planner for the specified plan and group. + + Swagger operation ID: `CreateBucket_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/v1.0/planner/buckets" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -873,6 +1061,7 @@ async def create_bucket_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -880,9 +1069,9 @@ async def create_bucket_async( return json.loads(response.text) - async def create_task_async( + def create_task( self, - input: CreateTaskRequest, + input: CreateTaskRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -893,10 +1082,26 @@ async def create_task_async( Create a task Create a new task in Planner. + + Swagger operation ID: `CreateTask_V4`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/beta/planner/tasks" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -910,6 +1115,7 @@ async def create_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -917,7 +1123,7 @@ async def create_task_async( return json.loads(response.text) - async def get_task_async( + def get_task( self, id: str, *, @@ -930,13 +1136,28 @@ async def get_task_async( Get a task Get an existing Planner task. + + Swagger operation ID: `GetTask_V2`. + + Args: + id: The unique identifier of the task to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/planner/tasks/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -950,6 +1171,7 @@ async def get_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -957,7 +1179,7 @@ async def get_task_async( return json.loads(response.text) - async def get_task_details_async( + def get_task_details( self, id: str, *, @@ -970,13 +1192,28 @@ async def get_task_details_async( Get task details Get the task details for an existing task. + + Swagger operation ID: `GetTaskDetails_V2`. + + Args: + id: The unique identifier of the task to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/planner/tasks/{quote(str(id), safe='')}/details" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -990,6 +1227,7 @@ async def get_task_details_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -997,7 +1235,7 @@ async def get_task_details_async( return json.loads(response.text) - async def list_buckets_async( + def list_buckets( self, id: str, group_id: str, @@ -1006,11 +1244,31 @@ async def list_buckets_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List buckets List the buckets in a plan. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListBuckets_V3`. + + Args: + id: The unique identifier of the plan. + group_id: The group to retrieve the plan. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1023,50 +1281,93 @@ async def list_buckets_async( query_params.append(f"groupId={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def list_my_tasks_async( + def list_my_tasks( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List my tasks List the tasks assigned to me. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListMyTasks_V2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/me/planner/tasks" + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1079,23 +1380,32 @@ async def list_my_tasks_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def list_tasks_async( + return ItemPaged(get_next, extract_data) + + def list_tasks( self, id: str, group_id: str, @@ -1104,14 +1414,31 @@ async def list_tasks_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List tasks List the tasks in a plan. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTasks_V3`. + + Args: + id: The unique identifier of the plan. + group_id: The group to retrieve the plan. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1124,11 +1451,18 @@ async def list_tasks_async( query_params.append(f"groupId={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1141,25 +1475,34 @@ async def list_tasks_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def update_task_async( + def update_task( self, - input: UpdateTaskRequest, + input: UpdateTaskRequest | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -1171,13 +1514,30 @@ async def update_task_async( Update a task Update an existing Planner task. + + Swagger operation ID: `UpdateTask_V3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: The unique identifier of the task to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v2/v1.0/planner/tasks/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -1191,6 +1551,7 @@ async def update_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1198,9 +1559,9 @@ async def update_task_async( return json.loads(response.text) - async def update_task_details_async( + def update_task_details( self, - input: UpdateTaskDetailsRequest, + input: UpdateTaskDetailsRequest | Mapping[str, Any], id: str, *, timeout: Optional[float] = None, @@ -1212,13 +1573,30 @@ async def update_task_details_async( Update task details Update the task details for an existing task. + + Swagger operation ID: `UpdateTaskDetails_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: The unique identifier of the task to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/planner/tasks/{quote(str(id), safe='')}/details" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -1232,6 +1610,7 @@ async def update_task_details_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1239,41 +1618,80 @@ async def update_task_details_async( return json.loads(response.text) - async def list_groups_async( + def list_groups( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List groups that I am member of Get groups that the user is a direct member of. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListGroups`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/me/memberOf" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/plivo.py b/src/azure/connectors/plivo.py index 7706552..619c3bb 100644 --- a/src/azure/connectors/plivo.py +++ b/src/azure/connectors/plivo.py @@ -5,21 +5,32 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "PlivoClient", + "Call", + "GetMessageResponse", + "ListMessagesResponse", + "MakeCallResponse", + "SMS", + "SendSMSResponse", +] + # Type Definitions @@ -29,11 +40,11 @@ class MakeCallResponse: Response for Make a call """ - api_id: Optional[str] = None + api_id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the API request.""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """Response obtained when the call was made.""" - request_uuid: Optional[str] = None + request_uuid: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the call.""" @@ -43,11 +54,11 @@ class ListMessagesResponse: Response for List all messages """ - api_id: Optional[str] = None + api_id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the API request.""" - meta: Optional[Dict[str, Any]] = None + meta: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Meta information about the response.""" - objects: Optional[List[Dict[str, Any]]] = None + objects: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Details of all messages.""" @@ -57,11 +68,11 @@ class SendSMSResponse: Response for Send SMS """ - api_id: Optional[str] = None + api_id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the API request.""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """Response of the sent message.""" - message_uuid: Optional[List[str]] = None + message_uuid: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Unique ID of the message.""" @@ -71,34 +82,34 @@ class GetMessageResponse: Response for Get message """ - api_id: Optional[str] = None + api_id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the API request.""" - error_code: Optional[str] = None + error_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Delivery error code if the message isn't delivered.""" - from_number: Optional[str] = None + from_number: Optional[str] = dataclass_field(default=None, kw_only=True) """Number from which the message was sent.""" - message_direction: Optional[str] = None + message_direction: Optional[str] = dataclass_field(default=None, kw_only=True) """Direction of the message (inbound/outbound).""" - message_state: Optional[str] = None + message_state: Optional[str] = dataclass_field(default=None, kw_only=True) """Status of the message (queued/sent/delivered/failed).""" - message_time: Optional[str] = None + message_time: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp at which the message was sent or received (yyyy-MM-dd HH:mm:ss UTC). """ - message_type: Optional[str] = None + message_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Type of the message.""" - message_uuid: Optional[str] = None + message_uuid: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the message.""" - resource_uri: Optional[str] = None + resource_uri: Optional[str] = dataclass_field(default=None, kw_only=True) """URI to get details of this single message.""" - to_number: Optional[str] = None + to_number: Optional[str] = dataclass_field(default=None, kw_only=True) """Number to which the message was sent.""" - total_amount: Optional[str] = None + total_amount: Optional[str] = dataclass_field(default=None, kw_only=True) """Amount charged for the message.""" - total_rate: Optional[str] = None + total_rate: Optional[str] = dataclass_field(default=None, kw_only=True) """Rate per unit of the message.""" - units: Optional[int] = None + units: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of units the message was split into.""" @@ -108,11 +119,11 @@ class SMS: Definition: SMS """ - src: Optional[str] = None + src: str """Plivo number from which the message is to be sent.""" - dst: Optional[str] = None + dst: str """Phone number to which the message is to be sent.""" - text: Optional[str] = None + text: str """Text of the message to be sent.""" @@ -122,13 +133,13 @@ class Call: Definition: Call """ - from_: Optional[str] = field(default=None, metadata={"wire_name": "from"}) + from_: str = dataclass_field(metadata={"wire_name": "from"}) """Plivo number to be used to make the call.""" - to: Optional[str] = None + to: str """The phone number to call.""" - answer_url: Optional[str] = None + answer_url: str """URL to be called when the call is made.""" - answer_method: Optional[str] = None + answer_method: Optional[str] = dataclass_field(default=None, kw_only=True) """HTTP Method (GET/POST) that should be used to call the Answer URL.""" @@ -140,16 +151,16 @@ class PlivoClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -160,8 +171,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -169,8 +180,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -182,7 +193,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -197,9 +208,48 @@ def __init__( def connector_name(self) -> str: return "plivo" - async def make_call_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def make_call( self, - input: Call, + input: Call | Mapping[str, Any], auth_id: str, *, timeout: Optional[float] = None, @@ -211,13 +261,30 @@ async def make_call_async( Make a call This operation is used to make a call. + + Swagger operation ID: `MakeCall`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + auth_id: Auth ID of your Plivo account. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1/Account/{quote(str(auth_id), safe='')}/Call/" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -231,6 +298,7 @@ async def make_call_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -238,7 +306,7 @@ async def make_call_async( return json.loads(response.text) - async def list_messages_async( + def list_messages( self, auth_id: str, *, @@ -246,42 +314,82 @@ async def list_messages_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List all messages This operation returns a list of all messages associated with your Plivo account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListMessages`. + + Args: + auth_id: Auth ID of your Plivo account. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1/Account/{quote(str(auth_id), safe='')}/Message/" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("objects", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def send_sms_async( + def send_sms( self, - input: SMS, + input: SMS | Mapping[str, Any], auth_id: str, *, timeout: Optional[float] = None, @@ -293,13 +401,30 @@ async def send_sms_async( Send SMS This operation is used to send a text message. + + Swagger operation ID: `SendSMS`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + auth_id: Auth ID of your Plivo account. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1/Account/{quote(str(auth_id), safe='')}/Message/" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -313,6 +438,7 @@ async def send_sms_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -320,7 +446,7 @@ async def send_sms_async( return json.loads(response.text) - async def get_message_async( + def get_message( self, auth_id: str, message_uuid: str, @@ -335,6 +461,23 @@ async def get_message_async( This operation is used to fetch the details of a message, given the message ID. + + Swagger operation ID: `GetMessage`. + + Args: + auth_id: Auth ID of your Plivo account. + message_uuid: UUID of the message for which the details need to be + fetched. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -345,7 +488,7 @@ async def get_message_async( f"/{quote(str(message_uuid), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -359,6 +502,7 @@ async def get_message_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/plumsail.py b/src/azure/connectors/plumsail.py index dd21963..ee1c282 100644 --- a/src/azure/connectors/plumsail.py +++ b/src/azure/connectors/plumsail.py @@ -5,21 +5,87 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, Dict, List, Any, Mapping from urllib.parse import quote import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.polling import LROPoller +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorPollingMethod, ) +__all__ = [ + "PlumsailClient", + "AddPowerAutomateWebhookData", + "Any2PdfRequest", + "ApplyDocxTemplateRequest", + "ApplyHtmlFlowTemplateRequest", + "ApplyHtmlTemplateResponse", + "ApplyPptxTemplateRequest", + "ApplyXlsxTemplateRequest", + "BooleanResultResponse", + "CompressPdfRequest", + "CreateArchiveRequest", + "Csv2XlsxColumnMapping", + "Csv2XlsxRequest", + "Doc2DocxRequest", + "DocumentContentWithFilenameResponse", + "DocumentProcessingResponse", + "DocumentsArrayResponse", + "DocumentsWithFilenamesResponse", + "Docx2PdfRequest", + "Email2PdfRequest", + "ExtractArchiveRequest", + "FileData", + "FillInPdfFormRequest", + "FlowDocumentsJobsAddWatermarkToPdfInput", + "FlowDocumentsJobsGetPdfFormPostResponse", + "FlowDocumentsJobsSplitPdfInput", + "FlowProcessesFlowJobsExecuteProcessInput", + "GetPdfFormRequest", + "GetPdfProtectionInfoResponse", + "Html2DocxFlowRequest", + "Html2PdfFlowRequest", + "Image2PdfRequest", + "Json2CsvRequest", + "Json2XlsxColumnMapping", + "Json2XlsxRequest", + "LicenseInfo", + "MergeAny2PdfFileData", + "MergeAny2PdfRequest", + "MergeDocxRequest", + "MergeFieldsTemplateRequest", + "MergePdfRequest", + "MergeXlsxRequest", + "ParseCsvFlowRequest", + "ParseCsvSchemaResponse", + "Pdf2ImageRequest", + "Pdf2TextRequest", + "PdfProtectionInfoRequest", + "Ppt2PptxRequest", + "Pptx2PdfRequest", + "ProcessJsonData", + "ProcessSchemaDynamicType", + "ProfileInfo", + "ProtectPdfRequest", + "RegExpMatchRequest", + "RegExpMatchSchemaResponseClass", + "RegExpReplaceRequest", + "RegExpTestRequest", + "SplitPdfRequest", + "StringResultResponse", + "Xls2XlsxRequest", + "Xlsx2PdfRequest", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,22 +95,26 @@ class ProfileInfo: Response for Get Profile Info """ - name: Optional[str] = None - email: Optional[str] = None - license_status: Optional[str] = field( + name: Optional[str] = dataclass_field(default=None, kw_only=True) + email: Optional[str] = dataclass_field(default=None, kw_only=True) + license_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "licenseStatus"}, ) - team_name: Optional[str] = field( + team_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "teamName"}, ) - license_info: Optional[LicenseInfo] = field( + license_info: Optional[LicenseInfo | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "licenseInfo"}, ) - short_user_id: Optional[str] = field( + short_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shortUserId"}, ) @@ -55,8 +125,9 @@ class DocumentProcessingResponse: Response for Create document from PPTX template """ - file_content: Optional[str] = field( + file_content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fileContent"}, ) """The result as a file""" @@ -68,8 +139,9 @@ class ApplyHtmlTemplateResponse: Response for Create HTML from template """ - html_result: Optional[str] = field( + html_result: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "htmlResult"}, ) """Raw HTML result""" @@ -81,7 +153,7 @@ class FlowDocumentsJobsSplitPdfInput: Split PDF """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -94,8 +166,11 @@ class DocumentsWithFilenamesResponse: Response for Split PDF """ - result_files: Optional[List[DocumentContentWithFilenameResponse]] = field( + result_files: Optional[ + List[DocumentContentWithFilenameResponse | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resultFiles"}, ) """Array of raw contents of result files with their filenames""" @@ -107,7 +182,7 @@ class FlowDocumentsJobsGetPdfFormPostResponse: Response for Get Form from PDF """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -120,8 +195,9 @@ class GetPdfProtectionInfoResponse: Response for Get information about PDF protection """ - is_password_protected: Optional[bool] = field( + is_password_protected: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isPasswordProtected"}, ) @@ -132,7 +208,7 @@ class FlowDocumentsJobsAddWatermarkToPdfInput: Add a watermark to PDF """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -145,7 +221,7 @@ class ParseCsvSchemaResponse: Response for Parse CSV """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -158,7 +234,7 @@ class RegExpMatchSchemaResponseClass: Response for Regular Expression Match """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -171,7 +247,7 @@ class StringResultResponse: Response for Regular Expression Replace """ - result: Optional[str] = None + result: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -180,8 +256,9 @@ class BooleanResultResponse: Response for Regular Expression Test """ - is_success: Optional[bool] = field( + is_success: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isSuccess"}, ) @@ -192,10 +269,11 @@ class DocumentContentWithFilenameResponse: Response for Create Archive """ - filename: Optional[str] = None + filename: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the file""" - file_content: Optional[str] = field( + file_content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fileContent"}, ) """File content""" @@ -207,7 +285,7 @@ class FlowProcessesFlowJobsExecuteProcessInput: Start document generation process with json """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -220,15 +298,9 @@ class AddPowerAutomateWebhookData: Definition: AddPowerAutomateWebhookData """ - process_id: Optional[str] = field( - default=None, - metadata={"wire_name": "processId"}, - ) + process_id: str = dataclass_field(metadata={"wire_name": "processId"}) """Name of the process that, when finished, will trigger the flow""" - hook_url: Optional[str] = field( - default=None, - metadata={"wire_name": "hookUrl"}, - ) + hook_url: str = dataclass_field(metadata={"wire_name": "hookUrl"}) """HookUrl""" @@ -238,8 +310,7 @@ class Any2PdfRequest: Definition: Any2PdfRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Content of document that should be converted""" @@ -251,23 +322,19 @@ class ApplyDocxTemplateRequest: Definition: ApplyDocxTemplateRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Content of the template""" - data: Optional[Dict[str, Any]] = None + data: Dict[str, Any] """JSON data that should be applied to the template""" - output_type: Optional[str] = field( - default=None, - metadata={"wire_name": "outputType"}, - ) + output_type: str = dataclass_field(metadata={"wire_name": "outputType"}) """The required document type""" - locale: Optional[str] = None + locale: Optional[str] = dataclass_field(default=None, kw_only=True) """The locale that will be applyed to the document""" - timezone: Optional[str] = None + timezone: Optional[str] = dataclass_field(default=None, kw_only=True) """The time zone of the document""" - engine: Optional[str] = None + engine: Optional[str] = dataclass_field(default=None, kw_only=True) """The engine that will process the template""" @@ -277,13 +344,13 @@ class ApplyHtmlFlowTemplateRequest: Definition: ApplyHtmlFlowTemplateRequest """ - html: Optional[str] = None + html: str """Text HTML template or HTML file template""" - data: Optional[Dict[str, Any]] = None + data: Dict[str, Any] """JSON data that should be applied to the template""" - locale: Optional[str] = None + locale: Optional[str] = dataclass_field(default=None, kw_only=True) """The locale that will be applyed to the document""" - timezone: Optional[str] = None + timezone: Optional[str] = dataclass_field(default=None, kw_only=True) """The time zone of the document""" @@ -293,21 +360,17 @@ class ApplyPptxTemplateRequest: Definition: ApplyPptxTemplateRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Content of the template""" - data: Optional[Dict[str, Any]] = None + data: Dict[str, Any] """JSON data that should be applied to the template""" - output_type: Optional[str] = field( - default=None, - metadata={"wire_name": "outputType"}, - ) + output_type: str = dataclass_field(metadata={"wire_name": "outputType"}) """The required document type""" - locale: Optional[str] = None + locale: Optional[str] = dataclass_field(default=None, kw_only=True) """The locale that will be applyed to the document""" - timezone: Optional[str] = None + timezone: Optional[str] = dataclass_field(default=None, kw_only=True) """The time zone of the document""" @@ -317,21 +380,17 @@ class ApplyXlsxTemplateRequest: Definition: ApplyXlsxTemplateRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Content of the template""" - data: Optional[Dict[str, Any]] = None + data: Dict[str, Any] """JSON data that should be applied to the template""" - output_type: Optional[str] = field( - default=None, - metadata={"wire_name": "outputType"}, - ) + output_type: str = dataclass_field(metadata={"wire_name": "outputType"}) """The required document type""" - locale: Optional[str] = None + locale: Optional[str] = dataclass_field(default=None, kw_only=True) """The locale that will be applyed to the document""" - timezone: Optional[str] = None + timezone: Optional[str] = dataclass_field(default=None, kw_only=True) """The time zone of the document""" @@ -341,20 +400,20 @@ class CompressPdfRequest: Definition: CompressPdfRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Raw content of PDF document""" - lossless_mode: Optional[str] = field( + lossless_mode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "losslessMode"}, ) """ When disabled, compresses the PDF file more effectively, but with a slight loss of image quality. """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password to open PDF file""" @@ -364,14 +423,11 @@ class CreateArchiveRequest: Definition: CreateArchiveRequest """ - file_name: Optional[str] = field( - default=None, - metadata={"wire_name": "fileName"}, - ) + file_name: str = dataclass_field(metadata={"wire_name": "fileName"}) """Name of the archive without the file extension""" - data: Optional[List[FileData]] = None + data: List[FileData | Mapping[str, Any]] """Array of documents to add to the archive""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Archive password""" @@ -381,18 +437,19 @@ class Csv2XlsxColumnMapping: Definition: Csv2XlsxColumnMapping """ - csv_column_index_or_name: Optional[str] = field( - default=None, + csv_column_index_or_name: str = dataclass_field( metadata={"wire_name": "csvColumnIndexOrName"}, ) """CSV column name or column index (1, 2, etc.)""" - xlsx_column_type: Optional[str] = field( + xlsx_column_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "xlsxColumnType"}, ) """Optional. Column type (ShortDateTime, TwoDecimal, etc.)""" - xlsx_column_name: Optional[str] = field( + xlsx_column_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "xlsxColumnName"}, ) """Optional. Rename CSV column to this name""" @@ -404,20 +461,26 @@ class Csv2XlsxRequest: Definition: Csv2XlsxRequest """ - content: Optional[str] = None + content: str """Content of CSV document""" - delimiter: Optional[str] = None + delimiter: Optional[str] = dataclass_field(default=None, kw_only=True) """Delimiter of columns (by default it is just comma)""" - locale: Optional[str] = None + locale: Optional[str] = dataclass_field(default=None, kw_only=True) """The locale that will be applyed to the document""" - limit: Optional[int] = None + limit: Optional[int] = dataclass_field(default=None, kw_only=True) """Returns the first \"n\" rows""" - has_header_records: Optional[bool] = field( + has_header_records: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasHeaderRecords"}, ) """If set to \"Yes\" then headers will be read from the first line.""" - mappings: Optional[List[Csv2XlsxColumnMapping]] = None + mappings: Optional[ + List[Csv2XlsxColumnMapping | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Rename headers and specify types for columns.""" @@ -427,8 +490,7 @@ class Doc2DocxRequest: Definition: Doc2DocxRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Content of document that should be converted""" @@ -440,8 +502,9 @@ class DocumentsArrayResponse: Definition: DocumentsArrayResponse """ - result_files_contents: Optional[List[str]] = field( + result_files_contents: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resultFilesContents"}, ) """The array of raw content of result files""" @@ -453,8 +516,7 @@ class Docx2PdfRequest: Definition: Docx2PdfRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Content of document that should be converted""" @@ -466,13 +528,11 @@ class Email2PdfRequest: Definition: Email2PdfRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Content of the email that should be converted""" - merge_attachments: Optional[bool] = field( - default=None, + merge_attachments: bool = dataclass_field( metadata={"wire_name": "mergeAttachments"}, ) """ @@ -487,17 +547,19 @@ class ExtractArchiveRequest: Definition: ExtractArchiveRequest """ - file_content: Optional[str] = field( + file_content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fileContent"}, ) """Content of archive file""" - include_folders: Optional[bool] = field( + include_folders: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "includeFolders"}, ) """If 'true' files contained in the folders will be extracted""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Archive password""" @@ -507,12 +569,13 @@ class FileData: Definition: FileData """ - file_name: Optional[str] = field( + file_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fileName"}, ) """File name including the file extension""" - content: Optional[str] = None + content: Optional[str] = dataclass_field(default=None, kw_only=True) """Content of the document""" @@ -522,22 +585,21 @@ class FillInPdfFormRequest: Definition: FillInPdfFormRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Raw content of PDF document""" - json_data: Optional[Dict[str, Any]] = field( - default=None, + json_data: Dict[str, Any] = dataclass_field( metadata={"wire_name": "jsonData"}, ) """The data that will be used to fill out the form""" - lock_form_fields: Optional[bool] = field( + lock_form_fields: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lockFormFields"}, ) """Disable fields editing after filling them""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password to open PDF file""" @@ -547,12 +609,11 @@ class GetPdfFormRequest: Definition: GetPdfFormRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Raw content of PDF document""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password to decrypt document""" @@ -562,34 +623,39 @@ class Html2DocxFlowRequest: Definition: Html2DocxFlowRequest """ - file_content: Optional[str] = field( + file_content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fileContent"}, ) """Binary content of the HTML file to convert to DOCX""" - raw_html: Optional[str] = field( + raw_html: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "rawHtml"}, ) """HTML Data to convert to DOCX""" - html_url: Optional[str] = field( + html_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "htmlUrl"}, ) """URL to the web page to convert to DOCX""" - paper_size: Optional[str] = field( + paper_size: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "paperSize"}, ) """Can be A4,A5 etc...""" - orientation: Optional[str] = None + orientation: Optional[str] = dataclass_field(default=None, kw_only=True) """Portrait or Landscape""" - decode_html: Optional[bool] = field( + decode_html: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "decodeHtml"}, ) """Whether HTML should be decoded prior to conversion""" - margins: Optional[str] = None + margins: Optional[str] = dataclass_field(default=None, kw_only=True) """ Page margins in pt. The syntax is the same as in CSS. Example: 25 50 75 100. @@ -602,25 +668,27 @@ class Html2PdfFlowRequest: Definition: Html2PdfFlowRequest """ - html: Optional[str] = None + html: str """HTML markup that should be converted to PDF""" - engine: Optional[str] = None + engine: Optional[str] = dataclass_field(default=None, kw_only=True) """Conversion engine""" - size: Optional[str] = None + size: Optional[str] = dataclass_field(default=None, kw_only=True) """Can be A4,A5 etc...""" - orientation: Optional[str] = None + orientation: Optional[str] = dataclass_field(default=None, kw_only=True) """Portrait or Landscape""" - margins: Optional[str] = None + margins: Optional[str] = dataclass_field(default=None, kw_only=True) """ The page margins. The syntax is the same as in CSS. Example: 25 50 75 100. """ - header_html: Optional[str] = field( + header_html: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "headerHtml"}, ) """HTML markup that should be added as a header""" - footer_html: Optional[str] = field( + footer_html: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "footerHtml"}, ) """HTML markup that should be added as a footer""" @@ -632,16 +700,16 @@ class Image2PdfRequest: Definition: Image2PdfRequest """ - image_per_page: Optional[bool] = field( + image_per_page: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "imagePerPage"}, ) """ Select \"No\" if you don't want each image to be on a separate page. Default is \"Yes\" """ - image_content: Optional[List[str]] = field( - default=None, + image_content: List[str] = dataclass_field( metadata={"wire_name": "imageContent"}, ) """Raw content of the image""" @@ -653,24 +721,26 @@ class Json2CsvRequest: Definition: Json2CsvRequest """ - content: Optional[str] = None + content: Optional[str] = dataclass_field(default=None, kw_only=True) """Optional. Content of the JSON file""" - json_data: Optional[str] = field( + json_data: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jsonData"}, ) """Optional. JSON data to process""" - locale: Optional[str] = None + locale: Optional[str] = dataclass_field(default=None, kw_only=True) """The locale that will be applyed to the document""" - path_to_json_array: Optional[str] = field( + path_to_json_array: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pathToJsonArray"}, ) """ Dot separated path to array in JSON. E.g.: \"data\" or \"prop1.prop2.prop3\" """ - delimiter: Optional[str] = None + delimiter: Optional[str] = dataclass_field(default=None, kw_only=True) """Delimiter of columns in CSV. Default is comma""" @@ -680,18 +750,19 @@ class Json2XlsxColumnMapping: Definition: Json2XlsxColumnMapping """ - json_property: Optional[str] = field( - default=None, + json_property: str = dataclass_field( metadata={"wire_name": "jsonProperty"}, ) """Name of the JSON property""" - xlsx_column_type: Optional[str] = field( + xlsx_column_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "xlsxColumnType"}, ) """Optional. Column type (ShortDateTime, TwoDecimal, etc.)""" - xlsx_column_name: Optional[str] = field( + xlsx_column_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "xlsxColumnName"}, ) """Optional. Rename JSON property to this name""" @@ -703,24 +774,31 @@ class Json2XlsxRequest: Definition: Json2XlsxRequest """ - content: Optional[str] = None + content: Optional[str] = dataclass_field(default=None, kw_only=True) """Optional. Content of the JSON file""" - json_data: Optional[str] = field( + json_data: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jsonData"}, ) """Optional. JSON data to process""" - locale: Optional[str] = None + locale: Optional[str] = dataclass_field(default=None, kw_only=True) """The locale that will be applyed to the document""" - path_to_json_array: Optional[str] = field( + path_to_json_array: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pathToJsonArray"}, ) """ Dot separated path to array in JSON. E.g.: \"data\" or \"prop1.prop2.prop3\" """ - mappings: Optional[List[Json2XlsxColumnMapping]] = None + mappings: Optional[ + List[Json2XlsxColumnMapping | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Rename headers and specify types for columns.""" @@ -730,14 +808,20 @@ class LicenseInfo: Definition: LicenseInfo """ - type_: Optional[int] = field(default=None, metadata={"wire_name": "type"}) - credits: Optional[int] = None - additional_credits: Optional[int] = field( + type_: Optional[int] = dataclass_field( default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) + credits: Optional[int] = dataclass_field(default=None, kw_only=True) + additional_credits: Optional[int] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "additionalCredits"}, ) - expiration_date: Optional[str] = field( + expiration_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "expirationDate"}, ) @@ -748,12 +832,9 @@ class MergeAny2PdfFileData: Definition: MergeAny2PdfFileData """ - file_name: Optional[str] = field( - default=None, - metadata={"wire_name": "fileName"}, - ) + file_name: str = dataclass_field(metadata={"wire_name": "fileName"}) """Name of the file, including extension""" - content: Optional[str] = None + content: str """Content of the file""" @@ -763,18 +844,19 @@ class MergeAny2PdfRequest: Definition: MergeAny2PdfRequest """ - documents_contents: Optional[List[str]] = field( - default=None, + documents_contents: List[str] = dataclass_field( metadata={"wire_name": "documentsContents"}, ) """The array of raw contents of files to merge""" - generate_bookmarks: Optional[bool] = field( + generate_bookmarks: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "generateBookmarks"}, ) """Generate a bookmark for each merged file""" - preserve_bookmarks: Optional[bool] = field( + preserve_bookmarks: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "preserveBookmarks"}, ) """Preserve bookmarks from each merged PDF""" @@ -786,21 +868,20 @@ class MergeDocxRequest: Definition: MergeDocxRequest """ - documents_contents: Optional[List[str]] = field( - default=None, + documents_contents: List[str] = dataclass_field( metadata={"wire_name": "documentsContents"}, ) """The array of raw content of Docx documents""" - apply_header_and_footer: Optional[bool] = field( - default=None, + apply_header_and_footer: bool = dataclass_field( metadata={"wire_name": "applyHeaderAndFooter"}, ) """ Applies the header and footer from the first document to all the others. Ignored when \"Add page break\" is No (forces Yes). """ - add_page_break: Optional[bool] = field( + add_page_break: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "addPageBreak"}, ) """Adds page breaks between merged documents.""" @@ -812,15 +893,14 @@ class MergeFieldsTemplateRequest: Definition: MergeFieldsTemplateRequest """ - docx_document: Optional[str] = field( - default=None, + docx_document: str = dataclass_field( metadata={"wire_name": "docxDocument"}, ) """ Raw content of docx document template. MergeField names should be the same as keys in template data """ - data: Optional[Dict[str, Any]] = None + data: Dict[str, Any] """JSON data that should be applied to the template""" @@ -830,8 +910,7 @@ class MergePdfRequest: Definition: MergePdfRequest """ - documents_contents: Optional[List[str]] = field( - default=None, + documents_contents: List[str] = dataclass_field( metadata={"wire_name": "documentsContents"}, ) """The array of raw content of PDF documents""" @@ -843,8 +922,7 @@ class MergeXlsxRequest: Definition: MergeXlsxRequest """ - documents_contents: Optional[List[str]] = field( - default=None, + documents_contents: List[str] = dataclass_field( metadata={"wire_name": "documentsContents"}, ) """The array of raw content of Xlsx documents""" @@ -856,18 +934,19 @@ class ParseCsvFlowRequest: Definition: ParseCsvFlowRequest """ - content: Optional[str] = None + content: str """Content of CSV document""" - delimiter: Optional[str] = None + delimiter: Optional[str] = dataclass_field(default=None, kw_only=True) """Delimiter of columns (by default it is just comma)""" - locale: Optional[str] = None + locale: Optional[str] = dataclass_field(default=None, kw_only=True) """The locale that will be applyed to the document""" - limit: Optional[int] = None + limit: Optional[int] = dataclass_field(default=None, kw_only=True) """Returns the first \"n\" rows""" - headers: Optional[str] = None + headers: str """Comma separated list of headers in the same order as CSV columns""" - skip_first_line: Optional[bool] = field( + skip_first_line: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "skipFirstLine"}, ) """Select \"Yes\" if your CSV has headers as a first line.""" @@ -879,39 +958,41 @@ class Pdf2ImageRequest: Definition: Pdf2ImageRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Raw content of PDF document""" - filename_prefix: Optional[str] = field( + filename_prefix: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filenamePrefix"}, ) """ Optional. Output files will have this prefix followed by an index number for name """ - start_page: Optional[int] = field( + start_page: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startPage"}, ) """The first page to start extraction (1 based)""" - end_page: Optional[int] = field( + end_page: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endPage"}, ) """The last page to extract (inclusive)""" - pages: Optional[str] = None + pages: Optional[str] = dataclass_field(default=None, kw_only=True) """ Page numbers for extraction separated by ';' (only this pages will be extracted) """ - format: Optional[str] = None + format: Optional[str] = dataclass_field(default=None, kw_only=True) """The format of the result image""" - dpi: Optional[int] = None + dpi: Optional[int] = dataclass_field(default=None, kw_only=True) """The resolution of the result image""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password to decrypt document""" @@ -921,27 +1002,29 @@ class Pdf2TextRequest: Definition: Pdf2TextRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Raw content of PDF document""" - start_page: Optional[int] = field( + start_page: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startPage"}, ) """The first page to start extraction (1 based)""" - end_page: Optional[int] = field( + end_page: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endPage"}, ) """The last page to extract (inclusive)""" - result_type: Optional[str] = field( + result_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resultType"}, ) """Raw or HTML""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password to decrypt document""" @@ -951,8 +1034,7 @@ class PdfProtectionInfoRequest: Definition: PdfProtectionInfoRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Raw content of PDF document""" @@ -964,8 +1046,7 @@ class Ppt2PptxRequest: Definition: Ppt2PptxRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Content of document that should be converted""" @@ -977,8 +1058,7 @@ class Pptx2PdfRequest: Definition: Pptx2PdfRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Content of document that should be converted""" @@ -990,8 +1070,7 @@ class ProcessJsonData: Definition: ProcessJsonData """ - json_content: Optional[Dict[str, Any]] = field( - default=None, + json_content: Dict[str, Any] = dataclass_field( metadata={"wire_name": "jsonContent"}, ) """JSON data that should be applied to the template""" @@ -1003,7 +1082,7 @@ class ProcessSchemaDynamicType: Definition: ProcessSchemaDynamicType """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1016,43 +1095,40 @@ class ProtectPdfRequest: Definition: ProtectPdfRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Raw content of PDF document""" - allow_printing: Optional[bool] = field( - default=None, + allow_printing: bool = dataclass_field( metadata={"wire_name": "allowPrinting"}, ) """Protect the PDF file from being printed out""" - allow_modification: Optional[bool] = field( - default=None, + allow_modification: bool = dataclass_field( metadata={"wire_name": "allowModification"}, ) """Protect the PDF file from being edited""" - allow_extract: Optional[bool] = field( - default=None, + allow_extract: bool = dataclass_field( metadata={"wire_name": "allowExtract"}, ) """Allows extraction of text, images, and other media from the PDF file""" - allow_annotate: Optional[bool] = field( - default=None, + allow_annotate: bool = dataclass_field( metadata={"wire_name": "allowAnnotate"}, ) """ Allows annotation (e.g. comments, form fill-in, signing) of the PDF file """ - new_owner_password: Optional[str] = field( + new_owner_password: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newOwnerPassword"}, ) """ Enter an optional owner password here. This password can be used to disable document restrictions """ - new_user_password: Optional[str] = field( + new_user_password: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newUserPassword"}, ) """ @@ -1060,7 +1136,7 @@ class ProtectPdfRequest: will be asked for this password. If you do not want a password prompt then leave this field blank """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password to decrypt document""" @@ -1070,9 +1146,9 @@ class RegExpMatchRequest: Definition: RegExpMatchRequest """ - pattern: Optional[str] = None + pattern: str """Regular expression pattern""" - text: Optional[str] = None + text: str """String to search for matches""" @@ -1082,11 +1158,11 @@ class RegExpReplaceRequest: Definition: RegExpReplaceRequest """ - pattern: Optional[str] = None + pattern: str """Regular expression pattern""" - text: Optional[str] = None + text: str """String to search for matches""" - replacement: Optional[str] = None + replacement: Optional[str] = dataclass_field(default=None, kw_only=True) """Replacement string""" @@ -1096,9 +1172,9 @@ class RegExpTestRequest: Definition: RegExpTestRequest """ - pattern: Optional[str] = None + pattern: str """Regular expression pattern""" - text: Optional[str] = None + text: str """String to search for matches""" @@ -1108,27 +1184,29 @@ class SplitPdfRequest: Definition: SplitPdfRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Raw content of PDF document""" - start_page: Optional[int] = field( + start_page: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startPage"}, ) """The first page to start split (1 based)""" - end_page: Optional[int] = field( + end_page: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endPage"}, ) """The last page to split (inclusive)""" - split_at_page: Optional[int] = field( + split_at_page: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "splitAtPage"}, ) """Number of pages per partition""" - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password to decrypt document""" @@ -1138,8 +1216,7 @@ class Xls2XlsxRequest: Definition: Xls2XlsxRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Content of document that should be converted""" @@ -1151,8 +1228,7 @@ class Xlsx2PdfRequest: Definition: Xlsx2PdfRequest """ - document_content: Optional[str] = field( - default=None, + document_content: str = dataclass_field( metadata={"wire_name": "documentContent"}, ) """Content of document that should be converted""" @@ -1166,16 +1242,16 @@ class PlumsailClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -1186,8 +1262,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -1195,8 +1271,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -1208,7 +1284,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -1223,7 +1299,7 @@ def __init__( def connector_name(self) -> str: return "plumsail" - async def profiles_me_get_async( + def profiles_me_get( self, *, timeout: Optional[float] = None, @@ -1235,10 +1311,24 @@ async def profiles_me_get_async( Get Profile Info Get Profile Info returns information about current user and license. + + Swagger operation ID: `ProfilesMeGet`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/profiles/me" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1252,6 +1342,7 @@ async def profiles_me_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1259,27 +1350,45 @@ async def profiles_me_get_async( return json.loads(response.text) - async def flow_v1_documents_jobs_apply_docx_template_async( + def begin_flow_v1_documents_jobs_apply_docx_template( self, - input: ApplyDocxTemplateRequest, + input: ApplyDocxTemplateRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Create document from DOCX template Create document from DOCX template. More information: https://plumsail.com/docs/documents/v1.x/document-generation/docx/index.html + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsApplyDocxTemplatePost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/flow/v1/Documents/jobs/ApplyDocxTemplate" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1293,31 +1402,62 @@ async def flow_v1_documents_jobs_apply_docx_template_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_apply_xlsx_template_async( + def begin_flow_v1_documents_jobs_apply_xlsx_template( self, - input: ApplyXlsxTemplateRequest, + input: ApplyXlsxTemplateRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Create document from XLSX template Create document from XLSX template. More information: https://plumsail.com/docs/documents/v1.x/document-generation/xlsx/index.html + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsApplyXlsxTemplatePost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/flow/v1/Documents/jobs/ApplyXlsxTemplate" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1331,30 +1471,62 @@ async def flow_v1_documents_jobs_apply_xlsx_template_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_apply_pptx_async( + def begin_flow_v1_documents_jobs_apply_pptx( self, - input: ApplyPptxTemplateRequest, + input: ApplyPptxTemplateRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Create document from PPTX template Create document from PPTX template. More information: https://plumsail.com/docs/documents/v1.x/document-generation/pptx/index.html + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsApplyPptxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/ApplyPptx" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1368,22 +1540,36 @@ async def flow_v1_documents_jobs_apply_pptx_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_apply_docx_async( + def begin_flow_v1_documents_jobs_apply_docx( self, - input: MergeFieldsTemplateRequest, + input: MergeFieldsTemplateRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Fill merge fields in DOCX document @@ -1392,12 +1578,31 @@ async def flow_v1_documents_jobs_apply_docx_async( should be the same as names of MergeFields (Express block) in document. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#fill-merge-fields-in-docx-document + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsApplyDocxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/ApplyDocx" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1411,22 +1616,36 @@ async def flow_v1_documents_jobs_apply_docx_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_apply_html_async( + def begin_flow_v1_documents_jobs_apply_html( self, - input: ApplyHtmlFlowTemplateRequest, + input: ApplyHtmlFlowTemplateRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Create HTML from template @@ -1435,12 +1654,31 @@ async def flow_v1_documents_jobs_apply_html_async( templates internally. More information about templates in Mustache docs: http://mustache.github.io/mustache.5.html. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#create-html-from-template + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsApplyHtmlPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/ApplyHtml" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1454,34 +1692,67 @@ async def flow_v1_documents_jobs_apply_html_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_html2_pdf_async( + def begin_flow_v1_documents_jobs_html2_pdf( self, - input: Html2PdfFlowRequest, + input: Html2PdfFlowRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Convert HTML to PDF Convert HTML to PDF file. This action takes HTML markup, renders it and converts to PDF document. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-html-to-pdf + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsHtml2PdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Html2Pdf" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1495,34 +1766,67 @@ async def flow_v1_documents_jobs_html2_pdf_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_html2_docx_async( + def begin_flow_v1_documents_jobs_html2_docx( self, - input: Html2DocxFlowRequest, + input: Html2DocxFlowRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Convert HTML to DOCX Convert HTML to DOCX document. This action takes HTML markup, renders it and converts to DOCX document. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-html-to-docx + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsHtml2DocxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Html2Docx" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1536,34 +1840,67 @@ async def flow_v1_documents_jobs_html2_docx_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_docx2_pdf_async( + def begin_flow_v1_documents_jobs_docx2_pdf( self, - input: Docx2PdfRequest, + input: Docx2PdfRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Convert DOCX to PDF Convert DOCX to PDF files. This action takes DOCX document and converts it to PDF. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-docx-to-pdf + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsDocx2PdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Docx2Pdf" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1577,34 +1914,66 @@ async def flow_v1_documents_jobs_docx2_pdf_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_xslx2_pdf_async( + def begin_flow_v1_documents_jobs_xslx2_pdf( self, - input: Xlsx2PdfRequest, + input: Xlsx2PdfRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Convert XLSX to PDF Convert XLSX to PDF files. This action takes XLSX document and converts it to PDF. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-xlsx-to-pdf + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsXslx2PdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Xslx2Pdf" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1618,31 +1987,62 @@ async def flow_v1_documents_jobs_xslx2_pdf_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_pptx2_pdf_async( + def begin_flow_v1_documents_jobs_pptx2_pdf( self, - input: Pptx2PdfRequest, + input: Pptx2PdfRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Convert PPTX to PDF Convert PPTX to PDF files. This action takes PPTX document and converts it to PDF. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-pptx-to-pdf + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsPptx2PdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Pptx2Pdf" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1656,30 +2056,61 @@ async def flow_v1_documents_jobs_pptx2_pdf_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_any2_pdf_v2_async( + def begin_flow_v1_documents_jobs_any2_pdf_v2( self, - input: Any2PdfRequest, + input: Any2PdfRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Convert to PDF Convert provided file to PDF file. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-to-pdf + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsAny2PdfV2Post`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Any2PdfV2" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1693,30 +2124,61 @@ async def flow_v1_documents_jobs_any2_pdf_v2_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_email2_pdf_async( + def begin_flow_v1_documents_jobs_email2_pdf( self, - input: Email2PdfRequest, + input: Email2PdfRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Convert Email to PDF Convert provided Email to PDF file. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-email-to-pdf + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsEmail2PdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Email2Pdf" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1730,31 +2192,62 @@ async def flow_v1_documents_jobs_email2_pdf_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_doc2_docx_async( + def begin_flow_v1_documents_jobs_doc2_docx( self, - input: Doc2DocxRequest, + input: Doc2DocxRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Convert DOC to DOCX Convert DOC to DOCX files. This action takes DOC document and converts it to DOCX. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-doc-to-docx + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsDoc2DocxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Doc2Docx" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1768,31 +2261,62 @@ async def flow_v1_documents_jobs_doc2_docx_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_xls2_xlsx_async( + def begin_flow_v1_documents_jobs_xls2_xlsx( self, - input: Xls2XlsxRequest, + input: Xls2XlsxRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Convert XLS to XLSX Convert XLS to XLSX files. This action takes XLS document and converts it to XLSX. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-xls-to-xlsx + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsXls2XlsxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Xls2Xlsx" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1806,31 +2330,62 @@ async def flow_v1_documents_jobs_xls2_xlsx_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_ppt2_pptx_async( + def begin_flow_v1_documents_jobs_ppt2_pptx( self, - input: Ppt2PptxRequest, + input: Ppt2PptxRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Convert PPT to PPTX Convert PPT to PPTX files. This action takes PPT document and converts it to PPTX. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-ppt-to-pptx + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsPpt2PptxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Ppt2Pptx" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1844,25 +2399,58 @@ async def flow_v1_documents_jobs_ppt2_pptx_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_split_pdf_v2_async( + def begin_flow_v1_documents_jobs_split_pdf_v2( self, - input: FlowDocumentsJobsSplitPdfInput, + input: FlowDocumentsJobsSplitPdfInput | Mapping[str, Any], type_: str, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Split PDF Split PDF takes PDF document and splits it. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#split-pdf + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsSplitPdfV2Post`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + type_: How to split the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/SplitPdfV2" @@ -1875,7 +2463,7 @@ async def flow_v1_documents_jobs_split_pdf_v2_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1889,35 +2477,67 @@ async def flow_v1_documents_jobs_split_pdf_v2_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_merge_any_to_pdf_v2_async( + def begin_flow_v1_documents_jobs_merge_any_to_pdf_v2( self, - input: MergeAny2PdfRequest, + input: MergeAny2PdfRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Merge any files into PDF Convert and merge multiple files into a single PDF document. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#merge-any-files-into-pdf + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsMergeAnyToPdfV2Post`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/flow/v1/Documents/jobs/MergeAnyToPdfV2" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1931,32 +2551,64 @@ async def flow_v1_documents_jobs_merge_any_to_pdf_v2_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_extract_text_from_pdf_async( + def begin_flow_v1_documents_jobs_extract_text_from_pdf( self, - input: Pdf2TextRequest, + input: Pdf2TextRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Extract text from PDF document Extract text from PDF takes PDF document and extracts text to Raw or HTML format. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#extract-text-from-pdf-document + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsExtractTextFromPdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/flow/v1/Documents/jobs/ExtractTextFromPdf" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1970,35 +2622,68 @@ async def flow_v1_documents_jobs_extract_text_from_pdf_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_pdf2_image_v2_async( + def begin_flow_v1_documents_jobs_pdf2_image_v2( self, - input: Pdf2ImageRequest, + input: Pdf2ImageRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Convert PDF to Image Convert PDF to image. This action takes PDF document and converts it to Image (jpeg, png, gif, bmp, etc). Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#convert-pdf-to-image + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsPdf2ImageV2Post`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/flow/v1/Documents/jobs/Pdf2ImageV2" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2012,32 +2697,64 @@ async def flow_v1_documents_jobs_pdf2_image_v2_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_image2_pdf_async( + def begin_flow_v1_documents_jobs_image2_pdf( self, - input: Image2PdfRequest, + input: Image2PdfRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Convert Images to PDF It takes images and converts them to a PDF document + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsImage2PdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Image2Pdf" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2051,31 +2768,63 @@ async def flow_v1_documents_jobs_image2_pdf_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_fill_in_pdf_form_async( + def begin_flow_v1_documents_jobs_fill_in_pdf_form( self, - input: FillInPdfFormRequest, + input: FillInPdfFormRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Fill in PDF Form Fill in PDF Form fills out PDF from by provided data. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#fill-in-pdf-form + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsFillInPdfFormPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/flow/v1/Documents/jobs/FillInPdfForm" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2089,34 +2838,67 @@ async def flow_v1_documents_jobs_fill_in_pdf_form_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_get_pdf_form_async( + def begin_flow_v1_documents_jobs_get_pdf_form( self, - input: GetPdfFormRequest, + input: GetPdfFormRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Get Form from PDF Get Form from PDF returns fillable form data from PDF as JSON. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#get-form-from-pdf + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsGetPdfFormPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/GetPdfForm" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2130,34 +2912,67 @@ async def flow_v1_documents_jobs_get_pdf_form_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_protect_pdf_async( + def begin_flow_v1_documents_jobs_protect_pdf( self, - input: ProtectPdfRequest, + input: ProtectPdfRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Protect PDF document Protect PDF document adds passwords, copy, printing, and other protections to PDF files. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#protect-pdf-document + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsProtectPdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/ProtectPdf" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2171,35 +2986,68 @@ async def flow_v1_documents_jobs_protect_pdf_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_get_pdf_protection_info_async( + def begin_flow_v1_documents_jobs_get_pdf_protection_info( self, - input: PdfProtectionInfoRequest, + input: PdfProtectionInfoRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Get information about PDF protection Get information about PDF protection returns information whether the document is password protected. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#get-pdf-protection-information + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsGetPdfProtectionInfoPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/flow/v1/Documents/jobs/GetPdfProtectionInfo" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2213,34 +3061,66 @@ async def flow_v1_documents_jobs_get_pdf_protection_info_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_compress_pdf_async( + def begin_flow_v1_documents_jobs_compress_pdf( self, - input: CompressPdfRequest, + input: CompressPdfRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Compress PDF document Compress PDF document size if possible and optimize it. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#compress-pdf-document + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsCompressPdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/flow/v1/Documents/jobs/CompressPdf" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2254,25 +3134,58 @@ async def flow_v1_documents_jobs_compress_pdf_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_add_watermark_to_pdf_async( + def begin_flow_v1_documents_jobs_add_watermark_to_pdf( self, - input: FlowDocumentsJobsAddWatermarkToPdfInput, + input: FlowDocumentsJobsAddWatermarkToPdfInput | Mapping[str, Any], type_: str, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Add a watermark to PDF Add a watermark to PDF as text, an image, HTML, or PDF. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#add-watermark-to-pdf + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsAddWatermarkToPdfPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + type_: The type of the watermark. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2286,7 +3199,7 @@ async def flow_v1_documents_jobs_add_watermark_to_pdf_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2300,34 +3213,67 @@ async def flow_v1_documents_jobs_add_watermark_to_pdf_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_merge_docx_async( + def begin_flow_v1_documents_jobs_merge_docx( self, - input: MergeDocxRequest, + input: MergeDocxRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Merge DOCX files Merge DOCX files takes an array of Docx documents and merge it into single file. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#merge-docx-files + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsMergeDocxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/MergeDocx" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2341,33 +3287,66 @@ async def flow_v1_documents_jobs_merge_docx_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_parse_csv_async( + def begin_flow_v1_documents_jobs_parse_csv( self, - input: ParseCsvFlowRequest, + input: ParseCsvFlowRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Parse CSV Parse CSV works like Parse JSON but for CSV files. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#parse-csv + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsParseCsvPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/ParseCsv" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2381,33 +3360,65 @@ async def flow_v1_documents_jobs_parse_csv_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_csv2_xlsx_async( + def begin_flow_v1_documents_jobs_csv2_xlsx( self, - input: Csv2XlsxRequest, + input: Csv2XlsxRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Convert CSV to Excel Convert CSV to Excel file (XLSX). Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#csv-to-excel + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsCsv2XlsxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Csv2Xlsx" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2421,30 +3432,61 @@ async def flow_v1_documents_jobs_csv2_xlsx_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_json2_xlsx_async( + def begin_flow_v1_documents_jobs_json2_xlsx( self, - input: Json2XlsxRequest, + input: Json2XlsxRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Convert JSON to Excel Convert JSON to Excel file (XLSX). Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#json-to-excel + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsJson2XlsxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Json2Xlsx" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2458,30 +3500,61 @@ async def flow_v1_documents_jobs_json2_xlsx_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_json2_csv_async( + def begin_flow_v1_documents_jobs_json2_csv( self, - input: Json2CsvRequest, + input: Json2CsvRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Convert JSON to CSV Convert JSON to CSV file. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#json-to-csv + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsJson2CsvPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/Json2Csv" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2495,19 +3568,32 @@ async def flow_v1_documents_jobs_json2_csv_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_reg_exp_match_async( + def begin_flow_v1_documents_jobs_reg_exp_match( self, - input: RegExpMatchRequest, + input: RegExpMatchRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Regular Expression Match @@ -2516,13 +3602,32 @@ async def flow_v1_documents_jobs_reg_exp_match_async( would recommend to use Regex Hero to test your expressions. It supports the same syntax as actions. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#regular-expression-match + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsRegExpMatchPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/flow/v1/Documents/jobs/RegExpMatch" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2536,22 +3641,36 @@ async def flow_v1_documents_jobs_reg_exp_match_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_reg_exp_replace_async( + def begin_flow_v1_documents_jobs_reg_exp_replace( self, - input: RegExpReplaceRequest, + input: RegExpReplaceRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Regular Expression Replace @@ -2560,13 +3679,32 @@ async def flow_v1_documents_jobs_reg_exp_replace_async( input string. We would recommend to use Regex Hero to test your expressions. It supports the same syntax as actions. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#regular-expression-replace + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsRegExpReplacePost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/flow/v1/Documents/jobs/RegExpReplace" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2580,22 +3718,36 @@ async def flow_v1_documents_jobs_reg_exp_replace_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_reg_exp_test_async( + def begin_flow_v1_documents_jobs_reg_exp_test( self, - input: RegExpTestRequest, + input: RegExpTestRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Regular Expression Test @@ -2604,12 +3756,31 @@ async def flow_v1_documents_jobs_reg_exp_test_async( string. We would recommend to use Regex Hero to test your expressions. It supports the same syntax as actions. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#regular-expression-test + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsRegExpTestPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/RegExpTest" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2623,33 +3794,66 @@ async def flow_v1_documents_jobs_reg_exp_test_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_create_archive_async( + def begin_flow_v1_documents_jobs_create_archive( self, - input: CreateArchiveRequest, + input: CreateArchiveRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Create Archive Compresses and adds files to a ZIP archive. + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsCreateArchivePost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/flow/v1/Documents/jobs/CreateArchive" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2663,33 +3867,66 @@ async def flow_v1_documents_jobs_create_archive_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_extract_archive_async( + def begin_flow_v1_documents_jobs_extract_archive( self, - input: ExtractArchiveRequest, + input: ExtractArchiveRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Extract Archive Extract files from archive. + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsExtractArchivePost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/flow/v1/Documents/jobs/ExtractArchive" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2703,34 +3940,67 @@ async def flow_v1_documents_jobs_extract_archive_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_jobs_merge_xlsx_async( + def begin_flow_v1_documents_jobs_merge_xlsx( self, - input: MergeXlsxRequest, + input: MergeXlsxRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> LROPoller[dict[str, Any] | None]: """ Merge XLSX files Merge XLSX files takes an array of Xlsx documents and merge it into single file. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#merge-xlsx-files + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1DocumentsJobsMergeXlsxPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[dict[str, Any] | None]: An Azure Core poller for the + connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/flow/v1/Documents/jobs/MergeXlsx" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2744,23 +4014,37 @@ async def flow_v1_documents_jobs_merge_xlsx_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return None - - return json.loads(response.text) + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: ( + json.loads(polling_response.text) + if polling_response.text + else None + ), + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_processes_flow_jobs_execute_process_async( + def begin_flow_v1_processes_flow_jobs_execute_process( self, - input: FlowProcessesFlowJobsExecuteProcessInput, + input: FlowProcessesFlowJobsExecuteProcessInput | Mapping[str, Any], process_id: str, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Start document generation process with json @@ -2768,6 +4052,25 @@ async def flow_v1_processes_flow_jobs_execute_process_async( template related to the selected process with the JSON data. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html##start-process-json + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: `FlowV1ProcessesFlowJobsExecuteProcessPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + process_id: The name of process to be started. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2781,7 +4084,7 @@ async def flow_v1_processes_flow_jobs_execute_process_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2795,20 +4098,33 @@ async def flow_v1_processes_flow_jobs_execute_process_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_processes_flow_jobs_execute_process_with_generated_data_async( + def begin_flow_v1_processes_flow_jobs_execute_process_with_generated_data( self, - input: ProcessJsonData, + input: ProcessJsonData | Mapping[str, Any], process_id: str, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> bytes: + ) -> LROPoller[bytes]: """ Start document generation process @@ -2816,6 +4132,26 @@ async def flow_v1_processes_flow_jobs_execute_process_with_generated_data_async( template related to the selected process with the JSON data. Documentation - https://plumsail.com/docs/documents/v1.x/flow/actions/document-processing.html#start-document-generation-process + + Returns an Azure Core poller for the connector operation. + + Swagger operation ID: + `FlowV1ProcessesFlowJobsExecuteProcessWithGeneratedDataPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + process_id: The name of process to be started. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + LROPoller[bytes]: An Azure Core poller for the connector operation. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2829,7 +4165,7 @@ async def flow_v1_processes_flow_jobs_execute_process_with_generated_data_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2843,11 +4179,24 @@ async def flow_v1_processes_flow_jobs_execute_process_with_generated_data_async( request_url, response.status, response.text, + response=response, ) - return response.content + return LROPoller( + client=self, + initial_response=response, + deserialization_callback=lambda polling_response: polling_response.content, + polling_method=ConnectorPollingMethod( + http_client=self.http_client, + polling_header_name="Location", + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ), + ) - async def flow_v1_documents_flow_schema_split_pdf_async( + def flow_v1_documents_flow_schema_split_pdf( self, type_: str, *, @@ -2860,6 +4209,21 @@ async def flow_v1_documents_flow_schema_split_pdf_async( SplitPdfSchema System + + Swagger operation ID: `FlowV1DocumentsFlowSchemaSplitPdfPost`. + + Args: + type_: How to split the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2873,7 +4237,7 @@ async def flow_v1_documents_flow_schema_split_pdf_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -2887,9 +4251,10 @@ async def flow_v1_documents_flow_schema_split_pdf_async( request_url, response.status, response.text, + response=response, ) - async def flow_v1_documents_flow_schema_add_watermark_to_pdf_async( + def flow_v1_documents_flow_schema_add_watermark_to_pdf( self, type_: str, *, @@ -2902,6 +4267,21 @@ async def flow_v1_documents_flow_schema_add_watermark_to_pdf_async( AddWatermarkToPdfSchema System + + Swagger operation ID: `FlowV1DocumentsFlowSchemaAddWatermarkToPdfPost`. + + Args: + type_: The type of the watermark. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2915,7 +4295,7 @@ async def flow_v1_documents_flow_schema_add_watermark_to_pdf_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -2929,9 +4309,10 @@ async def flow_v1_documents_flow_schema_add_watermark_to_pdf_async( request_url, response.status, response.text, + response=response, ) - async def flow_v1_processes_flow_schema_get_processes_async( + def flow_v1_processes_flow_schema_get_processes( self, *, timeout: Optional[float] = None, @@ -2943,13 +4324,27 @@ async def flow_v1_processes_flow_schema_get_processes_async( GetProcessesSchema System + + Swagger operation ID: `FlowV1ProcessesFlowSchemaGetProcessesPost`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/flow/v1/ProcessesFlow/Schema/GetProcesses" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -2963,9 +4358,10 @@ async def flow_v1_processes_flow_schema_get_processes_async( request_url, response.status, response.text, + response=response, ) - async def flow_v1_documents_flow_schema_parse_csv_async( + def flow_v1_documents_flow_schema_parse_csv( self, headers_parameter: str, *, @@ -2978,6 +4374,21 @@ async def flow_v1_documents_flow_schema_parse_csv_async( ParseCsv System + + Swagger operation ID: `FlowV1DocumentsFlowSchemaParseCsvPost`. + + Args: + headers_parameter: headers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2991,7 +4402,7 @@ async def flow_v1_documents_flow_schema_parse_csv_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -3005,9 +4416,10 @@ async def flow_v1_documents_flow_schema_parse_csv_async( request_url, response.status, response.text, + response=response, ) - async def flow_v1_processes_flow_schema_get_json_data_async( + def flow_v1_processes_flow_schema_get_json_data( self, process_id: str, *, @@ -3020,6 +4432,21 @@ async def flow_v1_processes_flow_schema_get_json_data_async( GetJsonSchema System + + Swagger operation ID: `FlowV1ProcessesFlowSchemaGetJsonDataPost`. + + Args: + process_id: The name of process to be started. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3033,7 +4460,7 @@ async def flow_v1_processes_flow_schema_get_json_data_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -3047,9 +4474,10 @@ async def flow_v1_processes_flow_schema_get_json_data_async( request_url, response.status, response.text, + response=response, ) - async def flow_v1_processes_flow_triggers_by_process_id_schema_get_async( + def flow_v1_processes_flow_triggers_by_process_id_schema_get( self, process_id: str, *, @@ -3062,6 +4490,22 @@ async def flow_v1_processes_flow_triggers_by_process_id_schema_get_async( Get schema of a process Returns schema of a process + + Swagger operation ID: + `FlowV1ProcessesFlowTriggersByProcessIdSchemaGet`. + + Args: + process_id: processId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3073,7 +4517,7 @@ async def flow_v1_processes_flow_triggers_by_process_id_schema_get_async( f"/schema" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3087,9 +4531,10 @@ async def flow_v1_processes_flow_triggers_by_process_id_schema_get_async( request_url, response.status, response.text, + response=response, ) - async def flow_v1_documents_flow_schema_reg_exp_match_async( + def flow_v1_documents_flow_schema_reg_exp_match( self, pattern: str, *, @@ -3102,6 +4547,21 @@ async def flow_v1_documents_flow_schema_reg_exp_match_async( RegexMatchSchema System + + Swagger operation ID: `FlowV1DocumentsFlowSchemaRegExpMatchPost`. + + Args: + pattern: pattern. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3115,7 +4575,7 @@ async def flow_v1_documents_flow_schema_reg_exp_match_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -3129,6 +4589,7 @@ async def flow_v1_documents_flow_schema_reg_exp_match_async( request_url, response.status, response.text, + response=response, ) diff --git a/src/azure/connectors/powerbi.py b/src/azure/connectors/powerbi.py index 5653313..f661ffc 100644 --- a/src/azure/connectors/powerbi.py +++ b/src/azure/connectors/powerbi.py @@ -5,21 +5,71 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "PowerbiClient", + "Alert", + "Columns", + "CreateGoalRequest", + "CreateGoalResponse", + "CreateScorecardRequest", + "CreatedScorecard", + "Datasets", + "DynamicPowerBiButtonClickedTriggerResult", + "EffectiveIdentity", + "EvaluatedAlert", + "ExecuteDatasetQueriesJsonInput", + "ExecuteDatasetQueriesJsonResponse", + "ExportFilter", + "ExportPayloadPaginatedReport", + "ExportPayloadPowerBIReport", + "ExportReportPage", + "ExportReportSettings", + "FetchedGoal", + "FetchedGoals", + "GetGoalCheckinResponse", + "GetGoalCheckinsResponse", + "GoalChanged", + "GoalNotes", + "GoalRefreshIssue", + "GoalRefreshIssues", + "GoalStatusChanged", + "GoalValueChanged", + "GoalValueCheckinNoteInput", + "GoalValueCheckinRequest", + "GoalValueCheckinUpdateRequest", + "GoalValueOrNoteUpserted", + "GoalsAssigned", + "Groups", + "IdentityBlob", + "ListedScorecard", + "ListedScorecards", + "PageBookmark", + "Payload", + "PowerBiButtonClickedOutputs", + "QueryExecutionResults", + "QuerySpecification", + "Reports", + "Tables", + "UpdateGoalRequest", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +79,12 @@ class ListedScorecards: Response for Get scorecards """ - value: Optional[List[ListedScorecard]] = None + value: Optional[ + List[ListedScorecard | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of scorecards.""" @@ -39,7 +94,7 @@ class CreatedScorecard: Response for Create a scorecard """ - id: Optional[str] = None + id: str """The unique identifier of the scorecard.""" @@ -49,7 +104,12 @@ class FetchedGoals: Response for Get multiple goals """ - value: Optional[List[FetchedGoal]] = None + value: Optional[ + List[FetchedGoal | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of the goals.""" @@ -59,7 +119,7 @@ class CreateGoalResponse: Response for Create a goal """ - id: Optional[str] = None + id: str """The unique identifier of the goal.""" @@ -69,58 +129,67 @@ class FetchedGoal: Response for Get a goal """ - id: Optional[str] = None + id: str """The unique identifier of the goal.""" - name: Optional[str] = None + name: str """The name of the goal.""" - owner: Optional[str] = None + owner: Optional[str] = dataclass_field(default=None, kw_only=True) """The email address of the goal's owner.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """The start date for the goal. Example: 2021-07-15.""" - completion_date: Optional[str] = field( + completion_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "completionDate"}, ) """The due date for the goal to be completed by. Example: 2021-07-29.""" - parent_id: Optional[str] = field( + parent_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentId"}, ) """If this goal is a subgoal, the unique id of its parent goal.""" - current_value: Optional[float] = field( + current_value: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "currentValue"}, ) """The current value of the goal being tracked.""" - current_value_timestamp: Optional[str] = field( + current_value_timestamp: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "currentValueTimestamp"}, ) """The timestamp when the current value of the goal was set.""" - target_value: Optional[float] = field( + target_value: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "targetValue"}, ) """The target value of the goal.""" - target_value_timestamp: Optional[str] = field( + target_value_timestamp: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "targetValueTimestamp"}, ) """The timestamp when the target value of the goal was set.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status of the goal.""" - status_timestamp: Optional[str] = field( + status_timestamp: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "statusTimestamp"}, ) """The timestamp when the status of the goal was set.""" - cycle: Optional[str] = None + cycle: Optional[str] = dataclass_field(default=None, kw_only=True) """Tracking cycle frequency interval shown on this goal's visuals.""" - cycle_period: Optional[str] = field( + cycle_period: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "cyclePeriod"}, ) """Date to find out extra properties of tracking cycle.""" @@ -132,8 +201,7 @@ class GoalsAssigned: Response for When someone assigns a new owner to a goal """ - assigned_goals: Optional[List[Dict[str, Any]]] = field( - default=None, + assigned_goals: List[Dict[str, Any]] = dataclass_field( metadata={"wire_name": "assignedGoals"}, ) """The list of goals that were assigned to the new owner.""" @@ -145,110 +213,131 @@ class GoalChanged: Response for When a goal changes """ - id: Optional[str] = None + id: str """The unique identifier of the goal.""" - old_name: Optional[str] = field( + old_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldName"}, ) """The name of the goal.""" - old_owner: Optional[str] = field( + old_owner: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldOwner"}, ) """The email address of the goal's owner.""" - old_start_date: Optional[str] = field( + old_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldStartDate"}, ) """The start date for the goal. Example: 2021-07-15.""" - old_completion_date: Optional[str] = field( + old_completion_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldCompletionDate"}, ) """The due date for the goal to be completed by. Example: 2021-07-29.""" - old_parent_id: Optional[str] = field( + old_parent_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldParentId"}, ) """If this goal is a subgoal, the unique id of its parent goal.""" - old_current_value: Optional[float] = field( + old_current_value: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldCurrentValue"}, ) """The current value of the goal being tracked.""" - old_target_value: Optional[float] = field( + old_target_value: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldTargetValue"}, ) """The target value of the goal.""" - old_status: Optional[str] = field( + old_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldStatus"}, ) """The status of the goal.""" - old_cycle: Optional[str] = field( + old_cycle: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldCycle"}, ) """Old tracking cycle frequency interval shown on this goal's visuals.""" - old_cycle_period: Optional[str] = field( + old_cycle_period: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldCyclePeriod"}, ) """Old date to find out extra properties of tracking cycle.""" - new_name: Optional[str] = field( + new_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newName"}, ) """The name of the goal.""" - new_owner: Optional[str] = field( + new_owner: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newOwner"}, ) """The email address of the goal's owner.""" - new_start_date: Optional[str] = field( + new_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newStartDate"}, ) """The start date for the goal.""" - new_completion_date: Optional[str] = field( + new_completion_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newCompletionDate"}, ) """The due date for the goal to be completed by.""" - new_parent_id: Optional[str] = field( + new_parent_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newParentId"}, ) """If this goal is a subgoal, the unique id of its parent goal.""" - new_current_value: Optional[float] = field( + new_current_value: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newCurrentValue"}, ) """The current value of the goal being tracked.""" - new_target_value: Optional[float] = field( + new_target_value: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newTargetValue"}, ) """The target value of the goal.""" - new_status: Optional[str] = field( + new_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newStatus"}, ) """The status of the goal.""" - new_cycle: Optional[str] = field( + new_cycle: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newCycle"}, ) """New tracking cycle interval shown on this goal's visuals.""" - new_cycle_period: Optional[str] = field( + new_cycle_period: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newCyclePeriod"}, ) """New date to find out extra properties of tracking cycle.""" - change_list: Optional[str] = field( + change_list: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "changeList"}, ) """Comma separated list of changes. Example: 'status,currentValue'.""" @@ -260,15 +349,17 @@ class GoalStatusChanged: Response for When status of a goal changes """ - id: Optional[str] = None + id: str """The unique identifier of the goal.""" - old_status: Optional[str] = field( + old_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldStatus"}, ) """The status of the goal.""" - new_status: Optional[str] = field( + new_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newStatus"}, ) """The status of the goal.""" @@ -280,15 +371,17 @@ class GoalValueChanged: Response for When current value of a goal changes """ - id: Optional[str] = None + id: str """The unique identifier of the goal.""" - old_current_value: Optional[float] = field( + old_current_value: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "oldCurrentValue"}, ) """The current value of the goal being tracked.""" - new_current_value: Optional[float] = field( + new_current_value: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newCurrentValue"}, ) """The current value of the goal being tracked.""" @@ -300,7 +393,7 @@ class GoalRefreshIssues: Response for When a data refresh for a goal fails """ - issues: Optional[List[GoalRefreshIssue]] = None + issues: List[GoalRefreshIssue | Mapping[str, Any]] """Goal refresh issues.""" @@ -310,9 +403,9 @@ class GoalValueOrNoteUpserted: Response for When someone adds or edits a goal check-in """ - values: Optional[List[Dict[str, Any]]] = None + values: List[Dict[str, Any]] """Added or updated check-ins.""" - notes: Optional[List[Dict[str, Any]]] = None + notes: List[Dict[str, Any]] """Added or changed notes.""" @@ -322,31 +415,36 @@ class EvaluatedAlert: Response for When a data driven alert is triggered """ - alert_title: Optional[str] = field( + alert_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "alertTitle"}, ) """The title of the alert.""" - alert_threshold: Optional[float] = field( + alert_threshold: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "alertThreshold"}, ) """The threshold at which the alert is triggered.""" - is_alert_triggered: Optional[bool] = field( + is_alert_triggered: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAlertTriggered"}, ) """ A boolean value (true, false) determining Whether or not the alert was triggered. """ - tile_url: Optional[str] = field( + tile_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tileUrl"}, ) """URL linking to the dashboard tile where the alert is set up.""" - tile_value: Optional[Any] = field( + tile_value: Optional[Any] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tileValue"}, ) """The value of the tile.""" @@ -358,8 +456,9 @@ class QueryExecutionResults: Response for Run a query against a dataset """ - first_table_rows: Optional[List[Dict[str, Any]]] = field( + first_table_rows: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "firstTableRows"}, ) """Query results as an array of rows.""" @@ -371,7 +470,7 @@ class ExecuteDatasetQueriesJsonInput: Run a json query against a dataset """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -384,7 +483,7 @@ class ExecuteDatasetQueriesJsonResponse: Response for Run a json query against a dataset """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -400,7 +499,7 @@ class GetGoalCheckinsResponse: Response for Get goal check-ins """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of check-ins.""" @@ -410,13 +509,13 @@ class GetGoalCheckinResponse: Response for Get a goal check-in """ - timestamp: Optional[str] = None + timestamp: Optional[str] = dataclass_field(default=None, kw_only=True) """The date that the check-in was made.""" - value: Optional[float] = None + value: Optional[float] = dataclass_field(default=None, kw_only=True) """The value at the time of check in, if set.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The goal status at the time of check in.""" - notes: Optional[GoalNotes] = None + notes: Optional[GoalNotes] = dataclass_field(default=None, kw_only=True) @dataclass @@ -425,7 +524,7 @@ class Groups: Response for ListGroups """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -434,18 +533,21 @@ class Alert: Response for Get alerts from Power BI """ - alert_id: Optional[str] = field( + alert_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "alertId"}, ) """The ID of the alert.""" - alert_title: Optional[str] = field( + alert_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "alertTitle"}, ) """The title of the alert.""" - group_id: Optional[str] = field( + group_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "groupId"}, ) """The ID of the group.""" @@ -457,7 +559,7 @@ class Datasets: Response for ListDatasets """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -466,7 +568,7 @@ class Tables: Response for ListTables """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -475,12 +577,13 @@ class Reports: Response for Get Reports in Group """ - odata_context: Optional[str] = field( + odata_context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "odata.context"}, ) """OData context""" - value: Optional[List[Any]] = None + value: Optional[List[Any]] = dataclass_field(default=None, kw_only=True) """The report collection""" @@ -490,7 +593,7 @@ class Columns: Response for GetColumns """ - schema: Optional[Dict[str, Any]] = None + schema: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -499,14 +602,16 @@ class QuerySpecification: Definition: QuerySpecification """ - query: Optional[str] = None + query: str """The text of the query. Can be multiline text.""" - serializer_settings: Optional[Dict[str, Any]] = field( + serializer_settings: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "serializerSettings"}, ) - impersonated_user_name: Optional[str] = field( + impersonated_user_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "impersonatedUserName"}, ) """A user identity in UPN format to run the query as another user.""" @@ -518,9 +623,9 @@ class CreateScorecardRequest: Definition: CreateScorecardRequest """ - name: Optional[str] = None + name: str """Scorecard name""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Scorecard description""" @@ -530,11 +635,11 @@ class ListedScorecard: Definition: ListedScorecard """ - id: Optional[str] = None + id: str """The unique identifier of the scorecard.""" - name: Optional[str] = None + name: str """The name of the scorecard.""" - contact: Optional[str] = None + contact: Optional[str] = dataclass_field(default=None, kw_only=True) """Contact information for the scorecard.""" @@ -544,33 +649,36 @@ class CreateGoalRequest: Definition: CreateGoalRequest """ - name: Optional[str] = None + name: str """The name of the goal.""" - owner: Optional[str] = None + owner: Optional[str] = dataclass_field(default=None, kw_only=True) """The email address of the goal's owner. Example: foo@bar.com""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """The current value of the goal being tracked.""" - target: Optional[str] = None + target: Optional[str] = dataclass_field(default=None, kw_only=True) """The target value of the goal.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The current status the goal.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """The start date for the goal. Example: 2021-07-15.""" - completion_date: Optional[str] = field( + completion_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "completionDate"}, ) """The date for the goal to be completed by. Example: 2021-07-29.""" - note: Optional[str] = None + note: Optional[str] = dataclass_field(default=None, kw_only=True) """ Note to attach to the initial check-in on goal creation. Can be multiline text """ - parent_id: Optional[str] = field( + parent_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentId"}, ) """If this goal is a subgoal, the unique id of its parent goal.""" @@ -582,23 +690,25 @@ class UpdateGoalRequest: Definition: UpdateGoalRequest """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """If provided, the new name of the goal.""" - owner: Optional[str] = None + owner: Optional[str] = dataclass_field(default=None, kw_only=True) """If provided, the email address of the new goal owner.""" - value: Optional[float] = None + value: Optional[float] = dataclass_field(default=None, kw_only=True) """If provided, sets the new value of the goal.""" - target: Optional[float] = None + target: Optional[float] = dataclass_field(default=None, kw_only=True) """If provided, sets the new goal target.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """If provided, sets the new status of the goal.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDate"}, ) """If provided, the new start date for the goal. Example: 2021-07-15.""" - completion_date: Optional[str] = field( + completion_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "completionDate"}, ) """ @@ -613,14 +723,15 @@ class GoalRefreshIssue: Definition: GoalRefreshIssue """ - connection_type: Optional[str] = field( + connection_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "connectionType"}, ) """The connection type, either Current or Target.""" - timestamp: Optional[str] = None + timestamp: Optional[str] = dataclass_field(default=None, kw_only=True) """The timestamp of when the failed refresh happened.""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the error.""" @@ -630,12 +741,12 @@ class GoalValueCheckinRequest: Definition: GoalValueCheckinRequest """ - timestamp: Optional[str] = None + timestamp: str """Check-in date. Example: 2021-07-21""" - value: Optional[float] = None - status: Optional[str] = None + value: Optional[float] = dataclass_field(default=None, kw_only=True) + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status of the goal.""" - note: Optional[str] = None + note: Optional[str] = dataclass_field(default=None, kw_only=True) """Can be multiline text""" @@ -645,8 +756,8 @@ class GoalValueCheckinUpdateRequest: Definition: GoalValueCheckinUpdateRequest """ - value: Optional[float] = None - status: Optional[str] = None + value: Optional[float] = dataclass_field(default=None, kw_only=True) + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status of the goal.""" @@ -659,7 +770,7 @@ class Payload: Definition: Payload """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -672,13 +783,14 @@ class ExportPayloadPowerBIReport: Definition: ExportPayloadPowerBIReport """ - format: Optional[str] = None + format: str """ The export format for the Power BI report. The supported formats are: PPTX (PowerPoint), PDF, and PNG """ - power_b_i_report_export_configuration: Optional[Dict[str, Any]] = field( + power_b_i_report_export_configuration: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PowerBIReportExportConfiguration"}, ) """Power BI report Export to file configuration""" @@ -690,14 +802,15 @@ class ExportPayloadPaginatedReport: Definition: ExportPayloadPaginatedReport """ - format: Optional[str] = None + format: str """ The export format for the paginated report. The supported formats are: PPTX (PowerPoint), PDF, ACCESSIBLEPDF (Accessible PDF), XLSX (Excel), DOCX (Word), CSV, XML, MHTML, and Image (BMP, EMF, GIF, JPEG, PNG, or TIFF). """ - paginated_report_configuration: Optional[Dict[str, Any]] = field( + paginated_report_configuration: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "paginatedReportConfiguration"}, ) """paginatedReportConfiguration""" @@ -709,10 +822,11 @@ class ExportReportSettings: Definition: ExportReportSettings """ - locale: Optional[str] = None + locale: Optional[str] = dataclass_field(default=None, kw_only=True) """The locale to apply""" - include_hidden_pages: Optional[bool] = field( + include_hidden_pages: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "includeHiddenPages"}, ) """ @@ -728,9 +842,9 @@ class PageBookmark: Definition: PageBookmark """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The bookmark name""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """The bookmark state""" @@ -740,7 +854,7 @@ class ExportFilter: Definition: ExportFilter """ - filter: Optional[str] = None + filter: Optional[str] = dataclass_field(default=None, kw_only=True) """The filter to apply""" @@ -750,17 +864,24 @@ class ExportReportPage: Definition: ExportReportPage """ - page_name: Optional[str] = field( + page_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageName"}, ) """The page name""" - visual_name: Optional[str] = field( + visual_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "visualName"}, ) """(Optional) Visual name to be exported""" - bookmark: Optional[PageBookmark] = None + bookmark: Optional[ + PageBookmark | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) """(Optional) The bookmark to be applied on the page""" @@ -770,7 +891,7 @@ class EffectiveIdentity: Definition: EffectiveIdentity """ - username: Optional[str] = None + username: str """ The effective username reflected by a token for applying RLS rules (For OnPrem model, username can be composed of alpha-numerical characters or any @@ -778,31 +899,33 @@ class EffectiveIdentity: also username cannot contain spaces. For Cloud model, username can be composed of all ASCII characters. username must be up to 256 characters) """ - datasets: Optional[List[str]] = None + datasets: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """An array of datasets for which this identity applies""" - roles: Optional[List[str]] = None + roles: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ An array of RLS roles reflected by a token when applying RLS rules (identity can contain up to 50 roles, role can be composed of any character besides ',' and must be up to 50 characters) """ - custom_data: Optional[str] = field( + custom_data: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customData"}, ) """ The value of customdata to be used for applying RLS rules. Only supported for live connections to Azure Analysis Services. """ - identity_blob: Optional[IdentityBlob] = field( + identity_blob: Optional[IdentityBlob | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "identityBlob"}, ) """ A blob for specifying the identity. Only supported for datasets with Direct Query connection to SQL Azure """ - reports: Optional[List[str]] = None + reports: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ An array of reports for which this identity applies, Only supported for paginated reports @@ -815,7 +938,7 @@ class IdentityBlob: Definition: IdentityBlob """ - value: Optional[str] = None + value: str """OAuth2 access token for SQL Azure""" @@ -825,7 +948,7 @@ class DynamicPowerBiButtonClickedTriggerResult: Definition: DynamicPowerBiButtonClickedTriggerResult """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -838,8 +961,9 @@ class PowerBiButtonClickedOutputs: Definition: PowerBiButtonClickedOutputs """ - power_bi_inputs: Optional[Dict[str, Any]] = field( + power_bi_inputs: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PowerBiInputs"}, ) @@ -852,16 +976,16 @@ class PowerbiClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -872,8 +996,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -881,8 +1005,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -894,7 +1018,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -909,7 +1033,46 @@ def __init__( def connector_name(self) -> str: return "powerbi" - async def get_scorecards_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_scorecards( self, groupid: str, *, @@ -917,11 +1080,30 @@ async def get_scorecards_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get scorecards Gets a list of Power BI scorecards in the specified workspace. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetScorecards`. + + Args: + groupid: The unique identifier of the workspace. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -935,31 +1117,52 @@ async def get_scorecards_async( query_params.append("pbi_source=" + quote("powerAutomate", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def create_scorecard_async( + def create_scorecard( self, - input: CreateScorecardRequest, + input: CreateScorecardRequest | Mapping[str, Any], groupid: str, *, timeout: Optional[float] = None, @@ -971,6 +1174,23 @@ async def create_scorecard_async( Create a scorecard Creates a scorecard for Power BI goals. + + Swagger operation ID: `CreateScorecard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -985,7 +1205,7 @@ async def create_scorecard_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -999,6 +1219,7 @@ async def create_scorecard_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1006,7 +1227,7 @@ async def create_scorecard_async( return json.loads(response.text) - async def get_multiple_goals_async( + def list_multiple_goals( self, groupid: str, scorecard_id: str, @@ -1015,11 +1236,31 @@ async def get_multiple_goals_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get multiple goals Get a list of Power BI goals in the specified scorecard. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMultipleGoals`. + + Args: + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1035,31 +1276,52 @@ async def get_multiple_goals_async( query_params.append("pbi_source=" + quote("powerAutomate", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def create_goal_async( + return ItemPaged(get_next, extract_data) + + def create_goal( self, - input: CreateGoalRequest, + input: CreateGoalRequest | Mapping[str, Any], groupid: str, scorecard_id: str, *, @@ -1072,6 +1334,24 @@ async def create_goal_async( Create a goal Creates a Power BI goal on the specified scorecard. + + Swagger operation ID: `CreateGoal`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1087,7 +1367,7 @@ async def create_goal_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1101,6 +1381,7 @@ async def create_goal_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1108,7 +1389,7 @@ async def create_goal_async( return json.loads(response.text) - async def get_goal_async( + def get_goal( self, groupid: str, scorecard_id: str, @@ -1123,6 +1404,23 @@ async def get_goal_async( Get a goal Gets the specified Power BI goal on a scorecard. + + Swagger operation ID: `GetGoal`. + + Args: + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + goal_id: The unique identifier of the goal. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1139,7 +1437,7 @@ async def get_goal_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1153,6 +1451,7 @@ async def get_goal_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1160,9 +1459,9 @@ async def get_goal_async( return json.loads(response.text) - async def update_goal_async( + def update_goal( self, - input: UpdateGoalRequest, + input: UpdateGoalRequest | Mapping[str, Any], groupid: str, scorecard_id: str, goal_id: str, @@ -1176,6 +1475,25 @@ async def update_goal_async( Update a goal Updates the Power BI goal's state. + + Swagger operation ID: `UpdateGoal`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + goal_id: The unique identifier of the goal. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1191,7 +1509,7 @@ async def update_goal_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -1205,11 +1523,12 @@ async def update_goal_async( request_url, response.status, response.text, + response=response, ) - async def execute_dataset_query_async( + def execute_dataset_query( self, - input: QuerySpecification, + input: QuerySpecification | Mapping[str, Any], groupid: str, datasetid: str, *, @@ -1222,6 +1541,24 @@ async def execute_dataset_query_async( Run a query against a dataset Use the Power BI REST API to run a query. + + Swagger operation ID: `ExecuteDatasetQuery`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + datasetid: The unique identifier of the dataset. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1238,7 +1575,7 @@ async def execute_dataset_query_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1252,6 +1589,7 @@ async def execute_dataset_query_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1259,9 +1597,9 @@ async def execute_dataset_query_async( return json.loads(response.text) - async def execute_dataset_queries_json_async( + def execute_dataset_queries_json( self, - input: ExecuteDatasetQueriesJsonInput, + input: ExecuteDatasetQueriesJsonInput | Mapping[str, Any], groupid: str, datasetid: str, *, @@ -1274,6 +1612,24 @@ async def execute_dataset_queries_json_async( Run a json query against a dataset Use the Power BI REST API to run a query in json format. + + Swagger operation ID: `ExecuteDatasetQueriesJson`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + datasetid: The unique identifier of the dataset. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1291,7 +1647,7 @@ async def execute_dataset_queries_json_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1305,6 +1661,7 @@ async def execute_dataset_queries_json_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1312,9 +1669,9 @@ async def execute_dataset_queries_json_async( return json.loads(response.text) - async def add_rows_async( + def add_rows( self, - input: Payload, + input: Payload | Mapping[str, Any], groupid: str, datasetid: str, tablename: str, @@ -1328,6 +1685,25 @@ async def add_rows_async( Add rows to a dataset Use Power BI REST API to add rows to a dataset. + + Swagger operation ID: `AddRows`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + datasetid: The unique identifier of the dataset. + tablename: The name of the table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1346,7 +1722,7 @@ async def add_rows_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1360,9 +1736,10 @@ async def add_rows_async( request_url, response.status, response.text, + response=response, ) - async def goal_value_checkin_note_async( + def goal_value_checkin_note( self, input: GoalValueCheckinNoteInput, groupid: str, @@ -1379,6 +1756,25 @@ async def goal_value_checkin_note_async( Add a note to a check-in Appends a new note to a check-in of a Power BI goal. + + Swagger operation ID: `GoalValueCheckinNote`. + + Args: + input: The request body. + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + goal_id: The unique identifier of the goal. + goal_checkin: Example: 2021-07-21. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1396,7 +1792,7 @@ async def goal_value_checkin_note_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1410,11 +1806,12 @@ async def goal_value_checkin_note_async( request_url, response.status, response.text, + response=response, ) - async def goal_value_checkin_async( + def goal_value_checkin( self, - input: GoalValueCheckinRequest, + input: GoalValueCheckinRequest | Mapping[str, Any], groupid: str, scorecard_id: str, goal_id: str, @@ -1428,6 +1825,25 @@ async def goal_value_checkin_async( Create a check-in Creates a Power BI goal check-in. + + Swagger operation ID: `GoalValueCheckin`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + goal_id: The unique identifier of the goal. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1444,7 +1860,7 @@ async def goal_value_checkin_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1458,9 +1874,10 @@ async def goal_value_checkin_async( request_url, response.status, response.text, + response=response, ) - async def get_goal_checkins_async( + def list_goal_checkins( self, groupid: str, scorecard_id: str, @@ -1470,11 +1887,32 @@ async def get_goal_checkins_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get goal check-ins Get all check-ins on a Power BI goal. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetGoalCheckins`. + + Args: + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + goal_id: The unique identifier of the goal. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1491,31 +1929,52 @@ async def get_goal_checkins_async( query_params.append("$expand=" + quote("notes", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def update_goal_checkin_async( + return ItemPaged(get_next, extract_data) + + def update_goal_checkin( self, - input: GoalValueCheckinUpdateRequest, + input: GoalValueCheckinUpdateRequest | Mapping[str, Any], groupid: str, scorecard_id: str, goal_id: str, @@ -1530,6 +1989,26 @@ async def update_goal_checkin_async( Update a check-in Updates a Power BI goal check-in. + + Swagger operation ID: `UpdateGoalCheckin`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + goal_id: The unique identifier of the goal. + goal_checkin: Example: 2021-07-21. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1546,7 +2025,7 @@ async def update_goal_checkin_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -1560,9 +2039,10 @@ async def update_goal_checkin_async( request_url, response.status, response.text, + response=response, ) - async def get_goal_checkin_async( + def get_goal_checkin( self, groupid: str, scorecard_id: str, @@ -1578,6 +2058,24 @@ async def get_goal_checkin_async( Get a goal check-in Get a check-in on a Power BI goal. + + Swagger operation ID: `GetGoalCheckin`. + + Args: + groupid: The unique identifier of the workspace. + scorecard_id: The unique identifier of the scorecard. + goal_id: The unique identifier of the goal. + goal_checkin: Example: 2021-07-21. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1595,7 +2093,7 @@ async def get_goal_checkin_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1609,6 +2107,7 @@ async def get_goal_checkin_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1616,7 +2115,7 @@ async def get_goal_checkin_async( return json.loads(response.text) - async def refresh_dataset_async( + def refresh_dataset( self, groupid: str, datasetid: str, @@ -1630,6 +2129,22 @@ async def refresh_dataset_async( Refresh a dataset Use Power BI REST API to refresh a powerbi dataset. + + Swagger operation ID: `RefreshDataset`. + + Args: + groupid: The unique identifier of the workspace. + datasetid: The unique identifier of the dataset. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1646,7 +2161,7 @@ async def refresh_dataset_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1660,11 +2175,12 @@ async def refresh_dataset_async( request_url, response.status, response.text, + response=response, ) - async def initiate_export_to_file_for_pbi_reports_async( + def initiate_export_to_file_for_pbi_reports( self, - input: ExportPayloadPowerBIReport, + input: ExportPayloadPowerBIReport | Mapping[str, Any], groupid: str, reportid: str, *, @@ -1677,6 +2193,24 @@ async def initiate_export_to_file_for_pbi_reports_async( Export To File for Power BI Reports Use Power BI Rest API to inititate export for Power BI reports + + Swagger operation ID: `InitiateExportToFileForPbiReports`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + reportid: The unique identifier of a pbi report. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1689,7 +2223,7 @@ async def initiate_export_to_file_for_pbi_reports_async( f"/ExportTo" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1703,13 +2237,14 @@ async def initiate_export_to_file_for_pbi_reports_async( request_url, response.status, response.text, + response=response, ) return response.content - async def initiate_export_to_file_for_paginated_reports_async( + def initiate_export_to_file_for_paginated_reports( self, - input: ExportPayloadPaginatedReport, + input: ExportPayloadPaginatedReport | Mapping[str, Any], groupid: str, reportid: str, *, @@ -1722,6 +2257,24 @@ async def initiate_export_to_file_for_paginated_reports_async( Export To File for Paginated Reports Use Power BI Rest API to inititate export for paginated reports + + Swagger operation ID: `InitiateExportToFileForPaginatedReports`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + groupid: The unique identifier of the workspace. + reportid: The unique identifier of a paginated report. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1734,7 +2287,7 @@ async def initiate_export_to_file_for_paginated_reports_async( f"/ExportToPaginatedReports" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1748,91 +2301,170 @@ async def initiate_export_to_file_for_paginated_reports_async( request_url, response.status, response.text, + response=response, ) return response.content - async def list_groups_async( + def list_groups( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ ListGroups Get Groups for Power BI. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListGroups`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/myorg/groups" query_params = [] query_params.append("pbi_source=" + quote("powerAutomate", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def get_alerts_async( + return ItemPaged(get_next, extract_data) + + def list_alerts( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get alerts from Power BI Return a list of alerts for a signed in user. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAlerts`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/metadata/v201606/alerts" query_params = [] query_params.append("pbi_source=" + quote("powerAutomate", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def list_datasets_async( + return ItemPaged(get_next, extract_data) + + def list_datasets( self, groupid: str, *, @@ -1840,11 +2472,30 @@ async def list_datasets_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ ListDatasets Get datasets for Power BI group. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListDatasets`. + + Args: + groupid: The unique identifier of the workspace. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1854,29 +2505,50 @@ async def list_datasets_async( query_params.append("pbi_source=" + quote("powerAutomate", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def list_tables_async( + def list_tables( self, groupid: str, datasetid: str, @@ -1885,11 +2557,31 @@ async def list_tables_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ ListTables Get tables for Power BI dataset. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTables`. + + Args: + groupid: The unique identifier of the workspace. + datasetid: The unique identifier of the dataset. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1905,29 +2597,50 @@ async def list_tables_async( query_params.append("pbi_source=" + quote("powerAutomate", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_reports_in_group_async( + def list_reports_in_group( self, groupid: str, *, @@ -1935,39 +2648,79 @@ async def get_reports_in_group_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Reports in Group Returns a list of reports from the specified workspace. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetReportsInGroup`. + + Args: + groupid: The unique identifier of the workspace. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/myorg/groups/{quote(str(groupid), safe='')}/reports" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_columns_async( + def get_columns( self, groupid: str, datasetid: str, @@ -1982,6 +2735,23 @@ async def get_columns_async( GetColumns Get columns for Power BI dataset table. + + Swagger operation ID: `GetColumns`. + + Args: + groupid: The unique identifier of the workspace. + datasetid: The unique identifier of the dataset. + tablename: The name of the table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2000,7 +2770,7 @@ async def get_columns_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2014,6 +2784,7 @@ async def get_columns_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/projectplace.py b/src/azure/connectors/projectplace.py index 2c23698..fa22af2 100644 --- a/src/azure/connectors/projectplace.py +++ b/src/azure/connectors/projectplace.py @@ -5,21 +5,34 @@ from __future__ import annotations -from dataclasses import dataclass -from typing import Optional, Dict, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "ProjectplaceClient", + "CreateCardInput", + "CreateCardResponse", + "MoveCardInput", + "MoveCardResponse", + "SetWebhookCardCreateInput", + "SetWebhookCardDueDateInput", + "SetWebhookPropertiesChangeInput", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,11 +42,11 @@ class SetWebhookCardCreateInput: When a card is created """ - card_create: Optional[bool] = None + card_create: bool """Triggers when a card is created on the defined board""" - webhook: Optional[str] = None + webhook: str """webhook""" - board_id: Optional[int] = None + board_id: int """The id of the Board that the card belongs to""" @@ -43,24 +56,24 @@ class SetWebhookPropertiesChangeInput: When a card's properties are changed """ - card_blocked: Optional[bool] = None + card_blocked: bool """Triggers when a card is blocked""" - card_unblock: Optional[bool] = None + card_unblock: bool """Triggers when a card block is removed""" - status_change: Optional[bool] = None + status_change: bool """Triggers when a card is moved to another column on the""" - card_done: Optional[bool] = None + card_done: bool """ Triggers when a card is set to done by moving it to the rightmost column on the board """ - description_changed: Optional[bool] = None + description_changed: bool """Triggers when the description of a card changes""" - due_date_changed: Optional[bool] = None + due_date_changed: bool """Triggers when the due date of a card changes""" - webhook: Optional[str] = None + webhook: str """webhook""" - board_id: Optional[int] = None + board_id: int """The id of the Board that the card belongs to""" @@ -70,11 +83,11 @@ class SetWebhookCardDueDateInput: When a card is due """ - due_today: Optional[bool] = None + due_today: bool """Triggers on the date that the card is due""" - webhook: Optional[str] = None + webhook: str """webhook""" - board_id: Optional[int] = None + board_id: int """The id of the Board that the card belongs to""" @@ -84,19 +97,19 @@ class CreateCardInput: Create Card """ - column_id: Optional[int] = None + column_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The column where the card should be created""" - title: Optional[str] = None + title: str """The title of the created card""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the created card""" - assignee_email: Optional[str] = None + assignee_email: Optional[str] = dataclass_field(default=None, kw_only=True) """The person that will be assigned to the created card""" - planlet_id: Optional[int] = None + planlet_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The activity the Card should be associated with""" - due_date: Optional[str] = None + due_date: Optional[str] = dataclass_field(default=None, kw_only=True) """The due date of the created card""" - label_id: Optional[int] = None + label_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The label of the created card""" @@ -106,39 +119,39 @@ class CreateCardResponse: Response for Create Card """ - access: Optional[str] = None + access: Optional[str] = dataclass_field(default=None, kw_only=True) """Access rights""" - assignee: Optional[Dict[str, Any]] = None + assignee: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The person who is assigned to the card""" - assignee_id: Optional[int] = None + assignee_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The id of the person who is assigned the card""" - board_id: Optional[int] = None + board_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The ID of the board""" - board_name: Optional[str] = None + board_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the board""" - direct_url: Optional[str] = None + direct_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The card's direct URL""" - due_date: Optional[str] = None + due_date: Optional[str] = dataclass_field(default=None, kw_only=True) """The due date of the card""" - estimated_time: Optional[str] = None + estimated_time: Optional[str] = dataclass_field(default=None, kw_only=True) """Estimated time for completion""" - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The ID of the card""" - is_blocked: Optional[bool] = None + is_blocked: Optional[bool] = dataclass_field(default=None, kw_only=True) """Is the card is""" - is_blocked_reason: Optional[str] = None + is_blocked_reason: Optional[str] = dataclass_field(default=None, kw_only=True) """The blocking reason - if blocked""" - is_done: Optional[bool] = None + is_done: Optional[bool] = dataclass_field(default=None, kw_only=True) """Is the card done""" - is_template: Optional[bool] = None + is_template: Optional[bool] = dataclass_field(default=None, kw_only=True) """Is a template card""" - label_id: Optional[int] = None + label_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The id of the label""" - planlet_id: Optional[int] = None + planlet_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The id of the activity""" - reported_time: Optional[str] = None + reported_time: Optional[str] = dataclass_field(default=None, kw_only=True) """How much time was reported for the card""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The card's title""" @@ -148,11 +161,11 @@ class MoveCardInput: Move card to another column """ - card_id: Optional[int] = None + card_id: int """The card to be moved""" - card_title: Optional[str] = None + card_title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the card to be moved""" - column_id: Optional[int] = None + column_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The column where the card should be moved to""" @@ -162,45 +175,45 @@ class MoveCardResponse: Response for Move card to another column """ - access: Optional[str] = None + access: Optional[str] = dataclass_field(default=None, kw_only=True) """Access rights""" - assignee_id: Optional[int] = None + assignee_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The ID of the person the card assigned to""" - board_id: Optional[int] = None + board_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The ID of the board""" - board_name: Optional[str] = None + board_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the board""" - column_id: Optional[int] = None + column_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The id of the column the card is on""" - column_name: Optional[str] = None + column_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the column""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """The description on the card""" - direct_url: Optional[str] = None + direct_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The direct URL of the card""" - due_date: Optional[str] = None + due_date: Optional[str] = dataclass_field(default=None, kw_only=True) """The due date of the card""" - estimated_time: Optional[str] = None + estimated_time: Optional[str] = dataclass_field(default=None, kw_only=True) """The estimated time of the card""" - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The id of the card""" - is_blocked: Optional[bool] = None + is_blocked: Optional[bool] = dataclass_field(default=None, kw_only=True) """Is the card blocked""" - is_blocked_reason: Optional[str] = None + is_blocked_reason: Optional[str] = dataclass_field(default=None, kw_only=True) """The reason the card is blocked""" - is_done: Optional[bool] = None + is_done: Optional[bool] = dataclass_field(default=None, kw_only=True) """Is the card done""" - is_template: Optional[bool] = None + is_template: Optional[bool] = dataclass_field(default=None, kw_only=True) """Is a template card""" - label_id: Optional[int] = None + label_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The id of the card's label""" - label_name: Optional[str] = None + label_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the label""" - planlet_id: Optional[int] = None + planlet_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The id of the activity""" - reported_time: Optional[str] = None + reported_time: Optional[str] = dataclass_field(default=None, kw_only=True) """The time reported for this card""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the card""" @@ -212,16 +225,16 @@ class ProjectplaceClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -232,8 +245,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -241,8 +254,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -254,7 +267,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -269,9 +282,48 @@ def __init__( def connector_name(self) -> str: return "projectplace" - async def create_card_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def create_card( self, - input: CreateCardInput, + input: CreateCardInput | Mapping[str, Any], board_id: int, *, timeout: Optional[float] = None, @@ -283,6 +335,23 @@ async def create_card_async( Create Card Creates a new card with the parameters provided + + Swagger operation ID: `create_card`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + board_id: The id of the Board where the card should be created. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -292,7 +361,7 @@ async def create_card_async( f"/create_card" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -306,6 +375,7 @@ async def create_card_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -313,9 +383,9 @@ async def create_card_async( return json.loads(response.text) - async def move_card_async( + def move_card( self, - input: MoveCardInput, + input: MoveCardInput | Mapping[str, Any], board_id: int, *, timeout: Optional[float] = None, @@ -327,6 +397,23 @@ async def move_card_async( Move card to another column Move a card on the selected board + + Swagger operation ID: `move_card`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + board_id: The id of the Board where the card should be created. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -336,7 +423,7 @@ async def move_card_async( f"/move_card" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -350,6 +437,7 @@ async def move_card_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -357,44 +445,83 @@ async def move_card_async( return json.loads(response.text) - async def list_boards_async( + def list_boards( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Lists the boards the user have access to Lists the boards that are part of the projects the user have access to + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `list_boards`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1/external_notifications/lists/list_boards" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/replicon.py b/src/azure/connectors/replicon.py index b6028c5..ea4d1f0 100644 --- a/src/azure/connectors/replicon.py +++ b/src/azure/connectors/replicon.py @@ -5,14 +5,13 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, Dict, List, Any, Mapping from urllib.parse import quote import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, @@ -20,6 +19,35 @@ ConnectorResponseHook, ) +__all__ = [ + "RepliconClient", + "BulkGetProjectDetails3Input", + "BulkGetTimeEnteredSummaryInput", + "BulkGetTimeEnteredSummaryResponse", + "CreateProjectOrApplyModificationsInput", + "CreateProjectOrApplyModificationsResponse", + "CreateTaskHierarchyOrApplyModificationsInput", + "CreateTaskHierarchyOrApplyModificationsResponse", + "Date", + "Duration", + "GetDescendantTaskDetailsInput", + "GetDescendantTaskDetailsResponse", + "GetTimesheetSummaryInput", + "GetTimesheetSummaryResponse", + "MoveTaskInput", + "ProjectDetailsResponse", + "PutProjectTeamMemberAssignmentsInput", + "PutResourceAssignmentsInput", + "TaskListServiceGetDataInput", + "TaskListServiceGetDataResponse", + "TenantEndpointDetails", + "UserListServiceGetDataInput", + "UserListServiceGetDataResponse", + "WebhookSubscriptionResponse", + "WebhookSubscriptionsRestAPIInput", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +57,7 @@ class BulkGetProjectDetails3Input: Get Project Details """ - projects: Optional[List[Dict[str, Any]]] = None + projects: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """projects""" @@ -39,7 +67,7 @@ class ProjectDetailsResponse: Response for Get Project Details """ - d: Optional[List[Dict[str, Any]]] = None + d: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """d""" @@ -49,17 +77,19 @@ class CreateProjectOrApplyModificationsInput: Create Project Or Apply Modifications """ - target: Optional[Dict[str, Any]] = None + target: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """project target""" - modifications: Optional[Dict[str, Any]] = None + modifications: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """modifications""" - project_modification_option_uri: Optional[str] = field( + project_modification_option_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "projectModificationOptionUri"}, ) """project modification option uri""" - unit_of_work_id: Optional[str] = field( + unit_of_work_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "unitOfWorkId"}, ) """unit of work id""" @@ -71,7 +101,7 @@ class CreateProjectOrApplyModificationsResponse: Response for Create Project Or Apply Modifications """ - d: Optional[Dict[str, Any]] = None + d: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """d""" @@ -81,19 +111,21 @@ class UserListServiceGetDataInput: Get User List """ - page: Optional[str] = None + page: Optional[str] = dataclass_field(default=None, kw_only=True) """page""" - pagesize: Optional[str] = None + pagesize: Optional[str] = dataclass_field(default=None, kw_only=True) """page size""" - column_uris: Optional[List[str]] = field( + column_uris: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "columnUris"}, ) """column uris""" - sort: Optional[List[Any]] = None + sort: Optional[List[Any]] = dataclass_field(default=None, kw_only=True) """sort""" - filter_expression: Optional[Dict[str, Any]] = field( + filter_expression: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterExpression"}, ) """filter expression""" @@ -105,7 +137,7 @@ class UserListServiceGetDataResponse: Response for Get User List """ - d: Optional[Dict[str, Any]] = None + d: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """d""" @@ -115,8 +147,9 @@ class GetDescendantTaskDetailsInput: Get Descendant Task Details """ - parent_uri: Optional[str] = field( + parent_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentUri"}, ) """parent uri""" @@ -128,7 +161,7 @@ class GetDescendantTaskDetailsResponse: Response for Get Descendant Task Details """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -141,20 +174,23 @@ class CreateTaskHierarchyOrApplyModificationsInput: Create Task Hierarchy Or Apply Modifications """ - project: Optional[Dict[str, Any]] = None + project: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """project""" - task_hierarchy: Optional[List[Dict[str, Any]]] = field( + task_hierarchy: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "taskHierarchy"}, ) """task hierarchy""" - task_modification_option_uri: Optional[str] = field( + task_modification_option_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "taskModificationOptionUri"}, ) """task modification option uri""" - unit_of_work_id: Optional[str] = field( + unit_of_work_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "unitOfWorkId"}, ) """unit of work id""" @@ -166,7 +202,7 @@ class CreateTaskHierarchyOrApplyModificationsResponse: Response for Create Task Hierarchy Or Apply Modifications """ - d: Optional[List[Dict[str, Any]]] = None + d: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """d""" @@ -176,18 +212,21 @@ class MoveTaskInput: Move Task """ - task_uri: Optional[str] = field( + task_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "taskUri"}, ) """task uri""" - target_uri: Optional[str] = field( + target_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "targetUri"}, ) """target uri""" - move_task_method_uri: Optional[str] = field( + move_task_method_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "moveTaskMethodUri"}, ) """move task method uri""" @@ -199,19 +238,21 @@ class TaskListServiceGetDataInput: Task List Service Get Data """ - page: Optional[str] = None + page: Optional[str] = dataclass_field(default=None, kw_only=True) """page""" - pagesize: Optional[str] = None + pagesize: Optional[str] = dataclass_field(default=None, kw_only=True) """page size""" - column_uris: Optional[List[str]] = field( + column_uris: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "columnUris"}, ) """column uris""" - sort: Optional[List[Any]] = None + sort: Optional[List[Any]] = dataclass_field(default=None, kw_only=True) """sort""" - filter_expression: Optional[Dict[str, Any]] = field( + filter_expression: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterExpression"}, ) """filter expression""" @@ -223,7 +264,7 @@ class TaskListServiceGetDataResponse: Response for Task List Service Get Data """ - d: Optional[Dict[str, Any]] = None + d: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """d""" @@ -233,8 +274,9 @@ class GetTimesheetSummaryInput: Get Timesheet Summary """ - timesheet_uri: Optional[str] = field( + timesheet_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "timesheetUri"}, ) """timesheet uri""" @@ -246,7 +288,7 @@ class GetTimesheetSummaryResponse: Response for Get Timesheet Summary """ - d: Optional[Dict[str, Any]] = None + d: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """d""" @@ -256,8 +298,9 @@ class BulkGetTimeEnteredSummaryInput: Get Time Entered Summary """ - task_uris: Optional[List[str]] = field( + task_uris: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "taskUris"}, ) """task uris""" @@ -269,7 +312,7 @@ class BulkGetTimeEnteredSummaryResponse: Response for Get Time Entered Summary """ - d: Optional[List[Dict[str, Any]]] = None + d: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """d""" @@ -279,15 +322,13 @@ class WebhookSubscriptionsRestAPIInput: Subscribe to Event triggers """ - event_type: Optional[str] = field( + event_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventType"}, ) """Event type to subscribe to""" - target_url: Optional[str] = field( - default=None, - metadata={"wire_name": "targetUrl"}, - ) + target_url: str = dataclass_field(metadata={"wire_name": "targetUrl"}) """target url""" @@ -297,35 +338,41 @@ class WebhookSubscriptionResponse: Response for Subscribe to Event triggers """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """identity of the webhook event""" - created_timestamp: Optional[str] = field( + created_timestamp: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdTimestamp"}, ) """created time stamp of the webhook event""" - updated_timestamp: Optional[str] = field( + updated_timestamp: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "updatedTimestamp"}, ) """updated time stamp of the webhook event""" - event_type: Optional[str] = field( + event_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventType"}, ) """event Type of the webhook event""" - target_url: Optional[str] = field( + target_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "targetUrl"}, ) """target Url of the webhook event""" - shared_secret: Optional[str] = field( + shared_secret: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sharedSecret"}, ) """shared Secret of the webhook event""" - auth_type: Optional[str] = field( + auth_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "authType"}, ) """auth Type of the webhook event""" @@ -337,13 +384,15 @@ class PutProjectTeamMemberAssignmentsInput: Put Project Team Member Assignments """ - project_uri: Optional[str] = field( + project_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "projectUri"}, ) """project uri""" - resource_uris: Optional[List[str]] = field( + resource_uris: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceUris"}, ) """resource uris""" @@ -355,13 +404,15 @@ class PutResourceAssignmentsInput: Rewrite Resource Assignment of a task """ - task_uri: Optional[str] = field( + task_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "taskUri"}, ) """task uri""" - resource_uris: Optional[List[str]] = field( + resource_uris: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceUris"}, ) """resource uris""" @@ -373,7 +424,7 @@ class TenantEndpointDetails: Response for Get Tenant End Point Details """ - d: Optional[Dict[str, Any]] = None + d: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """d""" @@ -383,11 +434,11 @@ class Date: Definition: Date """ - day: Optional[int] = None + day: Optional[int] = dataclass_field(default=None, kw_only=True) """day""" - month: Optional[int] = None + month: Optional[int] = dataclass_field(default=None, kw_only=True) """month""" - year: Optional[int] = None + year: Optional[int] = dataclass_field(default=None, kw_only=True) """year""" @@ -397,15 +448,15 @@ class Duration: Definition: Duration """ - hours: Optional[int] = None + hours: Optional[int] = dataclass_field(default=None, kw_only=True) """hours""" - microseconds: Optional[int] = None + microseconds: Optional[int] = dataclass_field(default=None, kw_only=True) """microseconds""" - milliseconds: Optional[int] = None + milliseconds: Optional[int] = dataclass_field(default=None, kw_only=True) """milliseconds""" - minutes: Optional[int] = None + minutes: Optional[int] = dataclass_field(default=None, kw_only=True) """minutes""" - seconds: Optional[int] = None + seconds: Optional[int] = dataclass_field(default=None, kw_only=True) """seconds""" @@ -417,16 +468,16 @@ class RepliconClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -437,8 +488,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -446,8 +497,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -459,7 +510,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -474,9 +525,9 @@ def __init__( def connector_name(self) -> str: return "replicon" - async def bulk_get_project_details3_async( + def bulk_get_project_details3( self, - input: BulkGetProjectDetails3Input, + input: BulkGetProjectDetails3Input | Mapping[str, Any], host_url: str, *, timeout: Optional[float] = None, @@ -488,6 +539,23 @@ async def bulk_get_project_details3_async( Get Project Details Get the project details from Replicon + + Swagger operation ID: `BulkGetProjectDetails3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -501,7 +569,7 @@ async def bulk_get_project_details3_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -515,6 +583,7 @@ async def bulk_get_project_details3_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -522,9 +591,9 @@ async def bulk_get_project_details3_async( return json.loads(response.text) - async def create_project_or_apply_modifications_async( + def create_project_or_apply_modifications( self, - input: CreateProjectOrApplyModificationsInput, + input: CreateProjectOrApplyModificationsInput | Mapping[str, Any], host_url: str, *, timeout: Optional[float] = None, @@ -536,6 +605,23 @@ async def create_project_or_apply_modifications_async( Create Project Or Apply Modifications Create Project Or Apply Modifications in Replicon + + Swagger operation ID: `CreateProjectOrApplyModifications`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -549,7 +635,7 @@ async def create_project_or_apply_modifications_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -563,6 +649,7 @@ async def create_project_or_apply_modifications_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -570,9 +657,9 @@ async def create_project_or_apply_modifications_async( return json.loads(response.text) - async def user_list_service_get_data_async( + def user_list_service_get_data( self, - input: UserListServiceGetDataInput, + input: UserListServiceGetDataInput | Mapping[str, Any], host_url: str, *, timeout: Optional[float] = None, @@ -584,6 +671,23 @@ async def user_list_service_get_data_async( Get User List Get User List Data from Replicon + + Swagger operation ID: `UserListServiceGetData`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -597,7 +701,7 @@ async def user_list_service_get_data_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -611,6 +715,7 @@ async def user_list_service_get_data_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -618,9 +723,9 @@ async def user_list_service_get_data_async( return json.loads(response.text) - async def get_descendant_task_details_async( + def get_descendant_task_details( self, - input: GetDescendantTaskDetailsInput, + input: GetDescendantTaskDetailsInput | Mapping[str, Any], host_url: str, *, timeout: Optional[float] = None, @@ -632,6 +737,23 @@ async def get_descendant_task_details_async( Get Descendant Task Details Get Hierarchial Task Details from Replicon + + Swagger operation ID: `GetDescendantTaskDetails`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -645,7 +767,7 @@ async def get_descendant_task_details_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -659,6 +781,7 @@ async def get_descendant_task_details_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -666,9 +789,9 @@ async def get_descendant_task_details_async( return json.loads(response.text) - async def create_task_hierarchy_or_apply_modifications_async( + def create_task_hierarchy_or_apply_modifications( self, - input: CreateTaskHierarchyOrApplyModificationsInput, + input: CreateTaskHierarchyOrApplyModificationsInput | Mapping[str, Any], host_url: str, *, timeout: Optional[float] = None, @@ -680,6 +803,23 @@ async def create_task_hierarchy_or_apply_modifications_async( Create Task Hierarchy Or Apply Modifications Create Task Hierarchy Or Apply Modifications to a Replicon Task + + Swagger operation ID: `CreateTaskHierarchyOrApplyModifications`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -695,7 +835,7 @@ async def create_task_hierarchy_or_apply_modifications_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -709,6 +849,7 @@ async def create_task_hierarchy_or_apply_modifications_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -716,9 +857,9 @@ async def create_task_hierarchy_or_apply_modifications_async( return json.loads(response.text) - async def move_task_async( + def move_task( self, - input: MoveTaskInput, + input: MoveTaskInput | Mapping[str, Any], host_url: str, *, timeout: Optional[float] = None, @@ -730,6 +871,23 @@ async def move_task_async( Move Task Move Task to a new Parent + + Swagger operation ID: `MoveTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -743,7 +901,7 @@ async def move_task_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -757,11 +915,12 @@ async def move_task_async( request_url, response.status, response.text, + response=response, ) - async def task_list_service_get_data_async( + def task_list_service_get_data( self, - input: TaskListServiceGetDataInput, + input: TaskListServiceGetDataInput | Mapping[str, Any], host_url: str, *, timeout: Optional[float] = None, @@ -773,6 +932,23 @@ async def task_list_service_get_data_async( Task List Service Get Data Get Task List Service Data From Replicon + + Swagger operation ID: `TaskListServiceGetData`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -786,7 +962,7 @@ async def task_list_service_get_data_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -800,6 +976,7 @@ async def task_list_service_get_data_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -807,9 +984,9 @@ async def task_list_service_get_data_async( return json.loads(response.text) - async def get_timesheet_summary_async( + def get_timesheet_summary( self, - input: GetTimesheetSummaryInput, + input: GetTimesheetSummaryInput | Mapping[str, Any], host_url: str, *, timeout: Optional[float] = None, @@ -821,6 +998,23 @@ async def get_timesheet_summary_async( Get Timesheet Summary Get Timesheet Summary from Replicon + + Swagger operation ID: `GetTimesheetSummary`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -834,7 +1028,7 @@ async def get_timesheet_summary_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -848,6 +1042,7 @@ async def get_timesheet_summary_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -855,9 +1050,9 @@ async def get_timesheet_summary_async( return json.loads(response.text) - async def bulk_get_time_entered_summary_async( + def bulk_get_time_entered_summary( self, - input: BulkGetTimeEnteredSummaryInput, + input: BulkGetTimeEnteredSummaryInput | Mapping[str, Any], host_url: str, *, timeout: Optional[float] = None, @@ -869,6 +1064,23 @@ async def bulk_get_time_entered_summary_async( Get Time Entered Summary Get Time Entered by Task Uri from Replicon + + Swagger operation ID: `BulkGetTimeEnteredSummary`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -882,7 +1094,7 @@ async def bulk_get_time_entered_summary_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -896,6 +1108,7 @@ async def bulk_get_time_entered_summary_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -903,9 +1116,9 @@ async def bulk_get_time_entered_summary_async( return json.loads(response.text) - async def put_project_team_member_assignments_async( + def put_project_team_member_assignments( self, - input: PutProjectTeamMemberAssignmentsInput, + input: PutProjectTeamMemberAssignmentsInput | Mapping[str, Any], host_url: str, *, timeout: Optional[float] = None, @@ -917,6 +1130,23 @@ async def put_project_team_member_assignments_async( Put Project Team Member Assignments Rewrite Team Member assignment of Project + + Swagger operation ID: `PutProjectTeamMemberAssignments`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -930,7 +1160,7 @@ async def put_project_team_member_assignments_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -944,11 +1174,12 @@ async def put_project_team_member_assignments_async( request_url, response.status, response.text, + response=response, ) - async def put_resource_assignments_async( + def put_resource_assignments( self, - input: PutResourceAssignmentsInput, + input: PutResourceAssignmentsInput | Mapping[str, Any], host_url: str, *, timeout: Optional[float] = None, @@ -960,6 +1191,23 @@ async def put_resource_assignments_async( Rewrite Resource Assignment of a task Update the Resource assignment to a specified task + + Swagger operation ID: `PutResourceAssignments`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + host_url: Replicon Host Url. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -973,7 +1221,7 @@ async def put_resource_assignments_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -987,9 +1235,10 @@ async def put_resource_assignments_async( request_url, response.status, response.text, + response=response, ) - async def get_my_tenant_endpoint_details_async( + def get_my_tenant_endpoint_details( self, *, timeout: Optional[float] = None, @@ -1001,13 +1250,27 @@ async def get_my_tenant_endpoint_details_async( Get Tenant End Point Details Get End Point Details of the Tenant + + Swagger operation ID: `GetMyTenantEndpointDetails`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/DiscoveryService1.svc/GetMyTenantEndpointDetails" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1021,6 +1284,7 @@ async def get_my_tenant_endpoint_details_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/revai.py b/src/azure/connectors/revai.py index 9050c6e..1a9caa5 100644 --- a/src/azure/connectors/revai.py +++ b/src/azure/connectors/revai.py @@ -5,21 +5,50 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "RevaiClient", + "AccountGetResponse", + "AlignmentGetResponse", + "AlignmentInput", + "AlignmentPostResponse", + "AlignmentTranscriptGetResponse", + "AnalysisGetResponse", + "AnalysisInput", + "AnalysisPostResponse", + "AnalysisResultGetResponse", + "ExtractionGetResponse", + "ExtractionInput", + "ExtractionPostResponse", + "ExtractionResultGetResponse", + "IdentificationGetResponse", + "IdentificationInput", + "IdentificationPostResponse", + "IdentificationResultGetResponse", + "TranscriptGetResponse", + "TranscriptionGetResponse", + "TranscriptionInput", + "TranscriptionPostResponse", + "VocabularyGetResponse", + "VocabularyInput", + "VocabularyPostResponse", +] + # Type Definitions @@ -29,15 +58,15 @@ class TranscriptionGetResponse: Response for Get transcription job """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status.""" - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The language.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """When created on.""" - transcriber: Optional[str] = None + transcriber: Optional[str] = dataclass_field(default=None, kw_only=True) """The transcriber.""" @@ -47,42 +76,57 @@ class TranscriptionInput: Submit transcription job """ - source_config: Optional[Dict[str, Any]] = None - metadata: Optional[str] = None + source_config: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + metadata: Optional[str] = dataclass_field(default=None, kw_only=True) """The metadata.""" - notification_config: Optional[Dict[str, Any]] = None - delete_after_seconds: Optional[int] = None + notification_config: Dict[str, Any] + delete_after_seconds: Optional[int] = dataclass_field(default=None, kw_only=True) """The delete after seconds.""" - transcriber: Optional[str] = None + transcriber: Optional[str] = dataclass_field(default=None, kw_only=True) """The transcriber.""" - verbatim: Optional[bool] = None + verbatim: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether verbatim.""" - rush: Optional[bool] = None + rush: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to rush.""" - test_mode: Optional[bool] = None + test_mode: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether test mode.""" - segments_to_transcribe: Optional[List[Dict[str, Any]]] = None - speakers_names: Optional[List[Dict[str, Any]]] = None - skip_diarization: Optional[bool] = None + segments_to_transcribe: Optional[ + List[Dict[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + speakers_names: Optional[ + List[Dict[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + skip_diarization: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to skip diarization.""" - skip_postprocessing: Optional[bool] = None + skip_postprocessing: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to skip postprocessing.""" - skip_punctuation: Optional[bool] = None + skip_punctuation: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to skip punctuations.""" - remove_disfluencies: Optional[bool] = None + remove_disfluencies: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to remove disfluencies.""" - remove_atmospherics: Optional[bool] = None + remove_atmospherics: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to remove atmospherics.""" - filter_profanity: Optional[bool] = None + filter_profanity: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether to filter profanity.""" - speaker_channels_count: Optional[int] = None + speaker_channels_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The speaker channels count.""" - speakers_count: Optional[int] = None + speakers_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The speakers count.""" - custom_vocabulary_id: Optional[str] = None + custom_vocabulary_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The custom vocabulary identifier.""" - custom_vocabularies: Optional[List[Dict[str, Any]]] = None - language: Optional[str] = None + custom_vocabularies: Optional[ + List[Dict[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The language.""" @@ -92,15 +136,15 @@ class TranscriptionPostResponse: Response for Submit transcription job """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status.""" - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The language.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """When created on.""" - transcriber: Optional[str] = None + transcriber: Optional[str] = dataclass_field(default=None, kw_only=True) """The transcriber.""" @@ -110,7 +154,7 @@ class TranscriptGetResponse: Response for Get transcript """ - monologues: Optional[List[Dict[str, Any]]] = None + monologues: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -119,19 +163,19 @@ class AccountGetResponse: Response for Get account """ - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """The email address.""" - free_balance: Optional[float] = None + free_balance: Optional[float] = dataclass_field(default=None, kw_only=True) """The free balance.""" - purchased_balance: Optional[float] = None + purchased_balance: Optional[float] = dataclass_field(default=None, kw_only=True) """The purchased balance.""" - total_balance: Optional[int] = None + total_balance: Optional[int] = dataclass_field(default=None, kw_only=True) """The total balance.""" - invoiced_balance: Optional[float] = None + invoiced_balance: Optional[float] = dataclass_field(default=None, kw_only=True) """The invoiced balance.""" - balance_seconds: Optional[int] = None + balance_seconds: Optional[int] = dataclass_field(default=None, kw_only=True) """The balance seconds.""" - hipaa_enabled: Optional[bool] = None + hipaa_enabled: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether HIPAA is enabled.""" @@ -141,10 +185,15 @@ class VocabularyInput: Submit custom vocabulary """ - metadata: Optional[str] = None + metadata: Optional[str] = dataclass_field(default=None, kw_only=True) """The metadata.""" - notification_config: Optional[Dict[str, Any]] = None - custom_vocabularies: Optional[List[Dict[str, Any]]] = None + notification_config: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + custom_vocabularies: Optional[ + List[Dict[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -153,13 +202,13 @@ class VocabularyPostResponse: Response for Submit custom vocabulary """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """When created on.""" - callback_url: Optional[str] = None + callback_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The callback URL address.""" @@ -169,13 +218,13 @@ class VocabularyGetResponse: Response for Get vocabulary """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """When created on.""" - callback_url: Optional[str] = None + callback_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The callback URL address.""" @@ -185,14 +234,14 @@ class ExtractionInput: Submit topic extraction job """ - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The language.""" - metadata: Optional[str] = None + metadata: Optional[str] = dataclass_field(default=None, kw_only=True) """The metadata.""" - notification_config: Optional[Dict[str, Any]] = None - delete_after_seconds: Optional[int] = None + notification_config: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + delete_after_seconds: Optional[int] = dataclass_field(default=None, kw_only=True) """The delete after seconds.""" - json: Optional[Dict[str, Any]] = None + json: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -201,15 +250,19 @@ class ExtractionPostResponse: Response for Submit topic extraction job """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status.""" - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The language.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """When created on.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type.""" @@ -219,15 +272,19 @@ class ExtractionGetResponse: Response for Get topic extraction job """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status.""" - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The language.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """When created on.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type.""" @@ -237,7 +294,7 @@ class ExtractionResultGetResponse: Response for Get topic extraction result """ - topics: Optional[List[Dict[str, Any]]] = None + topics: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -246,14 +303,14 @@ class AnalysisInput: Submit sentiment analysis job """ - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The language.""" - metadata: Optional[str] = None + metadata: Optional[str] = dataclass_field(default=None, kw_only=True) """The metadata.""" - notification_config: Optional[Dict[str, Any]] = None - delete_after_seconds: Optional[int] = None + notification_config: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + delete_after_seconds: Optional[int] = dataclass_field(default=None, kw_only=True) """The delete after seconds.""" - json: Optional[Dict[str, Any]] = None + json: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -262,17 +319,21 @@ class AnalysisPostResponse: Response for Submit sentiment analysis job """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status.""" - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The language.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """When created on.""" - callback_url: Optional[str] = None + callback_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The callback URL address.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type.""" @@ -282,17 +343,21 @@ class AnalysisGetResponse: Response for Get sentiment analysis job """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status.""" - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The language.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """When created on.""" - callback_url: Optional[str] = None + callback_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The callback URL address.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type.""" @@ -302,7 +367,7 @@ class AnalysisResultGetResponse: Response for Get sentiment analysis result """ - messages: Optional[List[Dict[str, Any]]] = None + messages: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -311,12 +376,12 @@ class IdentificationInput: Submit language identification job """ - metadata: Optional[str] = None + metadata: Optional[str] = dataclass_field(default=None, kw_only=True) """The metadata.""" - notification_config: Optional[Dict[str, Any]] = None - delete_after_seconds: Optional[int] = None + notification_config: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + delete_after_seconds: Optional[int] = dataclass_field(default=None, kw_only=True) """The delete after seconds.""" - source_config: Optional[Dict[str, Any]] = None + source_config: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -325,13 +390,17 @@ class IdentificationPostResponse: Response for Submit language identification job """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """When created on.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type.""" @@ -341,13 +410,17 @@ class IdentificationGetResponse: Response for Get language identification job """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """When created on.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type.""" @@ -357,9 +430,14 @@ class IdentificationResultGetResponse: Response for Get language identification result """ - top_language: Optional[str] = None + top_language: Optional[str] = dataclass_field(default=None, kw_only=True) """The top language.""" - language_confidences: Optional[List[Dict[str, Any]]] = None + language_confidences: Optional[ + List[Dict[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -368,15 +446,15 @@ class AlignmentInput: Submit forced alignment job """ - metadata: Optional[str] = None + metadata: Optional[str] = dataclass_field(default=None, kw_only=True) """The metadata.""" - notification_config: Optional[Dict[str, Any]] = None - delete_after_seconds: Optional[int] = None + notification_config: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + delete_after_seconds: Optional[int] = dataclass_field(default=None, kw_only=True) """The delete after seconds.""" - source_config: Optional[Dict[str, Any]] = None - transcript_text: Optional[str] = None + source_config: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + transcript_text: Optional[str] = dataclass_field(default=None, kw_only=True) """The transcript text.""" - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The language.""" @@ -386,13 +464,17 @@ class AlignmentPostResponse: Response for Submit forced alignment job """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """When created on.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type.""" @@ -402,13 +484,17 @@ class AlignmentGetResponse: Response for Get forced alignment job """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """When created on.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type.""" @@ -418,7 +504,7 @@ class AlignmentTranscriptGetResponse: Response for Get forced alignment transcript """ - monologues: Optional[List[Dict[str, Any]]] = None + monologues: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) # Client Class @@ -429,16 +515,16 @@ class RevaiClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -449,8 +535,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -458,8 +544,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -471,7 +557,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -486,7 +572,46 @@ def __init__( def connector_name(self) -> str: return "revai" - async def transcription_get_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def transcription_get( self, id: str, *, @@ -499,13 +624,28 @@ async def transcription_get_async( Get transcription job Returns information about a transcription job. + + Swagger operation ID: `TranscriptionGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/speechtotext/v1/jobs/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -519,6 +659,7 @@ async def transcription_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -526,7 +667,7 @@ async def transcription_get_async( return json.loads(response.text) - async def transcription_delete_async( + def transcription_delete( self, id: str, *, @@ -541,13 +682,28 @@ async def transcription_delete_async( Deletes a transcription job. All data related to the job, such as input media and transcript, will be permanently deleted. A job can only be deleted once it's completed (either with success or failure). + + Swagger operation ID: `TranscriptionDelete`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/speechtotext/v1/jobs/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -561,6 +717,7 @@ async def transcription_delete_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -568,21 +725,41 @@ async def transcription_delete_async( return json.loads(response.text) - async def transcriptions_get_async( + def list_transcriptions_get( self, + *, limit: Optional[int] = None, starting_after: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get transcription job list Retrieve a list of transcription jobs submitted within the last 30 days. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `TranscriptionsGet`. + + Args: + limit: The limit. + starting_after: The starting after. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/speechtotext/v1/jobs" query_params = [] @@ -598,31 +775,52 @@ async def transcriptions_get_async( query_params.append(f"starting_after={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def transcription_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def transcription( self, - input: TranscriptionInput, + input: TranscriptionInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -634,10 +832,26 @@ async def transcription_async( Starts an asynchronous job to transcribe speech-to-text for a media file. + + Swagger operation ID: `TranscriptionPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/speechtotext/v1/jobs" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -651,6 +865,7 @@ async def transcription_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -658,7 +873,7 @@ async def transcription_async( return json.loads(response.text) - async def transcript_get_async( + def list_transcript_get( self, id: str, *, @@ -666,39 +881,79 @@ async def transcript_get_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get transcript Returns the transcript for a completed transcription job. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `TranscriptGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/speechtotext/v1/jobs/{quote(str(id), safe='')}/transcript" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("monologues", []): + yield item - async def captions_get_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def captions_get( self, id: str, *, @@ -712,13 +967,28 @@ async def captions_get_async( Returns the caption output for a transcription job. We currently support the SubRip (SRT) format. + + Swagger operation ID: `CaptionsGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/speechtotext/v1/jobs/{quote(str(id), safe='')}/captions" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -732,6 +1002,7 @@ async def captions_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -739,7 +1010,7 @@ async def captions_get_async( return json.loads(response.text) - async def account_get_async( + def account_get( self, *, timeout: Optional[float] = None, @@ -751,10 +1022,24 @@ async def account_get_async( Get account Get the developer's account information. + + Swagger operation ID: `AccountGet`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/speechtotext/v1/account" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -768,6 +1053,7 @@ async def account_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -775,20 +1061,39 @@ async def account_get_async( return json.loads(response.text) - async def vocabularies_get_async( + def list_vocabularies_get( self, - limit: Optional[int] = None, *, + limit: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get list of vocabularies Retrieves a list of most recent custom vocabularies' processing information. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `VocabulariesGet`. + + Args: + limit: The limit. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/speechtotext/v1/vocabularies" @@ -801,31 +1106,52 @@ async def vocabularies_get_async( query_params.append(f"limit={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def vocabulary_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def vocabulary( self, - input: VocabularyInput, + input: VocabularyInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -836,12 +1162,28 @@ async def vocabulary_async( Submit custom vocabulary Submits a Custom Vocabulary for asynchronous processing. + + Swagger operation ID: `VocabularyPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/speechtotext/v1/vocabularies" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -855,6 +1197,7 @@ async def vocabulary_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -862,7 +1205,7 @@ async def vocabulary_async( return json.loads(response.text) - async def vocabulary_get_async( + def vocabulary_get( self, id: str, *, @@ -875,13 +1218,28 @@ async def vocabulary_get_async( Get vocabulary Retrieve a custom vocabulary processing information. + + Swagger operation ID: `VocabularyGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/speechtotext/v1/vocabularies/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -895,6 +1253,7 @@ async def vocabulary_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -902,7 +1261,7 @@ async def vocabulary_get_async( return json.loads(response.text) - async def vocabulary_delete_async( + def vocabulary_delete( self, id: str, *, @@ -916,13 +1275,28 @@ async def vocabulary_delete_async( Deletes a custom vocabulary. All data related to the custom vocabulary, such as webhooks and metadata, will be permanently deleted. + + Swagger operation ID: `VocabularyDelete`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/speechtotext/v1/vocabularies/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -936,6 +1310,7 @@ async def vocabulary_delete_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -943,21 +1318,41 @@ async def vocabulary_delete_async( return json.loads(response.text) - async def extractions_get_async( + def list_extractions_get( self, + *, limit: Optional[int] = None, starting_after: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get topic extraction jobs Retrieves a list of topic extraction jobs submitted within the last 30 days in reverse chronological order. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ExtractionsGet`. + + Args: + limit: The limit. + starting_after: The starting after. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/topic_extraction/v1/jobs" @@ -975,31 +1370,52 @@ async def extractions_get_async( query_params.append(f"starting_after={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def extraction_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def extraction( self, - input: ExtractionInput, + input: ExtractionInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1010,12 +1426,28 @@ async def extraction_async( Submit topic extraction job Starts an asynchronous job to extract topics from a transcript. + + Swagger operation ID: `ExtractionPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/topic_extraction/v1/jobs" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1029,6 +1461,7 @@ async def extraction_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1036,7 +1469,7 @@ async def extraction_async( return json.loads(response.text) - async def extraction_get_async( + def extraction_get( self, id: str, *, @@ -1049,13 +1482,28 @@ async def extraction_get_async( Get topic extraction job Returns information about a topic extraction job. + + Swagger operation ID: `ExtractionGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/topic_extraction/v1/jobs/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1069,6 +1517,7 @@ async def extraction_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1076,7 +1525,7 @@ async def extraction_get_async( return json.loads(response.text) - async def extraction_delete_async( + def extraction_delete( self, id: str, *, @@ -1090,13 +1539,28 @@ async def extraction_delete_async( Deletes a topic extraction job. All data related to the job will be permanently deleted. + + Swagger operation ID: `ExtractionDelete`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/topic_extraction/v1/jobs/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1110,6 +1574,7 @@ async def extraction_delete_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1117,20 +1582,40 @@ async def extraction_delete_async( return json.loads(response.text) - async def extraction_result_get_async( + def list_extraction_result_get( self, id: str, - threshold: Optional[float] = None, *, + threshold: Optional[float] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get topic extraction result Returns the results for a completed topic extraction job. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ExtractionResultGet`. + + Args: + id: The identifier. + threshold: The threshold. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1144,33 +1629,54 @@ async def extraction_result_get_async( query_params.append(f"threshold={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("topics", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def analysises_get_async( + def analysises_get( self, + *, limit: Optional[int] = None, starting_after: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1181,6 +1687,22 @@ async def analysises_get_async( Gets a list of sentiment analysis jobs submitted within the last 30 days in reverse chronological order. + + Swagger operation ID: `AnalysisesGet`. + + Args: + limit: The limit. + starting_after: The starting after. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/sentiment_analysis/v1/jobs" @@ -1199,7 +1721,7 @@ async def analysises_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1213,11 +1735,12 @@ async def analysises_get_async( request_url, response.status, response.text, + response=response, ) - async def analysis_async( + def analysis( self, - input: AnalysisInput, + input: AnalysisInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1228,12 +1751,28 @@ async def analysis_async( Submit sentiment analysis job Starts an asynchronous job to analyze sentiments in a transcript. + + Swagger operation ID: `AnalysisPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/sentiment_analysis/v1/jobs" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1247,6 +1786,7 @@ async def analysis_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1254,7 +1794,7 @@ async def analysis_async( return json.loads(response.text) - async def analysis_get_async( + def analysis_get( self, id: str, *, @@ -1267,13 +1807,28 @@ async def analysis_get_async( Get sentiment analysis job Returns information about a sentiment analysis job. + + Swagger operation ID: `AnalysisGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/sentiment_analysis/v1/jobs/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1287,6 +1842,7 @@ async def analysis_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1294,7 +1850,7 @@ async def analysis_get_async( return json.loads(response.text) - async def analysis_delete_async( + def analysis_delete( self, id: str, *, @@ -1308,13 +1864,28 @@ async def analysis_delete_async( Deletes a sentiment analysis job. All data related to the job will be permanently deleted. + + Swagger operation ID: `AnalysisDelete`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/sentiment_analysis/v1/jobs/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1328,6 +1899,7 @@ async def analysis_delete_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1335,20 +1907,40 @@ async def analysis_delete_async( return json.loads(response.text) - async def analysis_result_get_async( + def list_analysis_result_get( self, id: str, - filter_for: Optional[str] = None, *, + filter_for: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get sentiment analysis result Returns the results for a completed sentiment analysis job. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `AnalysisResultGet`. + + Args: + id: The identifier. + filter_for: The filter for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1362,43 +1954,84 @@ async def analysis_result_get_async( query_params.append(f"filter_for={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("messages", []): + yield item + + return None, items() - async def identifications_get_async( + return ItemPaged(get_next, extract_data) + + def list_identifications_get( self, + *, limit: Optional[int] = None, starting_after: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get language identification jobs Retrieves a list of language identification jobs submitted within the last 30 days in reverse chronological order. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `IdentificationsGet`. + + Args: + limit: The limit. + starting_after: The starting after. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/languageid/v1/jobs" query_params = [] @@ -1414,31 +2047,52 @@ async def identifications_get_async( query_params.append(f"starting_after={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def identification_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def identification( self, - input: IdentificationInput, + input: IdentificationInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1450,10 +2104,26 @@ async def identification_async( Starts an asynchronous job to identify the most probable language in the audio. + + Swagger operation ID: `IdentificationPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/languageid/v1/jobs" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1467,6 +2137,7 @@ async def identification_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1474,7 +2145,7 @@ async def identification_async( return json.loads(response.text) - async def identification_get_async( + def identification_get( self, id: str, *, @@ -1487,13 +2158,28 @@ async def identification_get_async( Get language identification job Returns information about a language identification job. + + Swagger operation ID: `IdentificationGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/languageid/v1/jobs/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1507,6 +2193,7 @@ async def identification_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1514,7 +2201,7 @@ async def identification_get_async( return json.loads(response.text) - async def identification_delete_async( + def identification_delete( self, id: str, *, @@ -1528,13 +2215,28 @@ async def identification_delete_async( Deletes a language identification job. All data related to the job will be permanently deleted. + + Swagger operation ID: `IdentificationDelete`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/languageid/v1/jobs/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1548,6 +2250,7 @@ async def identification_delete_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1555,7 +2258,7 @@ async def identification_delete_async( return json.loads(response.text) - async def identification_result_get_async( + def identification_result_get( self, id: str, *, @@ -1568,13 +2271,28 @@ async def identification_result_get_async( Get language identification result Returns the results for a completed language identification job. + + Swagger operation ID: `IdentificationResultGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/languageid/v1/jobs/{quote(str(id), safe='')}/result" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1588,6 +2306,7 @@ async def identification_result_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1595,21 +2314,41 @@ async def identification_result_get_async( return json.loads(response.text) - async def alignments_get_async( + def list_alignments_get( self, + *, limit: Optional[int] = None, starting_after: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get forced alignment jobs Retrieve a list of alignment jobs submitted within the last 30 days in reverse chronological order. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `AlignmentsGet`. + + Args: + limit: The limit. + starting_after: The starting after. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/alignment/v1/jobs" query_params = [] @@ -1625,31 +2364,52 @@ async def alignments_get_async( query_params.append(f"starting_after={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def alignment_async( + return ItemPaged(get_next, extract_data) + + def alignment( self, - input: AlignmentInput, + input: AlignmentInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1661,10 +2421,26 @@ async def alignment_async( Starts an asynchronous job to obtain precise word timings for an audio file and text transcript. + + Swagger operation ID: `AlignmentPost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/alignment/v1/jobs" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1678,6 +2454,7 @@ async def alignment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1685,7 +2462,7 @@ async def alignment_async( return json.loads(response.text) - async def alignment_get_async( + def alignment_get( self, id: str, *, @@ -1698,13 +2475,28 @@ async def alignment_get_async( Get forced alignment job Returns information about a forced alignment job. + + Swagger operation ID: `AlignmentGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/alignment/v1/jobs/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1718,6 +2510,7 @@ async def alignment_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1725,7 +2518,7 @@ async def alignment_get_async( return json.loads(response.text) - async def alignment_delete_async( + def alignment_delete( self, id: str, *, @@ -1739,13 +2532,28 @@ async def alignment_delete_async( Deletes a forced alignment job. All data related to the job will be permanently deleted. + + Swagger operation ID: `AlignmentDelete`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/alignment/v1/jobs/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1759,6 +2567,7 @@ async def alignment_delete_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1766,7 +2575,7 @@ async def alignment_delete_async( return json.loads(response.text) - async def alignment_transcript_get_async( + def list_alignment_transcript_get( self, id: str, *, @@ -1774,34 +2583,74 @@ async def alignment_transcript_get_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get forced alignment transcript Returns the results for a completed forced alignment job. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `AlignmentTranscriptGet`. + + Args: + id: The identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/alignment/v1/jobs/{quote(str(id), safe='')}/transcript" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("monologues", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/rss.py b/src/azure/connectors/rss.py index 06bcf43..201ee7b 100644 --- a/src/azure/connectors/rss.py +++ b/src/azure/connectors/rss.py @@ -5,21 +5,29 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "RssClient", + "FeedItem", + "TriggerBatchResponseFeedItem", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +37,12 @@ class TriggerBatchResponseFeedItem: Response for When a feed item is published """ - value: Optional[List[FeedItem]] = None + value: Optional[ + List[FeedItem | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A list of the response objects""" @@ -39,32 +52,35 @@ class FeedItem: Response for List all RSS feed items """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Feed ID""" - title: Optional[str] = None + title: str """Feed title""" - primary_link: Optional[str] = field( + primary_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "primaryLink"}, ) """Primary feed link""" - links: Optional[List[str]] = None + links: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Feed links""" - updated_on: Optional[str] = field( + updated_on: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "updatedOn"}, ) """Feed updated on""" - publish_date: Optional[str] = field( + publish_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "publishDate"}, ) """Feed published date""" - summary: Optional[str] = None + summary: Optional[str] = dataclass_field(default=None, kw_only=True) """Feed item summary""" - copyright: Optional[str] = None + copyright: Optional[str] = dataclass_field(default=None, kw_only=True) """Copyright information""" - categories: Optional[List[str]] = None + categories: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Feed item categories""" @@ -76,16 +92,16 @@ class RssClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -96,8 +112,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -105,8 +121,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -118,7 +134,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -133,21 +149,83 @@ def __init__( def connector_name(self) -> str: return "rss" - async def list_feed_items_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_feed_items( self, feed_url: str, + *, since: Optional[str] = None, since_property: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List all RSS feed items This operation retrieves all items from an RSS feed. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListFeedItems`. + + Args: + feed_url: The RSS feed URL (Example: + http://rss.cnn.com/rss/cnn_topstories.rss). + since: The date since when RSS feed should be retrieved (Example: + 2018-12-29 10:24:05Z). + since_property: Chosen property will be used for trigger state. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/ListFeedItems" query_params = [] @@ -167,27 +245,48 @@ async def list_feed_items_async( query_params.append(f"sinceProperty={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - return json.loads(response.text) + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/salesforce.py b/src/azure/connectors/salesforce.py index 2449130..de4da06 100644 --- a/src/azure/connectors/salesforce.py +++ b/src/azure/connectors/salesforce.py @@ -5,21 +5,69 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "SalesforceClient", + "BlobDataSetsMetadata", + "CheckJobResponse", + "CloseJobRequest", + "CreateJobParameters", + "CreateJobRequest", + "CreateJobResponse", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "ExecuteSoqlQueryParameters", + "ExternalIdField", + "ExternalIdFieldsList", + "GetAllJobsResponse", + "GetCurrentUserInfoResponse", + "GetItemByExternalIdResponse", + "GetItemResponse", + "InstanceUrlResponse", + "Item", + "ItemsList", + "JobInfo", + "MCPQueryRequest", + "MCPQueryResponse", + "ObjectEntity", + "ObjectWithoutType", + "PassThroughNativeQuery", + "PatchItemByExternalIdInput", + "PatchItemByExternalIdResponse", + "PatchItemInput", + "PatchItemResponse", + "PostItemInput", + "PostItemResponse", + "Procedure", + "SOSLSearchQueryResponse", + "SearchRecordObject", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TablesList", + "TabularDataSetsMetadata", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,10 +77,16 @@ class TablesList: Response for Get object types """ - value: Optional[List[Table]] = None + value: Optional[ + List[Table | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Tables""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -44,7 +98,7 @@ class GetItemByExternalIdResponse: Response for Get a Record by External ID """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -57,10 +111,16 @@ class ItemsList: Response for Get records """ - value: Optional[List[Item]] = None + value: Optional[ + List[Item | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Items""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -72,7 +132,7 @@ class ObjectEntity: Response for Execute a SOQL query """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -85,11 +145,17 @@ class GetAllJobsResponse: Response for Get all jobs """ - done: Optional[bool] = None + done: Optional[bool] = dataclass_field(default=None, kw_only=True) """Done""" - records: Optional[List[JobInfo]] = None - next_record_url: Optional[str] = field( + records: Optional[ + List[JobInfo | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, + ) + next_record_url: Optional[str] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "nextRecordUrl"}, ) """Next Record URL""" @@ -101,82 +167,96 @@ class CheckJobResponse: Response for Get job info """ - apex_processing_time: Optional[float] = field( + apex_processing_time: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "apexProcessingTime"}, ) """APEX Processing Time""" - api_active_processing_time: Optional[float] = field( + api_active_processing_time: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "apiActiveProcessingTime"}, ) """API Active Processing Time""" - api_version: Optional[float] = field( + api_version: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "apiVersion"}, ) """API Version""" - column_delimiter: Optional[str] = field( + column_delimiter: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "columnDelimiter"}, ) """Column Delimiter""" - concurrency_mode: Optional[str] = field( + concurrency_mode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "concurrencyMode"}, ) """Concurrency Mode""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentType"}, ) """Content Type""" - content_url: Optional[str] = field( + content_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentUrl"}, ) """Content URL""" - created_by_id: Optional[str] = field( + created_by_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdById"}, ) """Created By ID""" - created_date: Optional[str] = field( + created_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDate"}, ) """Created Date""" - external_field_name: Optional[str] = field( + external_field_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "externalFieldName"}, ) """External Field Name""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID""" - job_type: Optional[str] = field( + job_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobType"}, ) """Job Type""" - line_ending: Optional[str] = field( + line_ending: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lineEnding"}, ) """Line Ending""" - object: Optional[str] = None + object: Optional[str] = dataclass_field(default=None, kw_only=True) """Object""" - operation: Optional[str] = None + operation: Optional[str] = dataclass_field(default=None, kw_only=True) """Operation""" - retries: Optional[float] = None + retries: Optional[float] = dataclass_field(default=None, kw_only=True) """Retries""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """State""" - system_mod_stamp: Optional[str] = field( + system_mod_stamp: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "systemModStamp"}, ) - total_processing_time: Optional[float] = field( + total_processing_time: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "totalProcessingTime"}, ) """Total Processing Time""" @@ -188,66 +268,77 @@ class JobInfo: Response for Close or abort a job """ - api_version: Optional[float] = field( + api_version: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "apiVersion"}, ) """API Version""" - column_delimiter: Optional[str] = field( + column_delimiter: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "columnDelimiter"}, ) """Column Delimiter""" - concurrency_mode: Optional[str] = field( + concurrency_mode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "concurrencyMode"}, ) """Concurrency Mode""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentType"}, ) """Content Type""" - content_url: Optional[str] = field( + content_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentUrl"}, ) """Content URL""" - created_by_id: Optional[str] = field( + created_by_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdById"}, ) """Created By ID""" - created_date: Optional[str] = field( + created_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDate"}, ) """Created Date""" - external_id_field_name: Optional[str] = field( + external_id_field_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "externalIdFieldName"}, ) """External ID Field Name""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID""" - job_type: Optional[str] = field( + job_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobType"}, ) """Job Type""" - line_ending: Optional[str] = field( + line_ending: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lineEnding"}, ) """Line Ending""" - object: Optional[str] = None + object: Optional[str] = dataclass_field(default=None, kw_only=True) """Object""" - operation: Optional[str] = None + operation: Optional[str] = dataclass_field(default=None, kw_only=True) """Operation""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """State""" - system_modstamp: Optional[str] = field( + system_modstamp: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "systemModstamp"}, ) """System Mod Stamp""" @@ -259,12 +350,13 @@ class SOSLSearchQueryResponse: Response for Execute SOSL search query """ - search_records: Optional[List[SearchRecordObject]] = field( + search_records: Optional[List[SearchRecordObject | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "searchRecords"}, ) """A list of search records returned by an SOSL search query""" - metadata: Optional[Dict[str, Any]] = None + metadata: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Metadata of the result returned from the query""" @@ -274,7 +366,7 @@ class ObjectWithoutType: Response for Send an HTTP request """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -287,12 +379,12 @@ class MCPQueryResponse: Response for MCP server for Salesforce """ - jsonrpc: Optional[str] = None - id: Optional[str] = None - method: Optional[str] = None - params: Optional[Dict[str, Any]] = None - result: Optional[Dict[str, Any]] = None - error: Optional[Dict[str, Any]] = None + jsonrpc: Optional[str] = dataclass_field(default=None, kw_only=True) + id: Optional[str] = dataclass_field(default=None, kw_only=True) + method: Optional[str] = dataclass_field(default=None, kw_only=True) + params: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + result: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + error: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -301,72 +393,83 @@ class CreateJobResponse: Response for Create a job """ - object: Optional[str] = None + object: Optional[str] = dataclass_field(default=None, kw_only=True) """The object type for the data being processed.""" - operation: Optional[str] = None + operation: Optional[str] = dataclass_field(default=None, kw_only=True) """The processing operation for the job.""" - column_delimiter: Optional[str] = field( + column_delimiter: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "columnDelimiter"}, ) """The column delimiter used for CSV job data.""" - external_id_field_name: Optional[str] = field( + external_id_field_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "externalIdFieldName"}, ) """ The external ID field in the object being updated. Only needed for upsert operations. Field values must also exist in CSV job data. """ - line_ending: Optional[str] = field( + line_ending: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lineEnding"}, ) """The line ending used for CSV job data, marking the end of a data row.""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentType"}, ) """The content type for the job.""" - api_version: Optional[float] = field( + api_version: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "apiVersion"}, ) """The API version that the job was created in.""" - concurrency_mode: Optional[str] = field( + concurrency_mode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "concurrencyMode"}, ) """The concurrency mode for the job.""" - content_url: Optional[str] = field( + content_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentUrl"}, ) """ The URL to use for Upload Job Data requests for this job. Only valid if the job is in 'Open' state. """ - created_by_id: Optional[str] = field( + created_by_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdById"}, ) """The ID of the user who created the job.""" - created_date: Optional[str] = field( + created_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDate"}, ) """The date and time in the UTC time zone when the job was created.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID for this job.""" - job_type: Optional[str] = field( + job_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "jobType"}, ) """The job's type.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """The current state of processing for the job.""" - system_modstamp: Optional[str] = field( + system_modstamp: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "systemModstamp"}, ) """Date and time in the UTC time zone when the job finished.""" @@ -378,7 +481,7 @@ class GetItemResponse: Response for Get record """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -391,7 +494,7 @@ class PatchItemInput: Update record """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -404,7 +507,7 @@ class PatchItemResponse: Response for Update record """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -417,7 +520,7 @@ class PatchItemByExternalIdInput: Insert or Update (Upsert) a Record by External ID """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -430,7 +533,7 @@ class PatchItemByExternalIdResponse: Response for Insert or Update (Upsert) a Record by External ID """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -443,7 +546,7 @@ class PostItemInput: Create record """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -456,7 +559,7 @@ class PostItemResponse: Response for Create record """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -469,7 +572,12 @@ class ExternalIdFieldsList: Response for Get External ID Fields """ - value: Optional[List[ExternalIdField]] = None + value: Optional[ + List[ExternalIdField | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of external ID fields.""" @@ -479,26 +587,30 @@ class TableMetadata: Response for GetMetadataForGetItem """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Table name""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Table title""" - x_ms_permission: Optional[str] = field( + x_ms_permission: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-permission"}, ) """Table permission""" - x_ms_capabilities: Optional[TableCapabilitiesMetadata] = field( + x_ms_capabilities: Optional[TableCapabilitiesMetadata | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-capabilities"}, ) - schema: Optional[ObjectEntity] = None - referenced_entities: Optional[ObjectEntity] = field( + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + referenced_entities: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "referencedEntities"}, ) - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webUrl"}, ) """URL link""" @@ -510,15 +622,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -530,30 +644,34 @@ class CreateJobParameters: Definition: CreateJobParameters """ - object: Optional[str] = None + object: str """The object type for the data being processed.""" - operation: Optional[str] = None + operation: str """The processing operation for the job.""" - column_delimiter: Optional[str] = field( + column_delimiter: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "columnDelimiter"}, ) """The column delimiter used for CSV job data.""" - external_id_field_name: Optional[str] = field( + external_id_field_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "externalIdFieldName"}, ) """ The external ID field in the object being updated. Only needed for upsert operations. Field values must also exist in CSV job data. """ - line_ending: Optional[str] = field( + line_ending: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lineEnding"}, ) """The line ending used for CSV job data, marking the end of a data row.""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentType"}, ) """The content type for the job.""" @@ -565,14 +683,24 @@ class DataSet: Definition: DataSet """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Dataset name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Dataset display name""" - query: Optional[List[PassThroughNativeQuery]] = None + query: Optional[ + List[PassThroughNativeQuery | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Pass-through Native Queries""" @@ -582,7 +710,12 @@ class DataSetsList: Definition: DataSetsList """ - value: Optional[List[DataSet]] = None + value: Optional[ + List[DataSet | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of datasets""" @@ -592,8 +725,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -602,12 +745,12 @@ class ExecuteSoqlQueryParameters: Definition: ExecuteSoqlQueryParameters """ - query: Optional[str] = None + query: str """ SOQL Query text. Dynamic parameters can be specified using '@paramName' syntax. """ - parameters: Optional[Dict[str, str]] = None + parameters: Optional[Dict[str, str]] = dataclass_field(default=None, kw_only=True) """ SOQL Query dynamic parameters. Key is parameter name (without '@' at sign), value is parameter value. @@ -620,10 +763,15 @@ class ExternalIdField: Definition: ExternalIdField """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Name of the external ID field, used at runtime.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Display name of the external ID field.""" @@ -635,8 +783,9 @@ class Item: Definition: Item """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) @@ -647,8 +796,9 @@ class PassThroughNativeQuery: Definition: PassThroughNativeQuery """ - language: Optional[str] = field( + language: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Language"}, ) """Query language""" @@ -660,10 +810,15 @@ class Procedure: Definition: Procedure """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Procedure name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Procedure display name""" @@ -675,15 +830,21 @@ class Table: Definition: Table """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the table. The name is used at runtime.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the table.""" - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DynamicProperties"}, ) """Additional table properties provided by the connector to the clients.""" @@ -695,30 +856,42 @@ class TableCapabilitiesMetadata: Definition: TableCapabilitiesMetadata """ - sort_restrictions: Optional[TableSortRestrictionsMetadata] = field( + sort_restrictions: Optional[ + TableSortRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sortRestrictions"}, ) - filter_restrictions: Optional[TableFilterRestrictionsMetadata] = field( + filter_restrictions: Optional[ + TableFilterRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterRestrictions"}, ) - select_restrictions: Optional[TableSelectRestrictionsMetadata] = field( + select_restrictions: Optional[ + TableSelectRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selectRestrictions"}, ) - is_only_server_pagable: Optional[bool] = field( + is_only_server_pagable: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isOnlyServerPagable"}, ) """Server paging restrictions""" - filter_function_support: Optional[List[str]] = field( + filter_function_support: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterFunctionSupport"}, ) """List of supported filter capabilities""" - server_paging_options: Optional[List[str]] = field( + server_paging_options: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "serverPagingOptions"}, ) """List of supported server-driven paging capabilities""" @@ -730,15 +903,17 @@ class TableFilterRestrictionsMetadata: Definition: TableFilterRestrictionsMetadata """ - filterable: Optional[bool] = None + filterable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has filterable columns""" - non_filterable_properties: Optional[List[str]] = field( + non_filterable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nonFilterableProperties"}, ) """List of non filterable properties""" - required_properties: Optional[List[str]] = field( + required_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredProperties"}, ) """List of required properties""" @@ -750,7 +925,7 @@ class TableSelectRestrictionsMetadata: Definition: TableSelectRestrictionsMetadata """ - selectable: Optional[bool] = None + selectable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has selectable columns""" @@ -760,15 +935,17 @@ class TableSortRestrictionsMetadata: Definition: TableSortRestrictionsMetadata """ - sortable: Optional[bool] = None + sortable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has sortable columns""" - unsortable_properties: Optional[List[str]] = field( + unsortable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "unsortableProperties"}, ) """List of unsortable properties""" - ascending_only_properties: Optional[List[str]] = field( + ascending_only_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ascendingOnlyProperties"}, ) """List of properties which support ascending order only""" @@ -780,25 +957,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -810,24 +991,27 @@ class CreateJobRequest: Definition: CreateJobRequest """ - column_delimiter: Optional[str] = field( + column_delimiter: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "columnDelimiter"}, ) """Column Delimiter""" - external_id_field_name: Optional[str] = field( + external_id_field_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "externalIdFieldName"}, ) """External ID Field Name""" - line_ending: Optional[str] = field( + line_ending: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lineEnding"}, ) """Line Ending""" - object: Optional[str] = None + object: str """Object""" - operation: Optional[str] = None + operation: str """Operation""" @@ -837,8 +1021,9 @@ class InstanceUrlResponse: Definition: InstanceUrlResponse """ - instance_url: Optional[str] = field( + instance_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "instanceUrl"}, ) """Instance Url""" @@ -850,7 +1035,7 @@ class GetCurrentUserInfoResponse: Definition: GetCurrentUserInfoResponse """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -863,9 +1048,13 @@ class SearchRecordObject: Definition: SearchRecordObject """ - attributes: Optional[Dict[str, Any]] = None + attributes: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Attributes of a search record""" - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Unique identifier of the record""" @@ -875,7 +1064,7 @@ class CloseJobRequest: Definition: CloseJobRequest """ - state: Optional[str] = None + state: str """state""" @@ -885,14 +1074,15 @@ class MCPQueryRequest: Definition: MCPQueryRequest """ - jsonrpc: Optional[str] = None - id: Optional[str] = None - method: Optional[str] = None - params: Optional[Dict[str, Any]] = None - result: Optional[Dict[str, Any]] = None - error: Optional[Dict[str, Any]] = None - callback_endpoint: Optional[str] = field( + jsonrpc: Optional[str] = dataclass_field(default=None, kw_only=True) + id: Optional[str] = dataclass_field(default=None, kw_only=True) + method: Optional[str] = dataclass_field(default=None, kw_only=True) + params: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + result: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + error: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + callback_endpoint: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "callbackEndpoint"}, ) @@ -905,16 +1095,16 @@ class SalesforceClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -925,8 +1115,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -934,8 +1124,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -947,7 +1137,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -969,7 +1159,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -1001,28 +1191,50 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def get_tables_async( + def list_tables( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get object types This operation lists the available Salesforce object types. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTables`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/datasets/default/tables" + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1035,23 +1247,32 @@ async def get_tables_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def get_item_by_external_id_async( + def get_item_by_external_id( self, table: str, external_id_field: str, @@ -1066,6 +1287,24 @@ async def get_item_by_external_id_async( Get a Record by External ID This operation retrieves a record using an external ID. + + Swagger operation ID: `GetItemByExternalId`. + + Args: + table: The Salesforce object type like 'Leads'. + external_id_field: Field marked as external ID field on Salesforce + object. + external_id: External ID of the record to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1078,7 +1317,7 @@ async def get_item_by_external_id_async( f"/{quote(quote(str(external_id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1092,6 +1331,7 @@ async def get_item_by_external_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1099,28 +1339,51 @@ async def get_item_by_external_id_async( return json.loads(response.text) - async def get_items_async( + def list_items( self, table: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, select: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get records This operation gets records of a certain Salesforce object type like 'Leads'. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItems`. + + Args: + table: The Salesforce object type like 'Leads'. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1158,11 +1421,18 @@ async def get_items_async( query_params.append(f"$select={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1175,42 +1445,73 @@ async def get_items_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def get_items_table_account_async( + def list_items_table_account( self, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, select: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get Account records from Salesforce This operation gets Account records from Salesforce. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItems_table_account`. + + Args: + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1244,11 +1545,18 @@ async def get_items_table_account_async( query_params.append(f"$select={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1261,42 +1569,73 @@ async def get_items_table_account_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_items_table_user_async( + return ItemPaged(get_next, extract_data) + + def list_items_table_user( self, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, select: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get User records from Salesforce This operation gets User records from Salesforce. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItems_table_user`. + + Args: + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1330,11 +1669,18 @@ async def get_items_table_user_async( query_params.append(f"$select={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1347,42 +1693,73 @@ async def get_items_table_user_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_items_table_case_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def list_items_table_case( self, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, select: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get Case records from Salesforce This operation gets Case records from Salesforce. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItems_table_case`. + + Args: + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1416,11 +1793,18 @@ async def get_items_table_case_async( query_params.append(f"$select={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1433,42 +1817,73 @@ async def get_items_table_case_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_items_table_opportunity_async( + return ItemPaged(get_next, extract_data) + + def list_items_table_opportunity( self, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, select: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get Opportunity records from Salesforce This operation gets Opportunity records from Salesforce. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItems_table_opportunity`. + + Args: + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1502,11 +1917,18 @@ async def get_items_table_opportunity_async( query_params.append(f"$select={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1519,42 +1941,73 @@ async def get_items_table_opportunity_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def get_items_table_product2_async( + def list_items_table_product2( self, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, select: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get Product records from Salesforce This operation gets Product records from Salesforce. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItems_table_product2`. + + Args: + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1588,11 +2041,18 @@ async def get_items_table_product2_async( query_params.append(f"$select={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1605,42 +2065,73 @@ async def get_items_table_product2_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_items_table_contact_async( + return ItemPaged(get_next, extract_data) + + def list_items_table_contact( self, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, select: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get Contact records from Salesforce This operation gets Contact records from Salesforce. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItems_table_contact`. + + Args: + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + skip: The number of entries to skip (default = 0). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1674,11 +2165,18 @@ async def get_items_table_contact_async( query_params.append(f"$select={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1691,23 +2189,32 @@ async def get_items_table_contact_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def delete_item_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def delete_item( self, table: str, id: str, @@ -1721,6 +2228,22 @@ async def delete_item_async( Delete record This operation deletes a record. + + Swagger operation ID: `DeleteItem`. + + Args: + table: The Salesforce object type like 'Leads'. + id: The unique identifier of record to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1732,7 +2255,7 @@ async def delete_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1746,11 +2269,12 @@ async def delete_item_async( request_url, response.status, response.text, + response=response, ) - async def execute_soql_query_async( + def execute_soql_query( self, - input: ExecuteSoqlQueryParameters, + input: ExecuteSoqlQueryParameters | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1761,10 +2285,26 @@ async def execute_soql_query_async( Execute a SOQL query Execute a SOQL query. + + Swagger operation ID: `ExecuteSoqlQuery`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/soql/executesoqlquery" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1778,6 +2318,7 @@ async def execute_soql_query_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1785,22 +2326,44 @@ async def execute_soql_query_async( return json.loads(response.text) - async def get_all_jobs_async( + def list_all_jobs( self, + *, concurreny_mode: Optional[str] = None, is_pk_chunking_enabled: Optional[bool] = None, job_type: Optional[str] = None, query_locator: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get all jobs Get a list of all jobs + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAllJobs`. + + Args: + concurreny_mode: Concurrency Mode. + is_pk_chunking_enabled: Is PK Chunking Enabled. + job_type: Job Type. + query_locator: Query Locator. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/codeless/jobs/ingest" query_params = [] @@ -1826,29 +2389,50 @@ async def get_all_jobs_async( query_params.append(f"queryLocator={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("records", []): + yield item - async def upload_job_data_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def upload_job_data( self, input: bytes, job_id: str, @@ -1862,13 +2446,29 @@ async def upload_job_data_async( Upload job data Uploads data for a job using CSV data. + + Swagger operation ID: `UploadJobData`. + + Args: + input: The binary request body. + job_id: Job ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/codeless/jobs/ingest/{quote(str(job_id), safe='')}/batches" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, @@ -1885,9 +2485,10 @@ async def upload_job_data_async( request_url, response.status, response.text, + response=response, ) - async def get_job_info_async( + def get_job_info( self, job_id: str, *, @@ -1900,13 +2501,28 @@ async def get_job_info_async( Get job info Retrieves detailed information about a job. + + Swagger operation ID: `GetJobInfo`. + + Args: + job_id: Job ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/codeless/jobs/ingest/{quote(str(job_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1920,6 +2536,7 @@ async def get_job_info_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1927,9 +2544,9 @@ async def get_job_info_async( return json.loads(response.text) - async def close_job_async( + def close_job( self, - input: CloseJobRequest, + input: CloseJobRequest | Mapping[str, Any], job_id: str, *, timeout: Optional[float] = None, @@ -1944,13 +2561,30 @@ async def close_job_async( to abort a job. If you close a job, Salesforce queues the job and uploaded data for processing, and you can't add any additional job data. If you abort a job, the job does not get queued or processed. + + Swagger operation ID: `CloseJob`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + job_id: Job ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/codeless/jobs/ingest/{quote(str(job_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -1964,6 +2598,7 @@ async def close_job_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1971,7 +2606,7 @@ async def close_job_async( return json.loads(response.text) - async def delete_job_async( + def delete_job( self, job_id: str, *, @@ -1985,13 +2620,28 @@ async def delete_job_async( Deletes a job. To be deleted, a job must have a state of UploadComplete, JobComplete, Aborted, or Failed. + + Swagger operation ID: `DeleteJob`. + + Args: + job_id: Job ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/codeless/jobs/ingest/{quote(str(job_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2005,9 +2655,10 @@ async def delete_job_async( request_url, response.status, response.text, + response=response, ) - async def get_job_record_results_async( + def get_job_record_results( self, job_id: str, result_type: str, @@ -2022,6 +2673,22 @@ async def get_job_record_results_async( Retrieves a list of records based on the result type for a completed job. + + Swagger operation ID: `GetJobRecordResults`. + + Args: + job_id: Job ID. + result_type: Result Type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2035,7 +2702,7 @@ async def get_job_record_results_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2049,6 +2716,7 @@ async def get_job_record_results_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2056,7 +2724,7 @@ async def get_job_record_results_async( return json.loads(response.text) - async def execute_sosl_query_async( + def execute_sosl_query( self, q: str, *, @@ -2069,6 +2737,21 @@ async def execute_sosl_query_async( Execute SOSL search query Execute the specified SOSL search qyery + + Swagger operation ID: `ExecuteSOSLQuery`. + + Args: + q: SOSL search string. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/codeless/search" query_params = [] @@ -2079,7 +2762,7 @@ async def execute_sosl_query_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2093,6 +2776,7 @@ async def execute_sosl_query_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2100,7 +2784,7 @@ async def execute_sosl_query_async( return json.loads(response.text) - async def http_request_async( + def http_request( self, input: bytes, *, @@ -2113,10 +2797,25 @@ async def http_request_async( Send an HTTP request Construct a Salesforce REST API request to invoke + + Swagger operation ID: `HttpRequest`. + + Args: + input: The binary request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/codeless/httprequest" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -2133,6 +2832,7 @@ async def http_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2140,11 +2840,11 @@ async def http_request_async( return json.loads(response.text) - async def mcp_salesforce_management_async( + def mcp_salesforce_management( self, - input: MCPQueryRequest, - session_id: Optional[str] = None, + input: MCPQueryRequest | Mapping[str, Any], *, + session_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2154,6 +2854,23 @@ async def mcp_salesforce_management_async( MCP server for Salesforce MCP server for Salesforce + + Swagger operation ID: `mcp_SalesforceManagement`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + session_id: sessionId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/mcp/SalesforceManagement" @@ -2167,7 +2884,7 @@ async def mcp_salesforce_management_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2181,6 +2898,7 @@ async def mcp_salesforce_management_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2188,9 +2906,9 @@ async def mcp_salesforce_management_async( return json.loads(response.text) - async def create_job_async( + def create_job( self, - input: CreateJobParameters, + input: CreateJobParameters | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -2203,10 +2921,26 @@ async def create_job_async( Creates a job, which represents a bulk operation (and associated data) that is sent to Salesforce for asynchronous processing. Provide job data via an Upload Job Data request. + + Swagger operation ID: `CreateJobV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/bulk/createjob" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2220,6 +2954,7 @@ async def create_job_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2227,12 +2962,12 @@ async def create_job_async( return json.loads(response.text) - async def get_item_async( + def get_item( self, table: str, id: str, - select: Optional[str] = None, *, + select: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2242,6 +2977,23 @@ async def get_item_async( Get record This operation gets a record. + + Swagger operation ID: `GetItem_V2`. + + Args: + table: table name. + id: item key. + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2262,7 +3014,7 @@ async def get_item_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2276,6 +3028,7 @@ async def get_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2283,13 +3036,13 @@ async def get_item_async( return json.loads(response.text) - async def patch_item_async( + def patch_item( self, - input: PatchItemInput, + input: PatchItemInput | Mapping[str, Any], table: str, id: str, - select: Optional[str] = None, *, + select: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2299,6 +3052,25 @@ async def patch_item_async( Update record This operation updates a record and allows null values. + + Swagger operation ID: `PatchItem_V3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: table name. + id: item key. + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2319,7 +3091,7 @@ async def patch_item_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -2333,6 +3105,7 @@ async def patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2340,9 +3113,9 @@ async def patch_item_async( return json.loads(response.text) - async def patch_item_by_external_id_async( + def patch_item_by_external_id( self, - input: PatchItemByExternalIdInput, + input: PatchItemByExternalIdInput | Mapping[str, Any], table: str, external_id_field: str, external_id: str, @@ -2357,6 +3130,26 @@ async def patch_item_by_external_id_async( This operation inserts or updates (upserts) a record using an external ID. + + Swagger operation ID: `PatchItemByExternalIdV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: The Salesforce object type like 'Leads'. + external_id_field: Field marked as external ID field on Salesforce + object. + external_id: External ID of the record to upsert. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2370,7 +3163,7 @@ async def patch_item_by_external_id_async( f"/{quote(quote(str(external_id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -2384,6 +3177,7 @@ async def patch_item_by_external_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2391,9 +3185,9 @@ async def patch_item_by_external_id_async( return json.loads(response.text) - async def post_item_async( + def post_item( self, - input: PostItemInput, + input: PostItemInput | Mapping[str, Any], table: str, *, timeout: Optional[float] = None, @@ -2405,6 +3199,23 @@ async def post_item_async( Create record This operation creates a record and allows null values. + + Swagger operation ID: `PostItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: table name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2416,7 +3227,7 @@ async def post_item_async( f"/items" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2430,6 +3241,7 @@ async def post_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2437,7 +3249,7 @@ async def post_item_async( return json.loads(response.text) - async def get_external_id_fields_async( + def list_external_id_fields( self, table: str, *, @@ -2445,11 +3257,30 @@ async def get_external_id_fields_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get External ID Fields This operation retrieves external ID fields of Salesforce object type. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetExternalIdFields`. + + Args: + table: The Salesforce object type like 'Leads'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2459,29 +3290,50 @@ async def get_external_id_fields_async( f"/{quote(quote(str(table), safe=''), safe='')}" f"/externalIdFields" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def get_metadata_for_get_item_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_metadata_for_get_item( self, table: str, *, @@ -2492,6 +3344,21 @@ async def get_metadata_for_get_item_async( ) -> dict[str, Any] | None: """ GetMetadataForGetItem + + Swagger operation ID: `GetMetadataForGetItem`. + + Args: + table: table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2503,7 +3370,7 @@ async def get_metadata_for_get_item_async( f"/getitem" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2517,6 +3384,7 @@ async def get_metadata_for_get_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2524,7 +3392,7 @@ async def get_metadata_for_get_item_async( return json.loads(response.text) - async def get_metadata_for_patch_item_async( + def get_metadata_for_patch_item( self, table: str, *, @@ -2535,6 +3403,21 @@ async def get_metadata_for_patch_item_async( ) -> dict[str, Any] | None: """ GetMetadataForPatchItem + + Swagger operation ID: `GetMetadataForPatchItem`. + + Args: + table: table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2546,7 +3429,7 @@ async def get_metadata_for_patch_item_async( f"/patchitem" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2560,6 +3443,7 @@ async def get_metadata_for_patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2567,7 +3451,7 @@ async def get_metadata_for_patch_item_async( return json.loads(response.text) - async def get_metadata_for_post_item_async( + def get_metadata_for_post_item( self, table: str, *, @@ -2578,6 +3462,21 @@ async def get_metadata_for_post_item_async( ) -> dict[str, Any] | None: """ GetMetadataForPostItem + + Swagger operation ID: `GetMetadataForPostItem`. + + Args: + table: table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2589,7 +3488,7 @@ async def get_metadata_for_post_item_async( f"/postitem" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2603,6 +3502,7 @@ async def get_metadata_for_post_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2610,7 +3510,7 @@ async def get_metadata_for_post_item_async( return json.loads(response.text) - async def get_table_async( + def get_table( self, table: str, *, @@ -2623,6 +3523,21 @@ async def get_table_async( Get object metadata This operation gets the object metadata for a Salesforce object type. + + Swagger operation ID: `GetTable`. + + Args: + table: Salesforce object type like 'Leads'. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2633,7 +3548,7 @@ async def get_table_async( f"/{quote(quote(str(table), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2647,6 +3562,7 @@ async def get_table_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/sdk/__init__.py b/src/azure/connectors/sdk/__init__.py index 3080b9c..1aa1ab4 100644 --- a/src/azure/connectors/sdk/__init__.py +++ b/src/azure/connectors/sdk/__init__.py @@ -11,6 +11,7 @@ from .client_base import ConnectorClientBase from .exceptions import ConnectorException from .http_client import ConnectorHttpClient, ConnectorResponse +from .polling import ConnectorPollingMethod from .response import ConnectorResponseHook, ConnectorResponseSnapshot from .trigger_payload import TriggerCallbackPayload, TriggerCallbackBody @@ -20,6 +21,7 @@ "ConnectorClientBase", "ConnectorException", "ConnectorHttpClient", + "ConnectorPollingMethod", "ConnectorResponse", "ConnectorResponseHook", "ConnectorResponseSnapshot", diff --git a/src/azure/connectors/sdk/_polling.py b/src/azure/connectors/sdk/_polling.py new file mode 100644 index 0000000..06c2a9d --- /dev/null +++ b/src/azure/connectors/sdk/_polling.py @@ -0,0 +1,111 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Shared helpers for connector long-running operation polling.""" + +import math +from datetime import datetime, timezone +from email.utils import parsedate_to_datetime +from typing import Mapping, Optional +from urllib.parse import urljoin, urlsplit + +from .response import ConnectorResponseSnapshot + +DEFAULT_POLLING_INTERVAL_SECONDS = 1.0 + + +def get_header(headers: Mapping[str, str], name: str) -> Optional[str]: + """Return a response header using HTTP case-insensitive matching.""" + normalized_name = name.casefold() + return next( + ( + value + for header_name, value in headers.items() + if header_name.casefold() == normalized_name + ), + None, + ) + + +def get_location(response: ConnectorResponseSnapshot) -> Optional[str]: + """Return the Location polling URL from a connector response.""" + return get_header(response.headers, "Location") + + +def resolve_polling_url( + polling_url: str, + connection_runtime_url: str, + current_polling_url: Optional[str] = None, +) -> str: + """Route a connector polling URL through the authenticated runtime origin.""" + if polling_url.startswith("/"): + return f"{connection_runtime_url}{polling_url}" + + parsed_polling_url = urlsplit(polling_url) + if not parsed_polling_url.scheme and not parsed_polling_url.netloc: + base_url = current_polling_url or f"{connection_runtime_url.rstrip('/')}/" + return urljoin(base_url, polling_url) + + parsed_connection = urlsplit(connection_runtime_url) + polling_hostname = parsed_polling_url.hostname + connection_hostname = parsed_connection.hostname + if polling_hostname is None or connection_hostname is None: + raise ValueError("Polling URLs must include a hostname.") + + polling_port = parsed_polling_url.port or ( + 443 if parsed_polling_url.scheme == "https" else 80 + ) + connection_port = parsed_connection.port or ( + 443 if parsed_connection.scheme == "https" else 80 + ) + if polling_hostname.casefold() == connection_hostname.casefold(): + if ( + parsed_polling_url.scheme == parsed_connection.scheme + and polling_port == connection_port + ): + return polling_url + raise ValueError( + "Polling URL origin must use the connection runtime scheme and port." + ) + + suffix = parsed_polling_url.path + if parsed_polling_url.query: + suffix += f"?{parsed_polling_url.query}" + return f"{connection_runtime_url}{suffix}" + + +def get_retry_after_seconds(response: ConnectorResponseSnapshot) -> float: + """Return the server-requested delay or the default polling interval.""" + retry_after = get_header(response.headers, "Retry-After") + if retry_after is None: + return DEFAULT_POLLING_INTERVAL_SECONDS + + try: + delay = float(retry_after) + return ( + max(0.0, delay) + if math.isfinite(delay) + else DEFAULT_POLLING_INTERVAL_SECONDS + ) + except ValueError: + try: + retry_at = parsedate_to_datetime(retry_after) + except (TypeError, ValueError): + return DEFAULT_POLLING_INTERVAL_SECONDS + + if retry_at.tzinfo is None: + retry_at = retry_at.replace(tzinfo=timezone.utc) + return max( + 0.0, + (retry_at - datetime.now(timezone.utc)).total_seconds(), + ) + + +def get_polling_status(response: Optional[ConnectorResponseSnapshot]) -> str: + """Map an HTTP response to an Azure Core polling status string.""" + if response is None: + return "NotStarted" + if response.status == 202: + return "InProgress" + if 200 <= response.status < 300: + return "Succeeded" + return "Failed" diff --git a/src/azure/connectors/sdk/aio/__init__.py b/src/azure/connectors/sdk/aio/__init__.py new file mode 100644 index 0000000..99375ed --- /dev/null +++ b/src/azure/connectors/sdk/aio/__init__.py @@ -0,0 +1,22 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Asynchronous runtime infrastructure for Azure connector clients.""" + +from ..exceptions import ConnectorException +from ..response import ConnectorResponseHook, ConnectorResponseSnapshot +from ..trigger_payload import TriggerCallbackBody, TriggerCallbackPayload +from .client_base import ConnectorClientBase +from .http_client import ConnectorHttpClient, ConnectorResponse +from .polling import ConnectorPollingMethod + +__all__ = [ + "ConnectorClientBase", + "ConnectorException", + "ConnectorHttpClient", + "ConnectorPollingMethod", + "ConnectorResponse", + "ConnectorResponseHook", + "ConnectorResponseSnapshot", + "TriggerCallbackBody", + "TriggerCallbackPayload", +] diff --git a/src/azure/connectors/sdk/aio/client_base.py b/src/azure/connectors/sdk/aio/client_base.py new file mode 100644 index 0000000..c8b049c --- /dev/null +++ b/src/azure/connectors/sdk/aio/client_base.py @@ -0,0 +1,80 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Abstract base class for generated connector clients.""" + +from abc import ABC, abstractmethod +from typing import Any, Optional + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.pipeline.transport import AsyncHttpTransport + +from .http_client import ConnectorHttpClient + + +class ConnectorClientBase(ABC): + """Abstract base class for generated connector clients.""" + + def __init__( + self, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """ + Initialize a ConnectorClientBase. + + Args: + credential: Caller-owned Azure Core credential. + timeout: Total network timeout for each request, including + retries, response loading, and body reads. Nonpositive values + disable SDK and transport deadlines. + transport: Optional Azure Core async HTTP transport closed by the + client through its asynchronous lifecycle. + """ + if credential is None: + raise ValueError("credential cannot be None") + + self._http_client = ConnectorHttpClient( + credential, + max_retry_attempts=max_retry_attempts, + timeout_seconds=timeout, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + retry_unsafe_http_methods=retry_unsafe_http_methods, + transport=transport, + **kwargs, + ) + + @property + @abstractmethod + def connector_name(self) -> str: + """Get the connector name.""" + pass + + @property + def http_client(self) -> ConnectorHttpClient: + """Get the HTTP client for making connector requests.""" + return self._http_client + + async def close(self) -> None: + """Close the HTTP client and release resources.""" + await self._http_client.close() + + async def __aenter__(self): + """Enter async context manager.""" + return self + + async def __aexit__(self, exc_type, exc_val, exc_tb): + """Exit async context manager.""" + await self.close() diff --git a/src/azure/connectors/sdk/aio/http_client.py b/src/azure/connectors/sdk/aio/http_client.py new file mode 100644 index 0000000..7756109 --- /dev/null +++ b/src/azure/connectors/sdk/aio/http_client.py @@ -0,0 +1,446 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Asynchronous HTTP client for connector operations.""" + +import asyncio +import json +import random +from importlib.metadata import PackageNotFoundError, version +from typing import Any, Dict, Generic, List, Mapping, Optional, TypeVar + +from azure.core.credentials import AzureKeyCredential +from azure.core.credentials_async import AsyncTokenCredential +from azure.core.exceptions import ServiceResponseTimeoutError +from azure.core.pipeline import AsyncPipeline +from azure.core.pipeline.policies import ( + AsyncBearerTokenCredentialPolicy, + AsyncRetryPolicy, + AzureKeyCredentialPolicy, + ContentDecodePolicy, + CustomHookPolicy, + DistributedTracingPolicy, + HeadersPolicy, + HttpLoggingPolicy, + NetworkTraceLoggingPolicy, + ProxyPolicy, + RequestIdPolicy, + RetryMode, + UserAgentPolicy, +) +from azure.core.pipeline.transport import AioHttpTransport, AsyncHttpTransport +from azure.core.rest import HttpRequest + +from ..exceptions import ConnectorException +from ..response import ConnectorResponseHook, ConnectorResponseSnapshot +from ..serialization import to_wire + +ResponseT = TypeVar("ResponseT") +_SAFE_RETRY_METHODS = frozenset({"GET", "HEAD", "OPTIONS", "TRACE"}) +_ALL_RETRY_METHODS = frozenset( + {"DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "TRACE"} +) +_AUTHENTICATION_AND_CONTENT_HEADERS = frozenset({"authorization", "content-type"}) +_PROTECTED_OPERATION_HEADERS = _AUTHENTICATION_AND_CONTENT_HEADERS | frozenset( + {"x-ms-client-request-id"} +) + +try: + _SDK_VERSION = version("azure-connectors") +except PackageNotFoundError: + _SDK_VERSION = "0.0.0" + + +class _JitterRetryPolicy(AsyncRetryPolicy): + """Add bounded positive jitter to Azure Core retry backoff.""" + + def __init__(self, *, jitter_factor: float = 0.0, **kwargs: Any): + """Initialize the retry policy.""" + super().__init__(**kwargs) + self._jitter_factor = max(0.0, jitter_factor) + + def get_backoff_time(self, settings: Dict[str, Any]) -> float: + """Return Azure Core backoff with optional positive jitter.""" + backoff = super().get_backoff_time(settings) + if backoff <= 0 or self._jitter_factor == 0: + return backoff + + jitter = random.uniform(0, backoff * self._jitter_factor) + return min(settings["max_backoff"], backoff + jitter) + + +class ConnectorResponse(Generic[ResponseT]): + """Represent a response from a connector operation.""" + + def __init__( + self, + status_code: int, + headers: Dict[str, str], + value: Optional[ResponseT], + ): + """Initialize the response.""" + self.status_code = status_code + self.headers = headers + self.value = value + + @property + def is_success_status_code(self) -> bool: + """Check whether the response indicates success.""" + return 200 <= self.status_code < 300 + + +class ConnectorHttpClient: + """Asynchronous HTTP client with Azure Core policies.""" + + API_HUB_SCOPES = ["https://apihub.azure.com/.default"] + + def __init__( + self, + credential: AsyncTokenCredential | AzureKeyCredential, + *, + max_retry_attempts: int = 3, + timeout_seconds: float = 30.0, + use_exponential_backoff: bool = True, + initial_retry_delay_seconds: float = 0.5, + maximum_retry_delay_seconds: float = 120.0, + retry_jitter_factor: float = 0.1, + retry_unsafe_http_methods: bool = False, + transport: Optional[AsyncHttpTransport] = None, + **kwargs: Any, + ): + """Initialize the HTTP client.""" + if credential is None: + raise ValueError("credential cannot be None") + + self._credential = credential + self._timeout_seconds = timeout_seconds + self._retry_unsafe_http_methods = retry_unsafe_http_methods + self._transport = transport or AioHttpTransport(**kwargs) + policy_options = dict(kwargs) + per_call_policies = self._as_policy_list( + policy_options.pop("per_call_policies", []) + ) + per_retry_policies = self._as_policy_list( + policy_options.pop("per_retry_policies", []) + ) + policies = policy_options.pop("policies", None) + if policies is None: + policies = self._build_policies( + credential, + policy_options, + per_call_policies=per_call_policies, + per_retry_policies=per_retry_policies, + max_retry_attempts=max_retry_attempts, + timeout_seconds=timeout_seconds, + use_exponential_backoff=use_exponential_backoff, + initial_retry_delay_seconds=initial_retry_delay_seconds, + maximum_retry_delay_seconds=maximum_retry_delay_seconds, + retry_jitter_factor=retry_jitter_factor, + ) + else: + policies = self._compose_policies( + policies, + per_call_policies=per_call_policies, + per_retry_policies=per_retry_policies, + ) + self._has_retry_policy = any( + isinstance(policy, AsyncRetryPolicy) for policy in policies + ) + self._pipeline = AsyncPipeline(self._transport, policies=policies) + + def _build_policies( + self, + credential: AsyncTokenCredential | AzureKeyCredential, + policy_options: Dict[str, Any], + *, + per_call_policies: List[Any], + per_retry_policies: List[Any], + max_retry_attempts: int, + timeout_seconds: float, + use_exponential_backoff: bool, + initial_retry_delay_seconds: float, + maximum_retry_delay_seconds: float, + retry_jitter_factor: float, + ) -> List[Any]: + """Build the standard Azure Core asynchronous policy chain.""" + default_headers = { + name: value + for name, value in policy_options.pop("headers", {}).items() + if name.lower() not in _AUTHENTICATION_AND_CONTENT_HEADERS + } + retry_total = policy_options.pop( + "retry_total", max(0, max_retry_attempts - 1) + ) + retry_connect = policy_options.pop("retry_connect", retry_total) + retry_read = policy_options.pop("retry_read", retry_total) + retry_status = policy_options.pop("retry_status", retry_total) + retry_backoff_factor = policy_options.pop( + "retry_backoff_factor", initial_retry_delay_seconds + ) + retry_backoff_max = policy_options.pop( + "retry_backoff_max", maximum_retry_delay_seconds + ) + retry_mode = policy_options.pop( + "retry_mode", + RetryMode.Exponential if use_exponential_backoff else RetryMode.Fixed, + ) + retry_timeout = policy_options.pop("timeout", timeout_seconds) + jitter_factor = policy_options.pop( + "retry_jitter_factor", retry_jitter_factor + ) + policies = [ + policy_options.pop("headers_policy", None) + or HeadersPolicy(base_headers=default_headers, **policy_options), + policy_options.pop("request_id_policy", None) + or RequestIdPolicy(**policy_options), + policy_options.pop("user_agent_policy", None) + or UserAgentPolicy( + sdk_moniker=f"connectors/{_SDK_VERSION}", **policy_options + ), + policy_options.pop("proxy_policy", None) + or ProxyPolicy(**policy_options), + ContentDecodePolicy(**policy_options), + ] + policies.extend(per_call_policies) + policies.extend( + [ + policy_options.pop("retry_policy", None) + or _JitterRetryPolicy( + retry_total=retry_total, + retry_connect=retry_connect, + retry_read=retry_read, + retry_status=retry_status, + retry_backoff_factor=retry_backoff_factor, + retry_backoff_max=retry_backoff_max, + retry_mode=retry_mode, + timeout=retry_timeout, + jitter_factor=jitter_factor, + **policy_options, + ), + policy_options.pop("authentication_policy", None) + or self._build_authentication_policy( + credential, + policy_options, + ), + policy_options.pop("custom_hook_policy", None) + or CustomHookPolicy(**policy_options), + ] + ) + policies.extend(per_retry_policies) + policies.extend( + [ + policy_options.pop("logging_policy", None) + or NetworkTraceLoggingPolicy(**policy_options), + policy_options.pop("distributed_tracing_policy", None) + or DistributedTracingPolicy(**policy_options), + policy_options.pop("http_logging_policy", None) + or HttpLoggingPolicy(**policy_options), + ] + ) + return policies + + @classmethod + def _compose_policies( + cls, + policies: Any, + *, + per_call_policies: List[Any], + per_retry_policies: List[Any], + ) -> List[Any]: + """Compose extension policies with an explicit Azure Core chain.""" + composed_policies = per_call_policies + cls._as_policy_list(policies) + if not per_retry_policies: + return composed_policies + + retry_policy_index = next( + ( + index + for index in range(len(composed_policies) - 1, -1, -1) + if isinstance(composed_policies[index], AsyncRetryPolicy) + ), + None, + ) + if retry_policy_index is None: + raise ValueError( + "Cannot add per_retry_policies because the explicit policy " + "chain has no AsyncRetryPolicy." + ) + + insertion_index = retry_policy_index + 1 + return ( + composed_policies[:insertion_index] + + per_retry_policies + + composed_policies[insertion_index:] + ) + + @classmethod + def _build_authentication_policy( + cls, + credential: AsyncTokenCredential | AzureKeyCredential, + policy_options: Dict[str, Any], + ) -> Any: + """Build the authentication policy for the credential type.""" + if isinstance(credential, AzureKeyCredential): + return AzureKeyCredentialPolicy( + credential, + "Authorization", + prefix="Bearer", + **policy_options, + ) + + return AsyncBearerTokenCredentialPolicy( + credential, + *cls.API_HUB_SCOPES, + **policy_options, + ) + + @staticmethod + def _as_policy_list(policies: Any) -> List[Any]: + """Normalize one policy or an iterable of policies to a list.""" + if policies is None: + return [] + if isinstance(policies, (list, tuple)): + return list(policies) + return [policies] + + async def close(self) -> None: + """Close the HTTP transport without closing the caller credential.""" + await self._pipeline.__aexit__(None, None, None) + + async def send( + self, + method: str, + url: str, + body: Optional[Any] = None, + content_type: Optional[str] = None, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> ConnectorResponseSnapshot: + """Send an HTTP request within the selected total network timeout.""" + is_binary_body = isinstance(body, (bytes, bytearray)) + if content_type is None: + content_type = ( + "application/octet-stream" if is_binary_body else "application/json" + ) + operation_headers = { + name: value + for name, value in (headers or {}).items() + if name.lower() not in _PROTECTED_OPERATION_HEADERS + } + request_headers = dict(operation_headers) + request_headers["Content-Type"] = content_type + request_body: Optional[Any] = None + if body is not None: + request_body = bytes(body) if is_binary_body else json.dumps(to_wire(body)) + + response = await self._send_with_retry( + self._pipeline, + method, + url, + request_headers, + request_body, + client_request_id=client_request_id, + timeout=timeout, + ) + if response_hook is not None: + response_hook(response, response.headers) + return response + + async def _send_with_retry( + self, + pipeline: AsyncPipeline, + method: str, + url: str, + headers: Dict[str, str], + body: Optional[Any], + *, + client_request_id: Optional[str] = None, + timeout: Optional[float] = None, + ) -> ConnectorResponseSnapshot: + """Send a request within one total Azure Core pipeline timeout.""" + normalized_method = method.upper() + request = HttpRequest(normalized_method, url, headers=headers, content=body) + selected_timeout = ( + timeout if timeout is not None else self._timeout_seconds + ) + request_options: Dict[str, Any] = {"headers": headers} + if selected_timeout > 0: + if self._has_retry_policy: + request_options["timeout"] = selected_timeout + if self._has_retry_policy and isinstance( + self._transport, AioHttpTransport + ): + request_options["read_timeout"] = selected_timeout + else: + if self._has_retry_policy: + request_options["timeout"] = float("inf") + request_options["connection_timeout"] = None + if isinstance(self._transport, AioHttpTransport): + request_options["read_timeout"] = None + if self._has_retry_policy and normalized_method not in _SAFE_RETRY_METHODS: + if self._retry_unsafe_http_methods: + request_options["retry_on_methods"] = ( + _ALL_RETRY_METHODS | {normalized_method} + ) + else: + request_options["retry_total"] = 0 + if client_request_id is not None: + request_options["request_id"] = client_request_id + + async def send_request() -> ConnectorResponseSnapshot: + pipeline_response = await pipeline.run(request, **request_options) + http_response = pipeline_response.http_response + response_content = http_response.body() + return ConnectorResponseSnapshot( + status=http_response.status_code, + headers=dict(http_response.headers), + text=http_response.text(), + content=response_content, + ) + + if selected_timeout <= 0: + return await send_request() + + try: + return await asyncio.wait_for( + send_request(), + timeout=selected_timeout, + ) + except asyncio.TimeoutError as ex: + raise ServiceResponseTimeoutError( + message=( + f"Request to '{url}' exceeded the total timeout of " + f"'{selected_timeout}' seconds." + ), + error=ex, + ) from ex + + async def get(self, request_uri: str) -> Any: + """Send a GET request.""" + response = await self.send("GET", request_uri) + if not 200 <= response.status < 300: + raise ConnectorException( + "GET", + request_uri, + response.status, + response.text, + response=response, + ) + + return json.loads(response.text) if response.text else None + + async def post(self, request_uri: str, body: Any) -> Any: + """Send a POST request with a JSON body.""" + response = await self.send("POST", request_uri, body) + if not 200 <= response.status < 300: + raise ConnectorException( + "POST", + request_uri, + response.status, + response.text, + response=response, + ) + + return json.loads(response.text) if response.text else None diff --git a/src/azure/connectors/sdk/aio/polling.py b/src/azure/connectors/sdk/aio/polling.py new file mode 100644 index 0000000..b88ed3d --- /dev/null +++ b/src/azure/connectors/sdk/aio/polling.py @@ -0,0 +1,129 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Asynchronous Azure Core polling for connector operations.""" + +import asyncio +from typing import Any, Callable, Generic, Mapping, Optional, TypeVar + +from azure.core.polling import AsyncPollingMethod + +from .._polling import ( + get_location, + get_polling_status, + get_retry_after_seconds, + resolve_polling_url, +) +from ..exceptions import ConnectorException +from ..response import ConnectorResponseHook, ConnectorResponseSnapshot + +PollingResultT = TypeVar("PollingResultT") + + +class ConnectorPollingMethod( + AsyncPollingMethod[PollingResultT], Generic[PollingResultT] +): + """Poll a connector operation until it returns a terminal HTTP response.""" + + def __init__( + self, + http_client: Any, + polling_header_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """Initialize connector polling request options.""" + if polling_header_name.casefold() != "location": + raise ValueError("Only the 'Location' polling header is supported.") + + self._http_client = http_client + self._timeout = timeout + self._headers = headers + self._client_request_id = client_request_id + self._response_hook = response_hook + self._response: Optional[ConnectorResponseSnapshot] = None + self._polling_url: Optional[str] = None + self._connection_runtime_url: Optional[str] = None + self._deserialization_callback: Optional[ + Callable[[ConnectorResponseSnapshot], PollingResultT] + ] = None + + def initialize( + self, + client: Any, + initial_response: ConnectorResponseSnapshot, + deserialization_callback: Callable[ + [ConnectorResponseSnapshot], PollingResultT + ], + ) -> None: + """Initialize polling from the operation's first response.""" + self._response = initial_response + self._connection_runtime_url = client._connection_runtime_url + self._deserialization_callback = deserialization_callback + if initial_response.status == 202: + self._update_polling_url(require_url=True) + + async def run(self) -> None: + """Poll until the connector returns a terminal response.""" + while not self.finished(): + if self._response is None or self._polling_url is None: + raise RuntimeError("Connector polling was not initialized.") + await asyncio.sleep(get_retry_after_seconds(self._response)) + request_url = self._polling_url + self._response = await self._http_client.send( + "GET", + request_url, + body=None, + timeout=self._timeout, + headers=self._headers, + client_request_id=self._client_request_id, + response_hook=self._response_hook, + ) + if self._response.status == 202: + self._update_polling_url(require_url=False) + elif not 200 <= self._response.status < 300: + raise ConnectorException( + "GET", + request_url, + self._response.status, + self._response.text, + response=self._response, + ) + + def status(self) -> str: + """Return the current Azure Core polling status.""" + return get_polling_status(self._response) + + def finished(self) -> bool: + """Return whether the connector has produced a terminal response.""" + return self._response is not None and self._response.status != 202 + + def resource(self) -> PollingResultT: + """Deserialize the terminal connector response.""" + if self._response is None or self._deserialization_callback is None: + raise RuntimeError("Connector polling was not initialized.") + if not self.finished(): + raise RuntimeError("Connector polling has not completed.") + return self._deserialization_callback(self._response) + + def _update_polling_url(self, *, require_url: bool) -> None: + """Update and validate the polling URL from the current response.""" + if self._response is None or self._connection_runtime_url is None: + raise RuntimeError("Connector polling was not initialized.") + location = get_location(self._response) + if location is None: + if require_url: + raise ValueError( + "An HTTP 202 response must include a 'Location' polling URL." + ) + return + self._polling_url = resolve_polling_url( + location, + self._connection_runtime_url, + self._polling_url, + ) + + +__all__ = ["ConnectorPollingMethod"] diff --git a/src/azure/connectors/sdk/client_base.py b/src/azure/connectors/sdk/client_base.py index 97d6455..16d7dae 100644 --- a/src/azure/connectors/sdk/client_base.py +++ b/src/azure/connectors/sdk/client_base.py @@ -1,44 +1,42 @@ # Copyright (c) Microsoft Corporation. All rights reserved. -"""Abstract base class for generated connector clients.""" +"""Abstract base class for synchronous generated connector clients.""" from abc import ABC, abstractmethod from typing import Any, Optional -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from .http_client import ConnectorHttpClient class ConnectorClientBase(ABC): - """Abstract base class for generated connector clients.""" + """Abstract base class for synchronous generated connector clients.""" def __init__( self, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ - Initialize a ConnectorClientBase. + Initialize a synchronous ConnectorClientBase. Args: credential: Caller-owned Azure Core credential. - timeout_seconds: Total network timeout for each request, including + timeout: Total network timeout for each request, including retries, response loading, and body reads. Nonpositive values disable SDK and transport deadlines. - transport: Optional Azure Core async HTTP transport closed by the - client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by the client. """ if credential is None: raise ValueError("credential cannot be None") @@ -46,7 +44,7 @@ def __init__( self._http_client = ConnectorHttpClient( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout_seconds=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -67,14 +65,14 @@ def http_client(self) -> ConnectorHttpClient: """Get the HTTP client for making connector requests.""" return self._http_client - async def close(self) -> None: + def close(self) -> None: """Close the HTTP client and release resources.""" - await self._http_client.close() + self._http_client.close() - async def __aenter__(self): - """Enter async context manager.""" + def __enter__(self): + """Enter the context manager.""" return self - async def __aexit__(self, exc_type, exc_val, exc_tb): - """Exit async context manager.""" - await self.close() + def __exit__(self, exc_type, exc_val, exc_tb): + """Exit the context manager.""" + self.close() diff --git a/src/azure/connectors/sdk/exceptions.py b/src/azure/connectors/sdk/exceptions.py index c86c7a1..12a9c33 100644 --- a/src/azure/connectors/sdk/exceptions.py +++ b/src/azure/connectors/sdk/exceptions.py @@ -2,8 +2,48 @@ """Exception types for connector operations.""" +from http import HTTPStatus +from typing import Optional -class ConnectorException(Exception): +from azure.core.exceptions import HttpResponseError +from azure.core.pipeline.transport import HttpRequest, HttpResponse + +from .response import ConnectorResponseSnapshot + + +class _ConnectorHttpResponse(HttpResponse): + """Adapt an immutable connector response to the Azure Core response API.""" + + def __init__( + self, + method: str, + path: str, + response: ConnectorResponseSnapshot, + ) -> None: + """Initialize the response adapter.""" + super().__init__(HttpRequest(method, path), internal_response=None) + self.status_code = response.status + self.headers = dict(response.headers) + try: + self.reason = HTTPStatus(response.status).phrase + except ValueError: + self.reason = None + self.content_type = next( + ( + value + for name, value in response.headers.items() + if name.lower() == "content-type" + ), + None, + ) + self._content = response.content + + def body(self) -> bytes: + """Return the buffered response body.""" + return self._content + + +class ConnectorException(HttpResponseError): """Exception raised when connector operations fail.""" MAX_RESPONSE_BODY_LENGTH = 2000 @@ -14,7 +54,9 @@ def __init__( path: str, status_code: int, response_body: str, - ): + *, + response: Optional[ConnectorResponseSnapshot] = None, + ) -> None: """ Initialize a ConnectorException. @@ -23,6 +65,7 @@ def __init__( path: The API path that was called (e.g., "/v2/Mail"). status_code: The HTTP status code. response_body: The response body from the failed request. + response: The completed connector response, when available. """ self.method = method self.path = path @@ -32,7 +75,20 @@ def __init__( truncated_body = self._truncate_body(response_body) message = f"{self.operation} failed with status {status_code}: " message += truncated_body - super().__init__(message) + if response is None: + response = ConnectorResponseSnapshot( + status=status_code, + headers={}, + text=response_body, + content=response_body.encode("utf-8"), + ) + super().__init__( + message=message, + response=_ConnectorHttpResponse(method, path, response), + ) + self.message = message + self.args = (message,) + self.status_code = status_code @classmethod def _truncate_body(cls, body: str) -> str: diff --git a/src/azure/connectors/sdk/http_client.py b/src/azure/connectors/sdk/http_client.py index d0e4cbb..46ac334 100644 --- a/src/azure/connectors/sdk/http_client.py +++ b/src/azure/connectors/sdk/http_client.py @@ -1,21 +1,19 @@ # Copyright (c) Microsoft Corporation. All rights reserved. -"""Asynchronous HTTP client for connector operations.""" +"""Synchronous HTTP client for connector operations.""" -import asyncio import json import random +import time from importlib.metadata import PackageNotFoundError, version from typing import Any, Dict, Generic, List, Mapping, Optional, TypeVar -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential +from azure.core.credentials import AzureKeyCredential, TokenCredential from azure.core.exceptions import ServiceResponseTimeoutError -from azure.core.pipeline import AsyncPipeline +from azure.core.pipeline import Pipeline from azure.core.pipeline.policies import ( - AsyncBearerTokenCredentialPolicy, - AsyncRetryPolicy, AzureKeyCredentialPolicy, + BearerTokenCredentialPolicy, ContentDecodePolicy, CustomHookPolicy, DistributedTracingPolicy, @@ -25,9 +23,10 @@ ProxyPolicy, RequestIdPolicy, RetryMode, + RetryPolicy, UserAgentPolicy, ) -from azure.core.pipeline.transport import AioHttpTransport, AsyncHttpTransport +from azure.core.pipeline.transport import HttpTransport, RequestsTransport from azure.core.rest import HttpRequest from .exceptions import ConnectorException @@ -50,7 +49,7 @@ _SDK_VERSION = "0.0.0" -class _JitterRetryPolicy(AsyncRetryPolicy): +class _JitterRetryPolicy(RetryPolicy): """Add bounded positive jitter to Azure Core retry backoff.""" def __init__(self, *, jitter_factor: float = 0.0, **kwargs: Any): @@ -89,13 +88,13 @@ def is_success_status_code(self) -> bool: class ConnectorHttpClient: - """Asynchronous HTTP client with Azure Core policies.""" + """Synchronous HTTP client with Azure Core policies.""" API_HUB_SCOPES = ["https://apihub.azure.com/.default"] def __init__( self, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, timeout_seconds: float = 30.0, @@ -104,7 +103,7 @@ def __init__( maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """Initialize the HTTP client.""" @@ -114,7 +113,7 @@ def __init__( self._credential = credential self._timeout_seconds = timeout_seconds self._retry_unsafe_http_methods = retry_unsafe_http_methods - self._transport = transport or AioHttpTransport() + self._transport = transport or RequestsTransport(**kwargs) policy_options = dict(kwargs) per_call_policies = self._as_policy_list( policy_options.pop("per_call_policies", []) @@ -143,13 +142,13 @@ def __init__( per_retry_policies=per_retry_policies, ) self._has_retry_policy = any( - isinstance(policy, AsyncRetryPolicy) for policy in policies + isinstance(policy, RetryPolicy) for policy in policies ) - self._pipeline = AsyncPipeline(self._transport, policies=policies) + self._pipeline = Pipeline(self._transport, policies=policies) def _build_policies( self, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, policy_options: Dict[str, Any], *, per_call_policies: List[Any], @@ -161,7 +160,7 @@ def _build_policies( maximum_retry_delay_seconds: float, retry_jitter_factor: float, ) -> List[Any]: - """Build the standard Azure Core asynchronous policy chain.""" + """Build the standard Azure Core synchronous policy chain.""" default_headers = { name: value for name, value in policy_options.pop("headers", {}).items() @@ -255,14 +254,14 @@ def _compose_policies( ( index for index in range(len(composed_policies) - 1, -1, -1) - if isinstance(composed_policies[index], AsyncRetryPolicy) + if isinstance(composed_policies[index], RetryPolicy) ), None, ) if retry_policy_index is None: raise ValueError( "Cannot add per_retry_policies because the explicit policy " - "chain has no AsyncRetryPolicy." + "chain has no RetryPolicy." ) insertion_index = retry_policy_index + 1 @@ -275,7 +274,7 @@ def _compose_policies( @classmethod def _build_authentication_policy( cls, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, policy_options: Dict[str, Any], ) -> Any: """Build the authentication policy for the credential type.""" @@ -287,7 +286,7 @@ def _build_authentication_policy( **policy_options, ) - return AsyncBearerTokenCredentialPolicy( + return BearerTokenCredentialPolicy( credential, *cls.API_HUB_SCOPES, **policy_options, @@ -302,11 +301,11 @@ def _as_policy_list(policies: Any) -> List[Any]: return list(policies) return [policies] - async def close(self) -> None: + def close(self) -> None: """Close the HTTP transport without closing the caller credential.""" - await self._pipeline.__aexit__(None, None, None) + self._pipeline.__exit__(None, None, None) - async def send_async( + def send( self, method: str, url: str, @@ -318,7 +317,7 @@ async def send_async( client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, ) -> ConnectorResponseSnapshot: - """Send an HTTP request within the selected total network timeout.""" + """Send an HTTP request with the selected network timeout.""" is_binary_body = isinstance(body, (bytes, bytearray)) if content_type is None: content_type = ( @@ -335,7 +334,7 @@ async def send_async( if body is not None: request_body = bytes(body) if is_binary_body else json.dumps(to_wire(body)) - response = await self._send_with_retry( + response = self._send_with_retry( self._pipeline, method, url, @@ -348,9 +347,9 @@ async def send_async( response_hook(response, response.headers) return response - async def _send_with_retry( + def _send_with_retry( self, - pipeline: AsyncPipeline, + pipeline: Pipeline, method: str, url: str, headers: Dict[str, str], @@ -359,7 +358,7 @@ async def _send_with_retry( client_request_id: Optional[str] = None, timeout: Optional[float] = None, ) -> ConnectorResponseSnapshot: - """Send a request within one total Azure Core pipeline timeout.""" + """Send a request with Azure Core retry and transport timeouts.""" normalized_method = method.upper() request = HttpRequest(normalized_method, url, headers=headers, content=body) selected_timeout = ( @@ -369,15 +368,15 @@ async def _send_with_retry( if selected_timeout > 0: if self._has_retry_policy: request_options["timeout"] = selected_timeout - if self._has_retry_policy and isinstance( - self._transport, AioHttpTransport - ): + else: + request_options["connection_timeout"] = selected_timeout + if isinstance(self._transport, RequestsTransport): request_options["read_timeout"] = selected_timeout else: if self._has_retry_policy: request_options["timeout"] = float("inf") request_options["connection_timeout"] = None - if isinstance(self._transport, AioHttpTransport): + if isinstance(self._transport, RequestsTransport): request_options["read_timeout"] = None if self._has_retry_policy and normalized_method not in _SAFE_RETRY_METHODS: if self._retry_unsafe_http_methods: @@ -389,56 +388,194 @@ async def _send_with_retry( if client_request_id is not None: request_options["request_id"] = client_request_id - async def send_request() -> ConnectorResponseSnapshot: - pipeline_response = await pipeline.run(request, **request_options) - http_response = pipeline_response.http_response - response_content = http_response.body() - return ConnectorResponseSnapshot( - status=http_response.status_code, - headers=dict(http_response.headers), - text=http_response.text(), - content=response_content, + enforce_total_timeout = ( + selected_timeout > 0 and isinstance(self._transport, RequestsTransport) + ) + if enforce_total_timeout: + request_options["stream"] = True + + return self._run_pipeline( + pipeline, + request, + request_options, + total_timeout=selected_timeout if enforce_total_timeout else None, + url=url, + ) + + @staticmethod + def _run_pipeline( + pipeline: Pipeline, + request: HttpRequest, + request_options: Dict[str, Any], + *, + total_timeout: Optional[float] = None, + url: Optional[str] = None, + ) -> ConnectorResponseSnapshot: + """Run the pipeline and buffer its response within an optional deadline.""" + started_at = time.monotonic() + pipeline_response = pipeline.run(request, **request_options) + http_response = pipeline_response.http_response + if total_timeout is None: + return ConnectorHttpClient._snapshot_response(http_response) + + deadline = started_at + total_timeout + try: + response_chunks = [] + while True: + remaining_timeout = deadline - time.monotonic() + if remaining_timeout <= 0: + raise ConnectorHttpClient._create_timeout_error( + url=url, + total_timeout=total_timeout, + ) + + response_chunk = ConnectorHttpClient._read_response_chunk( + http_response, + read_timeout=remaining_timeout, + ) + if not response_chunk: + break + response_chunks.append(response_chunk) + + if time.monotonic() >= deadline: + raise ConnectorHttpClient._create_timeout_error( + url=url, + total_timeout=total_timeout, + ) + + response_content = b"".join(response_chunks) + return ConnectorHttpClient._snapshot_response( + http_response, + response_content=response_content, + response_text=ConnectorHttpClient._decode_response_content( + response_content, + encoding=http_response.encoding, + ), ) + except Exception as ex: + if ( + time.monotonic() >= deadline + and not isinstance(ex, ServiceResponseTimeoutError) + ): + raise ConnectorHttpClient._create_timeout_error( + url=url, + total_timeout=total_timeout, + error=ex, + ) from ex + raise + finally: + http_response.close() - if selected_timeout <= 0: - return await send_request() + @staticmethod + def _create_timeout_error( + *, + url: Optional[str], + total_timeout: float, + error: Optional[Exception] = None, + ) -> ServiceResponseTimeoutError: + """Create the standard Azure Core total-timeout exception.""" + return ServiceResponseTimeoutError( + message=( + f"Request to '{url}' exceeded the total timeout of " + f"'{total_timeout}' seconds." + ), + error=error, + ) - try: - return await asyncio.wait_for( - send_request(), - timeout=selected_timeout, + @staticmethod + def _read_response_chunk( + http_response: Any, + *, + read_timeout: float, + ) -> bytes: + """Read one available chunk from an Azure Core Requests response.""" + internal_response = getattr(http_response, "_internal_response", None) + raw_response = getattr(internal_response, "raw", None) + read_chunk = getattr(raw_response, "read1", None) + if not callable(read_chunk): + raise RuntimeError( + "The Azure Core Requests response does not expose incremental " + "body reads required for total timeout enforcement." ) - except asyncio.TimeoutError as ex: - raise ServiceResponseTimeoutError( - message=( - f"Request to '{url}' exceeded the total timeout of " - f"'{selected_timeout}' seconds." + + response_socket = getattr( + getattr( + getattr( + getattr(raw_response, "_fp", None), + "fp", + None, ), - error=ex, - ) from ex + "raw", + None, + ), + "_sock", + None, + ) + set_timeout = getattr(response_socket, "settimeout", None) + if not callable(set_timeout): + raise RuntimeError( + "The Azure Core Requests response does not expose the active " + "socket required for total timeout enforcement." + ) + set_timeout(read_timeout) + + return read_chunk(64 * 1024, decode_content=True) + + @staticmethod + def _decode_response_content( + response_content: bytes, + *, + encoding: Optional[str], + ) -> str: + """Decode buffered response content using Azure Core encoding metadata.""" + try: + return response_content.decode(encoding or "utf-8", errors="replace") + except LookupError: + return response_content.decode("utf-8", errors="replace") + + @staticmethod + def _snapshot_response( + http_response: Any, + *, + response_content: Optional[bytes] = None, + response_text: Optional[str] = None, + ) -> ConnectorResponseSnapshot: + """Buffer an Azure Core response into an immutable snapshot.""" + if response_content is None: + response_content = http_response.body() + if response_text is None: + response_text = http_response.text() + return ConnectorResponseSnapshot( + status=http_response.status_code, + headers=dict(http_response.headers), + text=response_text, + content=response_content, + ) - async def get_async(self, request_uri: str) -> Any: + def get(self, request_uri: str) -> Any: """Send a GET request.""" - response = await self.send_async("GET", request_uri) + response = self.send("GET", request_uri) if not 200 <= response.status < 300: raise ConnectorException( "GET", request_uri, response.status, response.text, + response=response, ) return json.loads(response.text) if response.text else None - async def post_async(self, request_uri: str, body: Any) -> Any: + def post(self, request_uri: str, body: Any) -> Any: """Send a POST request with a JSON body.""" - response = await self.send_async("POST", request_uri, body) + response = self.send("POST", request_uri, body) if not 200 <= response.status < 300: raise ConnectorException( "POST", request_uri, response.status, response.text, + response=response, ) return json.loads(response.text) if response.text else None diff --git a/src/azure/connectors/sdk/polling.py b/src/azure/connectors/sdk/polling.py new file mode 100644 index 0000000..b3dd854 --- /dev/null +++ b/src/azure/connectors/sdk/polling.py @@ -0,0 +1,127 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Synchronous Azure Core polling for connector operations.""" + +import time +from typing import Any, Callable, Generic, Mapping, Optional, TypeVar + +from azure.core.polling import PollingMethod + +from ._polling import ( + get_location, + get_polling_status, + get_retry_after_seconds, + resolve_polling_url, +) +from .exceptions import ConnectorException +from .response import ConnectorResponseHook, ConnectorResponseSnapshot + +PollingResultT = TypeVar("PollingResultT") + + +class ConnectorPollingMethod(PollingMethod[PollingResultT], Generic[PollingResultT]): + """Poll a connector operation until it returns a terminal HTTP response.""" + + def __init__( + self, + http_client: Any, + polling_header_name: str, + *, + timeout: Optional[float] = None, + headers: Optional[Mapping[str, str]] = None, + client_request_id: Optional[str] = None, + response_hook: Optional[ConnectorResponseHook] = None, + ) -> None: + """Initialize connector polling request options.""" + if polling_header_name.casefold() != "location": + raise ValueError("Only the 'Location' polling header is supported.") + + self._http_client = http_client + self._timeout = timeout + self._headers = headers + self._client_request_id = client_request_id + self._response_hook = response_hook + self._response: Optional[ConnectorResponseSnapshot] = None + self._polling_url: Optional[str] = None + self._connection_runtime_url: Optional[str] = None + self._deserialization_callback: Optional[ + Callable[[ConnectorResponseSnapshot], PollingResultT] + ] = None + + def initialize( + self, + client: Any, + initial_response: ConnectorResponseSnapshot, + deserialization_callback: Callable[ + [ConnectorResponseSnapshot], PollingResultT + ], + ) -> None: + """Initialize polling from the operation's first response.""" + self._response = initial_response + self._connection_runtime_url = client._connection_runtime_url + self._deserialization_callback = deserialization_callback + if initial_response.status == 202: + self._update_polling_url(require_url=True) + + def run(self) -> None: + """Poll until the connector returns a terminal response.""" + while not self.finished(): + if self._response is None or self._polling_url is None: + raise RuntimeError("Connector polling was not initialized.") + time.sleep(get_retry_after_seconds(self._response)) + request_url = self._polling_url + self._response = self._http_client.send( + "GET", + request_url, + body=None, + timeout=self._timeout, + headers=self._headers, + client_request_id=self._client_request_id, + response_hook=self._response_hook, + ) + if self._response.status == 202: + self._update_polling_url(require_url=False) + elif not 200 <= self._response.status < 300: + raise ConnectorException( + "GET", + request_url, + self._response.status, + self._response.text, + response=self._response, + ) + + def status(self) -> str: + """Return the current Azure Core polling status.""" + return get_polling_status(self._response) + + def finished(self) -> bool: + """Return whether the connector has produced a terminal response.""" + return self._response is not None and self._response.status != 202 + + def resource(self) -> PollingResultT: + """Deserialize the terminal connector response.""" + if self._response is None or self._deserialization_callback is None: + raise RuntimeError("Connector polling was not initialized.") + if not self.finished(): + raise RuntimeError("Connector polling has not completed.") + return self._deserialization_callback(self._response) + + def _update_polling_url(self, *, require_url: bool) -> None: + """Update and validate the polling URL from the current response.""" + if self._response is None or self._connection_runtime_url is None: + raise RuntimeError("Connector polling was not initialized.") + location = get_location(self._response) + if location is None: + if require_url: + raise ValueError( + "An HTTP 202 response must include a 'Location' polling URL." + ) + return + self._polling_url = resolve_polling_url( + location, + self._connection_runtime_url, + self._polling_url, + ) + + +__all__ = ["ConnectorPollingMethod"] diff --git a/src/azure/connectors/sdk/serialization.py b/src/azure/connectors/sdk/serialization.py index 875c0d1..d051542 100644 --- a/src/azure/connectors/sdk/serialization.py +++ b/src/azure/connectors/sdk/serialization.py @@ -13,6 +13,7 @@ from __future__ import annotations +from collections.abc import Mapping from dataclasses import fields, is_dataclass from typing import Any @@ -28,8 +29,8 @@ def to_wire(value: Any) -> Any: name). ``None`` dataclass fields and ``None`` map values are omitted. ``additional_properties`` are merged into the containing object, mirroring the .NET ``[JsonExtensionData]`` behavior. Lists and tuples are converted - element-by-element, and dictionaries are converted value-by-value with - their keys preserved. Raw ``bytes`` and ``bytearray`` are returned + element-by-element, and mappings are converted value-by-value with their + keys preserved. Raw ``bytes`` and ``bytearray`` are returned unchanged so binary payloads are never JSON-encoded. All other scalar values pass through unchanged. @@ -45,7 +46,7 @@ def to_wire(value: Any) -> Any: if is_dataclass(value) and not isinstance(value, type): return _dataclass_to_wire(value) - if isinstance(value, dict): + if isinstance(value, Mapping): return { key: to_wire(item) for key, item in value.items() diff --git a/src/azure/connectors/seismicplanner.py b/src/azure/connectors/seismicplanner.py index 90c272f..9765b5c 100644 --- a/src/azure/connectors/seismicplanner.py +++ b/src/azure/connectors/seismicplanner.py @@ -5,21 +5,64 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "SeismicplannerClient", + "Association", + "AssociationReq", + "AsyncOperationResponse", + "Comment", + "CommentQueryResponse", + "ContentRef", + "CreateCommentModel", + "CreateProject", + "CreateRequest", + "CreateTask", + "CustomProperty", + "CustomPropertyDataDisplay", + "CustomPropertyValues", + "CustomPropertyValuesInput", + "CustomPropertyValuesValues", + "DeleteRequest", + "Follower", + "Meta", + "MetaQueryInfo", + "PlannerProject", + "PlannerProjectQueryResponse", + "PlannerRequest", + "PlannerRequestQueryResponse", + "PlannerSubTask", + "PlannerTask", + "PlannerTaskQueryResponse", + "PossibleValuesItem", + "ProblemDetails", + "ProjectAssociatedNodes", + "RequestFormCustomProperties", + "ScopeSettingsItemDefinition", + "StatusSchema", + "StatusSchemaQueryResponse", + "UpdateCommentModel", + "UpdateProject", + "UpdateRequest", + "UpdateTask", + "ValueSchemaPropertyDefinition", +] + # Type Definitions @@ -29,15 +72,20 @@ class CommentQueryResponse: Response for Get comments """ - count: Optional[int] = None + count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of records returned""" - cursor: Optional[str] = None + cursor: Optional[str] = dataclass_field(default=None, kw_only=True) """Cursor used for pagination""" - items: Optional[List[Comment]] = None + items: Optional[ + List[Comment | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of items in the response""" - limit: Optional[int] = None + limit: Optional[int] = dataclass_field(default=None, kw_only=True) """Number to limit records""" - meta: Optional[Meta] = None + meta: Optional[Meta | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -46,67 +94,80 @@ class Comment: Response for Create comment """ - annotation_payload: Optional[str] = field( + annotation_payload: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "annotationPayload"}, ) - annotation_type: Optional[str] = field( + annotation_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "annotationType"}, ) - comment_content: Optional[str] = field( + comment_content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "commentContent"}, ) - created_at: Optional[str] = field( + created_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdAt"}, ) """Date string of date created""" - creator_id: Optional[str] = field( + creator_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "creatorId"}, ) """User ID of the creator""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Comment ID""" - is_resolved: Optional[bool] = field( + is_resolved: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isResolved"}, ) """True/false on whether the comment is resolved""" - node_id: Optional[str] = field( + node_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nodeId"}, ) """Node ID""" - node_type: Optional[str] = field( + node_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nodeType"}, ) """Node type of the comment""" - page_index: Optional[str] = field( + page_index: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pageIndex"}, ) """Number page index""" - parent_id: Optional[str] = field( + parent_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentId"}, ) """Parent comment ID""" - reply_count: Optional[int] = field( + reply_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "replyCount"}, ) """Number of replies""" - space_id: Optional[str] = field( + space_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "spaceId"}, ) """Space ID""" - updated_at: Optional[str] = field( + updated_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "updatedAt"}, ) """Date string of updated date""" @@ -118,15 +179,20 @@ class PlannerProjectQueryResponse: Response for Get projects """ - count: Optional[int] = None + count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of records returned""" - cursor: Optional[str] = None + cursor: Optional[str] = dataclass_field(default=None, kw_only=True) """Cursor used for pagination""" - items: Optional[List[PlannerProject]] = None + items: Optional[ + List[PlannerProject | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of project items in the response""" - limit: Optional[int] = None + limit: Optional[int] = dataclass_field(default=None, kw_only=True) """Number to limit records""" - meta: Optional[Meta] = None + meta: Optional[Meta | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -135,8 +201,9 @@ class AsyncOperationResponse: Response for Delete projects """ - async_operation_ids: Optional[List[str]] = field( + async_operation_ids: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "asyncOperationIds"}, ) """List of async action IDs""" @@ -148,110 +215,148 @@ class PlannerProject: Response for Create project """ - actual_duration: Optional[int] = field( + actual_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "actualDuration"}, ) """Calculated actual duration in days""" - actual_end_date: Optional[str] = field( + actual_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "actualEndDate"}, ) """Calculated end date from when the project actually ended""" - actual_start_date: Optional[str] = field( + actual_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "actualStartDate"}, ) """Calculated start date from when the project actually started""" - associated_nodes: Optional[List[ProjectAssociatedNodes]] = field( + associated_nodes: Optional[ + List[ProjectAssociatedNodes | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "associatedNodes"}, ) """List of association data""" - associations: Optional[List[Association]] = None + associations: Optional[ + List[Association | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of associations (Library content)""" - copy_from: Optional[str] = field( + copy_from: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "copyFrom"}, ) """Project ID the project is copied from""" - created_at: Optional[str] = field( + created_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdAt"}, ) """Date string of created date""" - creator_id: Optional[str] = field( + creator_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "creatorId"}, ) """User ID of creator""" - custom_properties: Optional[List[CustomPropertyValues]] = field( + custom_properties: Optional[ + List[CustomPropertyValues | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customProperties"}, ) """List of custom properties""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of project""" - followers: Optional[List[Follower]] = None + followers: Optional[ + List[Follower | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of followers""" - id: Optional[str] = None - is_active: Optional[bool] = field( + id: Optional[str] = dataclass_field(default=None, kw_only=True) + is_active: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isActive"}, ) """Indicator on if a project is active or not""" - is_template: Optional[bool] = field( + is_template: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isTemplate"}, ) """Indicator on if the project is a template or not""" - manager_id: Optional[str] = field( + manager_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerId"}, ) """User ID of project manager""" - max_rank: Optional[str] = field( + max_rank: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "maxRank"}, ) """Maximum rank number""" - min_rank: Optional[str] = field( + min_rank: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "minRank"}, ) """Minimum rank number""" - planned_duration: Optional[int] = field( + planned_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedDuration"}, ) """Planned duration in days""" - planned_end_date: Optional[str] = field( + planned_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedEndDate"}, ) """Date string of planned end date""" - planned_start_date: Optional[str] = field( + planned_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedStartDate"}, ) """Date string of planned start date""" - space_id: Optional[str] = field( + space_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "spaceId"}, ) - template_id: Optional[str] = field( + template_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "templateId"}, ) """Template ID the the project was created from""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of project""" - updated_at: Optional[str] = field( + updated_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "updatedAt"}, ) """Date project was last updated""" - works: Optional[List[PlannerTask]] = None + works: Optional[ + List[PlannerTask | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of tasks and requests""" @@ -261,15 +366,20 @@ class PlannerRequestQueryResponse: Response for Get requests """ - count: Optional[int] = None + count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of records returned""" - cursor: Optional[str] = None + cursor: Optional[str] = dataclass_field(default=None, kw_only=True) """Cursor used for pagination""" - items: Optional[List[PlannerRequest]] = None + items: Optional[ + List[PlannerRequest | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of request objects in the response""" - limit: Optional[int] = None + limit: Optional[int] = dataclass_field(default=None, kw_only=True) """Number to limit records""" - meta: Optional[Meta] = None + meta: Optional[Meta | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -278,93 +388,123 @@ class PlannerRequest: Response for Create request """ - assignee_id: Optional[str] = field( + assignee_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assigneeId"}, ) """User ID of the assignee""" - assigner_id: Optional[str] = field( + assigner_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignerId"}, ) """User ID of the assigner""" - associations: Optional[List[Association]] = None + associations: Optional[ + List[Association | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of associations (Library content)""" - content_refs: Optional[List[ContentRef]] = field( + content_refs: Optional[List[ContentRef | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentRefs"}, ) """List of content references (WorkSpace and DocCenter content)""" - created_at: Optional[str] = field( + created_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdAt"}, ) """Date string for created date""" - creator_id: Optional[str] = field( + creator_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "creatorId"}, ) """User ID of the creator""" - custom_properties: Optional[List[CustomPropertyValues]] = field( + custom_properties: Optional[ + List[CustomPropertyValues | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customProperties"}, ) """List of custom properties""" - followers: Optional[List[Follower]] = None + followers: Optional[ + List[Follower | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of followers""" - form_ref: Optional[Any] = field( + form_ref: Optional[Any] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "formRef"}, ) """Form reference object""" - id: Optional[str] = None - note: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + note: Optional[str] = dataclass_field(default=None, kw_only=True) """Note for notifications on status changes""" - planned_duration: Optional[int] = field( + planned_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedDuration"}, ) """Planned duration in days""" - planned_end_date: Optional[str] = field( + planned_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedEndDate"}, ) """Date string of planned end date""" - planned_start_date: Optional[str] = field( + planned_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedStartDate"}, ) """Date string of planned start date""" - priority: Optional[str] = None + priority: Optional[str] = dataclass_field(default=None, kw_only=True) """Priority value""" - project_id: Optional[str] = field( + project_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "projectId"}, ) """Project ID of the project the request is associated with""" - rank: Optional[str] = None + rank: Optional[str] = dataclass_field(default=None, kw_only=True) """Rank of request in request list""" - request_form_custom_property_option: Optional[RequestFormCustomProperties] = field( + request_form_custom_property_option: Optional[ + RequestFormCustomProperties | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requestFormCustomPropertyOption"}, ) - space_id: Optional[str] = field( + space_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "spaceId"}, ) - status_schema_id: Optional[str] = field( + status_schema_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "statusSchemaId"}, ) - step_id: Optional[int] = field( + step_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "stepId"}, ) """Step ID indicating the status value""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of the request""" - updated_at: Optional[str] = field( + updated_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "updatedAt"}, ) """Date the request was last updated""" @@ -376,15 +516,20 @@ class StatusSchemaQueryResponse: Response for Get status schemas """ - count: Optional[int] = None + count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of records returned""" - cursor: Optional[str] = None + cursor: Optional[str] = dataclass_field(default=None, kw_only=True) """Cursor used for pagination""" - items: Optional[List[StatusSchema]] = None + items: Optional[ + List[StatusSchema | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of status schema objects in the response""" - limit: Optional[int] = None + limit: Optional[int] = dataclass_field(default=None, kw_only=True) """Number to limit records""" - meta: Optional[Meta] = None + meta: Optional[Meta | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -393,36 +538,45 @@ class StatusSchema: Response for Get status schema """ - created_at: Optional[str] = field( + created_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdAt"}, ) """Date string of created date""" - creator_id: Optional[str] = field( + creator_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "creatorId"}, ) """User ID of creator""" - id: Optional[str] = None - is_default: Optional[bool] = field( + id: Optional[str] = dataclass_field(default=None, kw_only=True) + is_default: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isDefault"}, ) """Indicator on if the status schema is the default schema""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of status schema""" - space_id: Optional[str] = field( + space_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "spaceId"}, ) - steps: Optional[List[str]] = None + steps: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """List of steps and their values""" - transitions: Optional[List[List[int]]] = None + transitions: Optional[List[List[int]]] = dataclass_field(default=None, kw_only=True) """List of transition rules""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Node type the status schema can be used for""" - updated_at: Optional[str] = field( + updated_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "updatedAt"}, ) """Date the status schema was last updated""" @@ -434,15 +588,20 @@ class PlannerTaskQueryResponse: Response for Get tasks """ - count: Optional[int] = None + count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of records returned""" - cursor: Optional[str] = None + cursor: Optional[str] = dataclass_field(default=None, kw_only=True) """Cursor used for pagination""" - items: Optional[List[PlannerTask]] = None + items: Optional[ + List[PlannerTask | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of task objects in the response""" - limit: Optional[int] = None + limit: Optional[int] = dataclass_field(default=None, kw_only=True) """Number to limit records""" - meta: Optional[Meta] = None + meta: Optional[Meta | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -451,136 +610,176 @@ class PlannerTask: Response for Create task """ - actual_duration: Optional[int] = field( + actual_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "actualDuration"}, ) """Calculated actual duration in days""" - actual_end_date: Optional[str] = field( + actual_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "actualEndDate"}, ) """Date when work on the task was completed""" - actual_start_date: Optional[str] = field( + actual_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "actualStartDate"}, ) """Date when work on the task started""" - assignee_id: Optional[str] = field( + assignee_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assigneeId"}, ) """User ID of assignee""" - assigner_id: Optional[str] = field( + assigner_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignerId"}, ) """User ID of the last user to add an assignee""" - associations: Optional[List[Association]] = None + associations: Optional[ + List[Association | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of associations on a task""" - copy_from: Optional[str] = field( + copy_from: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "copyFrom"}, ) """Task ID that task was copied from""" - created_at: Optional[str] = field( + created_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdAt"}, ) """Date the task was created""" - creator_id: Optional[str] = field( + creator_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "creatorId"}, ) """User ID of creator""" - custom_properties: Optional[List[CustomPropertyValues]] = field( + custom_properties: Optional[ + List[CustomPropertyValues | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customProperties"}, ) """List of custom properties on a task""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of task""" - followers: Optional[List[Follower]] = None + followers: Optional[ + List[Follower | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of followers on a task""" - id: Optional[str] = None - is_template: Optional[bool] = field( + id: Optional[str] = dataclass_field(default=None, kw_only=True) + is_template: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isTemplate"}, ) """Indicates if a task is part of a template""" - max_rank: Optional[str] = field( + max_rank: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "maxRank"}, ) """Maximum rank""" - min_rank: Optional[str] = field( + min_rank: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "minRank"}, ) """Minimum rank""" - parent_id: Optional[str] = field( + parent_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentId"}, ) """Task ID of parent if task is a subtask""" - planned_duration: Optional[int] = field( + planned_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedDuration"}, ) """Planned duration in days""" - planned_end_date: Optional[str] = field( + planned_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedEndDate"}, ) """Date string of planned end date (due date)""" - planned_start_date: Optional[str] = field( + planned_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedStartDate"}, ) """Date string of planned start date""" - priority: Optional[str] = None + priority: Optional[str] = dataclass_field(default=None, kw_only=True) """Priority value""" - project_id: Optional[str] = field( + project_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "projectId"}, ) """Project ID the task belongs to""" - rank: Optional[str] = None + rank: Optional[str] = dataclass_field(default=None, kw_only=True) """Rank of task in a task list""" - space_id: Optional[str] = field( + space_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "spaceId"}, ) - status_schema_id: Optional[str] = field( + status_schema_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "statusSchemaId"}, ) - step_id: Optional[int] = field( + step_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "stepId"}, ) """Id of step in status schema""" - sub_task_ids: Optional[List[str]] = field( + sub_task_ids: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "subTaskIds"}, ) """List of subtask IDs""" - sub_tasks: Optional[List[PlannerSubTask]] = field( + sub_tasks: Optional[List[PlannerSubTask | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "subTasks"}, ) """List of subtasks on the task""" - template_id: Optional[str] = field( + template_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "templateId"}, ) """Template ID of the template the task belongs to""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of task""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type of task""" - updated_at: Optional[str] = field( + updated_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "updatedAt"}, ) """Date the task was last updated""" @@ -592,32 +791,37 @@ class Association: Definition: Association """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of association""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of association""" - node_guid: Optional[str] = field( + node_guid: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nodeGuid"}, ) """Longer GUID format""" - node_id: Optional[str] = field( + node_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nodeId"}, ) """Node ID""" - node_type: Optional[str] = field( + node_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nodeType"}, ) """Node type of the association""" - space_guid: Optional[str] = field( + space_guid: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "spaceGuid"}, ) """Longer GUID format""" - space_id: Optional[str] = field( + space_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "spaceId"}, ) """Space ID""" @@ -629,18 +833,21 @@ class AssociationReq: Definition: AssociationReq """ - node_id: Optional[str] = field( + node_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nodeId"}, ) """Node ID""" - node_type: Optional[str] = field( + node_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nodeType"}, ) """Node type of the association""" - space_id: Optional[str] = field( + space_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "spaceId"}, ) """Space ID""" @@ -652,60 +859,71 @@ class ContentRef: Definition: ContentRef """ - content_id: Optional[str] = field( + content_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentId"}, ) """Content ID""" - doc_center_full_path: Optional[str] = field( + doc_center_full_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "docCenterFullPath"}, ) """Full location path of where content exists in DocCenter""" - major_version: Optional[int] = field( + major_version: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "majorVersion"}, ) """Number of major version""" - minor_version: Optional[int] = field( + minor_version: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "minorVersion"}, ) """Number of minor version""" - modified_date: Optional[str] = field( + modified_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "modifiedDate"}, ) """Date the content reference was last updated""" - order_no: Optional[int] = field( + order_no: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "orderNo"}, ) """Number to indicate order""" - profile_id: Optional[str] = field( + profile_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "profileId"}, ) """Profile ID""" - profile_version_id: Optional[str] = field( + profile_version_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "profileVersionId"}, ) """Version ID of profile""" - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Source of content""" - team_site_id: Optional[str] = field( + team_site_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "teamSiteId"}, ) """TeamSite ID""" - thumbnail_id: Optional[str] = field( + thumbnail_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "thumbnailId"}, ) """ID for image thumbnail""" - version_id: Optional[str] = field( + version_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "versionId"}, ) """Version ID of content""" @@ -717,22 +935,26 @@ class CreateCommentModel: Definition: CreateCommentModel """ - annotation_payload: Optional[str] = field( + annotation_payload: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "annotationPayload"}, ) - annotation_type: Optional[str] = field( + annotation_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "annotationType"}, ) """Annotation type""" - comment_content: Optional[str] = field( + comment_content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "commentContent"}, ) """Content of the comment""" - is_resolved: Optional[bool] = field( + is_resolved: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isResolved"}, ) """True/false on whether the comment is resolved""" @@ -744,36 +966,48 @@ class CreateProject: Definition: CreateProject """ - associations: Optional[List[AssociationReq]] = None + associations: Optional[ + List[AssociationReq | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of association objects""" - custom_properties: Optional[List[CustomPropertyValuesInput]] = field( + custom_properties: Optional[ + List[CustomPropertyValuesInput | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customProperties"}, ) """List of custom properties""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of description""" - manager_id: Optional[str] = field( + manager_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerId"}, ) """User ID of manager""" - planned_duration: Optional[int] = field( + planned_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedDuration"}, ) """Planned duration in days""" - planned_end_date: Optional[str] = field( + planned_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedEndDate"}, ) """Date string of end date""" - planned_start_date: Optional[str] = field( + planned_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedStartDate"}, ) """Date string of start date""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of project""" @@ -783,55 +1017,71 @@ class CreateRequest: Definition: CreateRequest """ - assignee_id: Optional[str] = field( + assignee_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assigneeId"}, ) """User ID of assignee""" - associations: Optional[List[AssociationReq]] = None + associations: Optional[ + List[AssociationReq | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of associations (Library content)""" - content_refs: Optional[List[ContentRef]] = field( + content_refs: Optional[List[ContentRef | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentRefs"}, ) """List of content references (DocCenter and Workspace associations)""" - custom_properties: Optional[List[CustomPropertyValuesInput]] = field( + custom_properties: Optional[ + List[CustomPropertyValuesInput | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customProperties"}, ) """List of custom properties""" - form_ref: Optional[Any] = field( + form_ref: Optional[Any] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "formRef"}, ) """Form reference object""" - planned_duration: Optional[int] = field( + planned_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedDuration"}, ) """Planned duration in days""" - planned_end_date: Optional[str] = field( + planned_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedEndDate"}, ) """Date string of end date""" - planned_start_date: Optional[str] = field( + planned_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedStartDate"}, ) """Date string of start date""" - priority: Optional[str] = None + priority: Optional[str] = dataclass_field(default=None, kw_only=True) """Priority value""" - project_id: Optional[str] = field( + project_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "projectId"}, ) """ID of project the request belongs to""" - status_schema_id: Optional[str] = field( + status_schema_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "statusSchemaId"}, ) - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of request""" @@ -841,48 +1091,62 @@ class CreateTask: Definition: CreateTask """ - assignee_id: Optional[str] = field( + assignee_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assigneeId"}, ) """User ID of assignee""" - associations: Optional[List[AssociationReq]] = None + associations: Optional[ + List[AssociationReq | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of associations (Library content)""" - custom_properties: Optional[List[CustomPropertyValuesInput]] = field( + custom_properties: Optional[ + List[CustomPropertyValuesInput | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customProperties"}, ) """List of custom properties""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of task""" - parent_id: Optional[str] = field( + parent_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentId"}, ) """Task ID of parent""" - planned_duration: Optional[int] = field( + planned_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedDuration"}, ) """Planned duration in days""" - planned_end_date: Optional[str] = field( + planned_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedEndDate"}, ) """Date string of end date""" - planned_start_date: Optional[str] = field( + planned_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedStartDate"}, ) """Date string of start date""" - priority: Optional[str] = None + priority: Optional[str] = dataclass_field(default=None, kw_only=True) """Priority values""" - project_id: Optional[str] = field( + project_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "projectId"}, ) """ID of project the task is associated with""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of task""" @@ -892,73 +1156,88 @@ class CustomProperty: Definition: CustomProperty """ - allow_multiple_values: Optional[bool] = field( + allow_multiple_values: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowMultipleValues"}, ) """Indicates if custom property allows for multiple values""" - created_by_id: Optional[str] = field( + created_by_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdById"}, ) """User ID of the creator""" - has_domain_of_values: Optional[bool] = field( + has_domain_of_values: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasDomainOfValues"}, ) """Indicates if custom property has possible values""" - hint: Optional[str] = None + hint: Optional[str] = dataclass_field(default=None, kw_only=True) """ Value that describes the hint displayed under the custom property name """ - id: Optional[str] = None - is_required: Optional[bool] = field( + id: Optional[str] = dataclass_field(default=None, kw_only=True) + is_required: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isRequired"}, ) """Indicates whether the custom property is required or not""" - last_modified_by_id: Optional[str] = field( + last_modified_by_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedById"}, ) """User ID of the user that last updated the custom property""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of custom property""" - operation_setting: Optional[str] = field( + operation_setting: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "operationSetting"}, ) """ Object that describes settings for different operations on a custom property """ - order: Optional[int] = None + order: Optional[int] = dataclass_field(default=None, kw_only=True) """Number indicating order within custom property list""" - possible_values: Optional[List[PossibleValuesItem]] = field( + possible_values: Optional[List[PossibleValuesItem | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "possibleValues"}, ) """List of possible values for the custom property (if applicable)""" - scope_settings: Optional[List[ScopeSettingsItemDefinition]] = field( + scope_settings: Optional[ + List[ScopeSettingsItemDefinition | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "scopeSettings"}, ) """ Object that describes settings for different scopes on a custom property """ - scopes: Optional[List[str]] = None + scopes: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """List of scopes""" - value_schema_name: Optional[str] = field( + value_schema_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "valueSchemaName"}, ) """Name of custom property value schema""" - value_schema_property: Optional[ValueSchemaPropertyDefinition] = field( + value_schema_property: Optional[ + ValueSchemaPropertyDefinition | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "valueSchemaProperty"}, ) - value_type: Optional[str] = field( + value_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "valueType"}, ) """Type of custom property value""" @@ -970,7 +1249,7 @@ class CustomPropertyDataDisplay: Definition: CustomPropertyDataDisplay """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of custom property""" @@ -980,17 +1259,28 @@ class CustomPropertyValues: Definition: CustomPropertyValues """ - id: Optional[str] = None - localizations: Optional[Dict[str, CustomPropertyDataDisplay]] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + localizations: Optional[ + Dict[str, CustomPropertyDataDisplay | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Localization object""" - multiple_value: Optional[bool] = field( + multiple_value: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "multipleValue"}, ) """Indicate if the custom property allows multiple values""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of custom property""" - values: Optional[List[CustomPropertyValuesValues]] = None + values: Optional[ + List[CustomPropertyValuesValues | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of custom property values""" @@ -1000,8 +1290,13 @@ class CustomPropertyValuesInput: Definition: CustomPropertyValuesInput """ - id: Optional[str] = None - values: Optional[List[CustomPropertyValuesValues]] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + values: Optional[ + List[CustomPropertyValuesValues | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of custom property values""" @@ -1011,8 +1306,8 @@ class CustomPropertyValuesValues: Definition: CustomPropertyValuesValues """ - id: Optional[str] = None - value: Optional[Any] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + value: Optional[Any] = dataclass_field(default=None, kw_only=True) """Value data for custom property value""" @@ -1022,7 +1317,7 @@ class DeleteRequest: Definition: DeleteRequest """ - ids: Optional[List[str]] = None + ids: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """List of Request IDs to delete""" @@ -1032,9 +1327,13 @@ class Follower: Definition: Follower """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """User/User group ID of follower""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Either user or user group follower type""" @@ -1044,9 +1343,14 @@ class Meta: Definition: Meta """ - count: Optional[int] = None + count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of records returned""" - query: Optional[List[MetaQueryInfo]] = None + query: Optional[ + List[MetaQueryInfo | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Query object""" @@ -1056,7 +1360,7 @@ class MetaQueryInfo: Definition: MetaQueryInfo """ - sort: Optional[List[str]] = None + sort: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Sort query""" @@ -1066,126 +1370,164 @@ class PlannerSubTask: Definition: PlannerSubTask """ - actual_duration: Optional[int] = field( + actual_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "actualDuration"}, ) """Calculated actual duration in days""" - actual_end_date: Optional[str] = field( + actual_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "actualEndDate"}, ) """Date when work on the task was completed""" - actual_start_date: Optional[str] = field( + actual_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "actualStartDate"}, ) """Date when work on the task started""" - assignee_id: Optional[str] = field( + assignee_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assigneeId"}, ) """User ID of assignee""" - assigner_id: Optional[str] = field( + assigner_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignerId"}, ) """User ID of the last user to add an assignee""" - associations: Optional[List[Association]] = None + associations: Optional[ + List[Association | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of associations on a task""" - copy_from: Optional[str] = field( + copy_from: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "copyFrom"}, ) """Task ID that task was copied from""" - created_at: Optional[str] = field( + created_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdAt"}, ) """Date the task was created""" - creator_id: Optional[str] = field( + creator_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "creatorId"}, ) """User ID of creator""" - custom_properties: Optional[List[CustomPropertyValues]] = field( + custom_properties: Optional[ + List[CustomPropertyValues | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customProperties"}, ) """List of custom properties on a task""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of task""" - followers: Optional[List[Follower]] = None + followers: Optional[ + List[Follower | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of followers on a task""" - id: Optional[str] = None - is_template: Optional[bool] = field( + id: Optional[str] = dataclass_field(default=None, kw_only=True) + is_template: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isTemplate"}, ) """Indicates if a task is part of a template""" - max_rank: Optional[str] = field( + max_rank: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "maxRank"}, ) """Maximum rank""" - min_rank: Optional[str] = field( + min_rank: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "minRank"}, ) """Minimum rank""" - parent_id: Optional[str] = field( + parent_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentId"}, ) """Task ID of parent if task is a subtask""" - planned_duration: Optional[int] = field( + planned_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedDuration"}, ) """Planned duration in days""" - planned_end_date: Optional[str] = field( + planned_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedEndDate"}, ) """Date string of end date (due date)""" - planned_start_date: Optional[str] = field( + planned_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedStartDate"}, ) """Date string of start date""" - priority: Optional[str] = None + priority: Optional[str] = dataclass_field(default=None, kw_only=True) """Priority value""" - project_id: Optional[str] = field( + project_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "projectId"}, ) """Project ID the task belongs to""" - rank: Optional[str] = None + rank: Optional[str] = dataclass_field(default=None, kw_only=True) """Rank of task in a task list""" - space_id: Optional[str] = field( + space_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "spaceId"}, ) - status_schema_id: Optional[str] = field( + status_schema_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "statusSchemaId"}, ) - step_id: Optional[int] = field( + step_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "stepId"}, ) """Id of step in status schema""" - template_id: Optional[str] = field( + template_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "templateId"}, ) """Template ID of the template the task belongs to""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of task""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type of task""" - updated_at: Optional[str] = field( + updated_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "updatedAt"}, ) """Date the task was last updated""" @@ -1197,10 +1539,10 @@ class PossibleValuesItem: Definition: PossibleValuesItem """ - id: Optional[str] = None - order: Optional[int] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + order: Optional[int] = dataclass_field(default=None, kw_only=True) """Number to indicate order""" - value: Optional[Any] = None + value: Optional[Any] = dataclass_field(default=None, kw_only=True) """Actual value data""" @@ -1210,11 +1552,15 @@ class ProblemDetails: Definition: ProblemDetails """ - detail: Optional[str] = None - instance: Optional[str] = None - status: Optional[int] = None - title: Optional[str] = None - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + detail: Optional[str] = dataclass_field(default=None, kw_only=True) + instance: Optional[str] = dataclass_field(default=None, kw_only=True) + status: Optional[int] = dataclass_field(default=None, kw_only=True) + title: Optional[str] = dataclass_field(default=None, kw_only=True) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) @dataclass @@ -1223,17 +1569,20 @@ class ProjectAssociatedNodes: Definition: ProjectAssociatedNodes """ - node_id: Optional[str] = field( + node_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nodeId"}, ) - node_type: Optional[str] = field( + node_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nodeType"}, ) """Node type of the association""" - space_id: Optional[str] = field( + space_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "spaceId"}, ) @@ -1244,13 +1593,15 @@ class RequestFormCustomProperties: Definition: RequestFormCustomProperties """ - created_at: Optional[str] = field( + created_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdAt"}, ) """Date string of created date""" - custom_properties: Optional[List[CustomProperty]] = field( + custom_properties: Optional[List[CustomProperty | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customProperties"}, ) """List of custom properties""" @@ -1262,12 +1613,13 @@ class ScopeSettingsItemDefinition: Definition: ScopeSettingsItemDefinition """ - is_required: Optional[bool] = field( + is_required: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isRequired"}, ) """Indicator on whether a field is required or not""" - scope: Optional[str] = None + scope: Optional[str] = dataclass_field(default=None, kw_only=True) """ Type list of node types that the custom property definition belongs to """ @@ -1279,21 +1631,25 @@ class UpdateCommentModel: Definition: UpdateCommentModel """ - annotation_payload: Optional[str] = field( + annotation_payload: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "annotationPayload"}, ) - annotation_type: Optional[str] = field( + annotation_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "annotationType"}, ) - comment_content: Optional[str] = field( + comment_content: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "commentContent"}, ) """Content of the comment""" - is_resolved: Optional[bool] = field( + is_resolved: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isResolved"}, ) """True/false on whether the comment is resolved""" @@ -1305,49 +1661,59 @@ class UpdateProject: Definition: UpdateProject """ - custom_properties: Optional[List[CustomPropertyValues]] = field( + custom_properties: Optional[ + List[CustomPropertyValues | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customProperties"}, ) """List of custom properties""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of project""" - is_active: Optional[bool] = field( + is_active: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isActive"}, ) """Indicator on whether a project is active?""" - manager_id: Optional[str] = field( + manager_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerId"}, ) """User ID of project manager""" - max_rank: Optional[str] = field( + max_rank: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "maxRank"}, ) """Maximum rank number""" - min_rank: Optional[str] = field( + min_rank: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "minRank"}, ) """Minimum rank number""" - planned_duration: Optional[int] = field( + planned_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedDuration"}, ) """Planned duration in days""" - planned_end_date: Optional[str] = field( + planned_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedEndDate"}, ) """Date string of planned end date""" - planned_start_date: Optional[str] = field( + planned_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedStartDate"}, ) """Date string of planned start date""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of project""" @@ -1357,56 +1723,67 @@ class UpdateRequest: Definition: UpdateRequest """ - assignee_id: Optional[str] = field( + assignee_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assigneeId"}, ) """User ID of the assignee""" - content_refs: Optional[List[ContentRef]] = field( + content_refs: Optional[List[ContentRef | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentRefs"}, ) """List of content references (WorkSpace and DocCenter content)""" - custom_properties: Optional[List[CustomPropertyValuesInput]] = field( + custom_properties: Optional[ + List[CustomPropertyValuesInput | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customProperties"}, ) """List of custom properties""" - form_ref: Optional[Any] = field( + form_ref: Optional[Any] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "formRef"}, ) """Form reference object""" - note: Optional[str] = None + note: Optional[str] = dataclass_field(default=None, kw_only=True) """Note used for notifications on status changes""" - planned_duration: Optional[int] = field( + planned_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedDuration"}, ) """Planned duration in days""" - planned_end_date: Optional[str] = field( + planned_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedEndDate"}, ) """Date string of planned end date (due date)""" - planned_start_date: Optional[str] = field( + planned_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedStartDate"}, ) """Date string of planned start date""" - priority: Optional[str] = None + priority: Optional[str] = dataclass_field(default=None, kw_only=True) """Priority value""" - project_id: Optional[str] = field( + project_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "projectId"}, ) """Project ID of the project the request belongs to""" - step_id: Optional[int] = field( + step_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "stepId"}, ) """Step ID indicating status""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of the request""" @@ -1416,51 +1793,61 @@ class UpdateTask: Definition: UpdateTask """ - assignee_id: Optional[str] = field( + assignee_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assigneeId"}, ) """User ID of the assignee""" - custom_properties: Optional[List[CustomPropertyValuesInput]] = field( + custom_properties: Optional[ + List[CustomPropertyValuesInput | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "customProperties"}, ) """List of custom properties""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of task""" - parent_id: Optional[str] = field( + parent_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentId"}, ) """Task ID of parent task""" - planned_duration: Optional[int] = field( + planned_duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedDuration"}, ) """Planned duration in days""" - planned_end_date: Optional[str] = field( + planned_end_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedEndDate"}, ) """Date string of planned end date""" - planned_start_date: Optional[str] = field( + planned_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "plannedStartDate"}, ) """Date string of planned start date""" - priority: Optional[str] = None + priority: Optional[str] = dataclass_field(default=None, kw_only=True) """Priority value""" - project_id: Optional[str] = field( + project_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "projectId"}, ) """Project ID that the task belongs to""" - step_id: Optional[int] = field( + step_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "stepId"}, ) """Step ID indicating the task status""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of task""" @@ -1470,8 +1857,8 @@ class ValueSchemaPropertyDefinition: Definition: ValueSchemaPropertyDefinition """ - max: Optional[str] = None - min: Optional[str] = None + max: Optional[str] = dataclass_field(default=None, kw_only=True) + min: Optional[str] = dataclass_field(default=None, kw_only=True) # Client Class @@ -1482,16 +1869,16 @@ class SeismicplannerClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -1502,8 +1889,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -1511,8 +1898,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -1524,7 +1911,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -1539,25 +1926,88 @@ def __init__( def connector_name(self) -> str: return "seismicplanner" - async def get_comments_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_comments( self, space_id: str, node_id: str, + *, creator_ids: Optional[List[str]] = None, cursor: Optional[str] = None, limit: Optional[int] = None, sort: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get comments Get all comments for a given project, task, or request. Requires node (project, task, or request) ID. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetComments`. + + Args: + space_id: Space ID. + node_id: Node ID. + creator_ids: List of user IDs to query by creator. + cursor: Cursor used for pagination. + limit: Number to limit records. + sort: Sort by query. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1613,31 +2063,52 @@ async def get_comments_async( query_params.append(f"sort={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def create_comment_async( + def create_comment( self, - input: CreateCommentModel, + input: CreateCommentModel | Mapping[str, Any], space_id: str, node_id: str, *, @@ -1651,6 +2122,24 @@ async def create_comment_async( Create a comment on a given project, task, or request. Requires node (project, task, or request) ID. + + Swagger operation ID: `CreateComment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + node_id: Node ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1663,7 +2152,7 @@ async def create_comment_async( f"/comments" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1677,6 +2166,7 @@ async def create_comment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1684,7 +2174,7 @@ async def create_comment_async( return json.loads(response.text) - async def get_comment_async( + def get_comment( self, space_id: str, node_id: str, @@ -1700,6 +2190,23 @@ async def get_comment_async( Get a single comment. Requires node (project, task, or request) and comment ID. + + Swagger operation ID: `GetComment`. + + Args: + space_id: Space ID. + node_id: Node ID. + comment_id: Comment ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1713,7 +2220,7 @@ async def get_comment_async( f"/{quote(str(comment_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1727,6 +2234,7 @@ async def get_comment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1734,7 +2242,7 @@ async def get_comment_async( return json.loads(response.text) - async def delete_comment_async( + def delete_comment( self, space_id: str, node_id: str, @@ -1750,6 +2258,23 @@ async def delete_comment_async( Delete a comment. Requires node (project, task, or request) and comment ID. + + Swagger operation ID: `DeleteComment`. + + Args: + space_id: Space ID. + node_id: Node ID. + comment_id: Comment ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1763,7 +2288,7 @@ async def delete_comment_async( f"/{quote(str(comment_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1777,11 +2302,12 @@ async def delete_comment_async( request_url, response.status, response.text, + response=response, ) - async def update_comment_async( + def update_comment( self, - input: UpdateCommentModel, + input: UpdateCommentModel | Mapping[str, Any], space_id: str, node_id: str, comment_id: str, @@ -1796,6 +2322,25 @@ async def update_comment_async( Update an existing comment. Requires node (project, task, or request) and comment ID. + + Swagger operation ID: `UpdateComment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + node_id: Node ID. + comment_id: Comment ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1809,7 +2354,7 @@ async def update_comment_async( f"/{quote(str(comment_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1823,6 +2368,7 @@ async def update_comment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1830,9 +2376,10 @@ async def update_comment_async( return json.loads(response.text) - async def get_projects_async( + def list_projects( self, space_id: str, + *, planned_end_date_from: Optional[str] = None, planned_end_date_to: Optional[str] = None, planned_start_date_from: Optional[str] = None, @@ -1848,16 +2395,50 @@ async def get_projects_async( custom_properties: Optional[str] = None, follower_ids: Optional[List[str]] = None, include_associations: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get projects Get a list of projects with their attributes and associations. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetProjects`. + + Args: + space_id: Space ID. + planned_end_date_from: Filter from a planned end date. + planned_end_date_to: Filter to a planned end date. + planned_start_date_from: Filter from a planned start date. + planned_start_date_to: Filter to a planned start date. + ids: List of project IDs to query by. + title: Project title to query by. + manager_ids: List of user IDs to query by manager. + creator_ids: List of user IDs to query by creator. + associated_node_ids: List of association IDs to query by. + cursor: Cursor used for pagination. + limit: Number to limit records returned. + sort: Sort query. + custom_properties: List of custom properties to query by. + follower_ids: List of user IDs to query by follower. + include_associations: Indicator to allow for inclusion of + association data. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2002,34 +2583,55 @@ async def get_projects_async( query_params.append(f"includeAssociations={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() - async def delete_projects_async( + return ItemPaged(get_next, extract_data) + + def delete_projects( self, space_id: str, ids: List[str], - delete_tasks: Optional[bool] = None, *, + delete_tasks: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2039,6 +2641,23 @@ async def delete_projects_async( Delete projects Delete one or more projects. + + Swagger operation ID: `DeleteProjects`. + + Args: + space_id: Space ID. + ids: List of project IDs. + delete_tasks: Also delete associated tasks. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2068,7 +2687,7 @@ async def delete_projects_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2082,6 +2701,7 @@ async def delete_projects_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2089,9 +2709,9 @@ async def delete_projects_async( return json.loads(response.text) - async def create_project_async( + def create_project( self, - input: CreateProject, + input: CreateProject | Mapping[str, Any], space_id: str, *, timeout: Optional[float] = None, @@ -2103,13 +2723,30 @@ async def create_project_async( Create project Create a project. + + Swagger operation ID: `CreateProject`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/planner/v2/spaces/{quote(str(space_id), safe='')}/projects" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2123,6 +2760,7 @@ async def create_project_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2130,13 +2768,13 @@ async def create_project_async( return json.loads(response.text) - async def get_project_async( + def get_project( self, space_id: str, project_id: str, + *, associated_nodes_depth: Optional[int] = None, include_works: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2146,6 +2784,25 @@ async def get_project_async( Get project Get a single project by ID. Return tasks if desired. + + Swagger operation ID: `GetProject`. + + Args: + space_id: Space ID. + project_id: Project ID. + associated_nodes_depth: Number to indicate depth of associated node + data returned. + include_works: Indicator to include associated tasks data. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2170,7 +2827,7 @@ async def get_project_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2184,6 +2841,7 @@ async def get_project_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2191,12 +2849,12 @@ async def get_project_async( return json.loads(response.text) - async def delete_project_async( + def delete_project( self, space_id: str, project_id: str, - delete_tasks: Optional[bool] = None, *, + delete_tasks: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2206,6 +2864,23 @@ async def delete_project_async( Delete project Delete a project. + + Swagger operation ID: `DeleteProject`. + + Args: + space_id: Space ID. + project_id: Project ID. + delete_tasks: Also delete associated tasks. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2225,7 +2900,7 @@ async def delete_project_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2239,6 +2914,7 @@ async def delete_project_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2246,9 +2922,9 @@ async def delete_project_async( return json.loads(response.text) - async def update_project_async( + def update_project( self, - input: UpdateProject, + input: UpdateProject | Mapping[str, Any], space_id: str, project_id: str, *, @@ -2261,6 +2937,24 @@ async def update_project_async( Update a project Update and return a project. + + Swagger operation ID: `UpdateProject`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + project_id: Project ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2272,7 +2966,7 @@ async def update_project_async( f"/{quote(str(project_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -2286,6 +2980,7 @@ async def update_project_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2293,9 +2988,10 @@ async def update_project_async( return json.loads(response.text) - async def get_requests_async( + def list_requests( self, space_id: str, + *, planned_end_date_from: Optional[str] = None, planned_end_date_to: Optional[str] = None, planned_start_date_from: Optional[str] = None, @@ -2323,16 +3019,63 @@ async def get_requests_async( associated_node_ids: Optional[List[str]] = None, content_refs: Optional[List[str]] = None, include_request_form_custom_properties: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get requests Get a list of requests. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetRequests`. + + Args: + space_id: Space ID. + planned_end_date_from: filter by request due date (inclusive). + planned_end_date_to: filter by request due date (exclusive). + planned_start_date_from: filter by request start date (inclusive). + planned_start_date_to: filter by request start date (exclusive). + created_at_from: filter by request created date (inclusive). + created_at_to: filter by request created date (exclusive). + updated_at_from: filter by request updated date (inclusive). + updated_at_to: filter by request updated date (exclusive). + ids: A list of request IDs. + title: Keyword values to search for on request titles. + assignee_ids: A list of assignees' user IDs to filter by. + priorities: A list of priority values, Available values : critical, + high, medium, low. + keywords: Keyword values to search. + assigner_ids: A list of assigner' user Ids to filter by. + creator_ids: A list of creators' user IDs to filter by. + step_ids: A list of step IDs to filter by. + status_schema_id: Status schema ID to filter by. + cursor: A token used to guide the next page window. + limit: Number of items to return per page, default: 50. + sort: Sort by requests. + project_id: The project ID a request is associated to. + has_project: Filter by if requests are associated with a project. + custom_properties: Filter by custom properties. + follower_ids: A list of followers' user id. + associated_node_ids: A list of Associated node IDs to filter by. + content_refs: List of content reference objects. + include_request_form_custom_properties: whether to include request + form custom properties, default false. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2577,31 +3320,52 @@ async def get_requests_async( query_params.append(f"includeRequestFormCustomProperties={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() - async def delete_requests_async( + return ItemPaged(get_next, extract_data) + + def delete_requests( self, - input: DeleteRequest, + input: DeleteRequest | Mapping[str, Any], space_id: str, *, timeout: Optional[float] = None, @@ -2613,13 +3377,30 @@ async def delete_requests_async( Delete requests Bulk delete requests. + + Swagger operation ID: `DeleteRequests`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/planner/v2/spaces/{quote(str(space_id), safe='')}/requests" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=input, timeout=timeout, headers=headers, @@ -2633,6 +3414,7 @@ async def delete_requests_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2640,9 +3422,9 @@ async def delete_requests_async( return json.loads(response.text) - async def create_request_async( + def create_request( self, - input: CreateRequest, + input: CreateRequest | Mapping[str, Any], space_id: str, *, timeout: Optional[float] = None, @@ -2654,13 +3436,30 @@ async def create_request_async( Create request Create a request. + + Swagger operation ID: `CreateRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/planner/v2/spaces/{quote(str(space_id), safe='')}/requests" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2674,6 +3473,7 @@ async def create_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2681,7 +3481,7 @@ async def create_request_async( return json.loads(response.text) - async def get_request_async( + def get_request( self, space_id: str, request_id: str, @@ -2695,6 +3495,22 @@ async def get_request_async( Get request Get a single request. + + Swagger operation ID: `GetRequest`. + + Args: + space_id: Space ID. + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2706,7 +3522,7 @@ async def get_request_async( f"/{quote(str(request_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2720,6 +3536,7 @@ async def get_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2727,7 +3544,7 @@ async def get_request_async( return json.loads(response.text) - async def delete_request_async( + def delete_request( self, space_id: str, request_id: str, @@ -2741,6 +3558,22 @@ async def delete_request_async( Delete request Delete a request. + + Swagger operation ID: `DeleteRequest`. + + Args: + space_id: Space ID. + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2752,7 +3585,7 @@ async def delete_request_async( f"/{quote(str(request_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2766,11 +3599,12 @@ async def delete_request_async( request_url, response.status, response.text, + response=response, ) - async def update_request_async( + def update_request( self, - input: UpdateRequest, + input: UpdateRequest | Mapping[str, Any], space_id: str, request_id: str, *, @@ -2783,6 +3617,24 @@ async def update_request_async( Update request Update a request. + + Swagger operation ID: `UpdateRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2794,7 +3646,7 @@ async def update_request_async( f"/{quote(str(request_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -2808,6 +3660,7 @@ async def update_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2815,27 +3668,52 @@ async def update_request_async( return json.loads(response.text) - async def get_status_schemas_async( + def list_status_schemas( self, space_id: str, + *, is_default: Optional[bool] = None, type_: Optional[str] = None, ids: Optional[List[str]] = None, creator_ids: Optional[List[str]] = None, cursor: Optional[str] = None, limit: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get status schemas Get a list of task/request status schemas. These schemas hold the data for set statuses for specific work. Example: `(Not started, In progress, Complete)` + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetStatusSchemas`. + + Args: + space_id: Space ID. + is_default: Get default status schema. + type_: Query by node type. + ids: List of status schemas IDs. + creator_ids: List of user IDs to query by creator. + cursor: Cursor used for pagination. + limit: Number to limit returned records. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2895,29 +3773,50 @@ async def get_status_schemas_async( query_params.append(f"limit={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() - async def get_status_schema_async( + return ItemPaged(get_next, extract_data) + + def get_status_schema( self, space_id: str, status_schema_id: str, @@ -2933,6 +3832,22 @@ async def get_status_schema_async( Get a single status schema by ID. These schemas hold the data for set statuses for specific work. Example: `(Not started, In progress, Complete)` + + Swagger operation ID: `GetStatusSchema`. + + Args: + space_id: Space ID. + status_schema_id: Status schema ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2944,7 +3859,7 @@ async def get_status_schema_async( f"/{quote(str(status_schema_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2958,6 +3873,7 @@ async def get_status_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2965,9 +3881,10 @@ async def get_status_schema_async( return json.loads(response.text) - async def get_tasks_async( + def list_tasks( self, space_id: str, + *, planned_end_date_from: Optional[str] = None, planned_end_date_to: Optional[str] = None, planned_start_date_from: Optional[str] = None, @@ -2997,16 +3914,64 @@ async def get_tasks_async( creator_ids: Optional[List[str]] = None, include_associations: Optional[bool] = None, parent_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get tasks Get a list of tasks. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTasks`. + + Args: + space_id: Space ID. + planned_end_date_from: Filter by task due date (inclusive). + planned_end_date_to: Filter by task due date (exclusive). + planned_start_date_from: Filter by task start date (inclusive). + planned_start_date_to: Filter by task start date (exclusive). + created_at_from: Filter by task created date (inclusive). + created_at_to: Filter by task created date (exclusive). + updated_at_from: Filter by task updated date (inclusive). + updated_at_to: Filter by task updated date (exclusive). + ids: Filter by a list of task IDs. + title: Filter by task title. + description: Filter by task description. + assignee_ids: List of user IDs to filter by assignee. + priorities: Filter by list of priorities. + keywords: Filter by keywords. + assigner_ids: List of user IDs to filter by user that assigned the + task. + step_ids: Filter by status value IDs. + status_schema_id: Filter by status schema IDs. + cursor: Cursor used for pagination. + limit: Number to limit returned records. + sort: Sort by query. + recursive: Include subtasks within the returned list. + project_id: Filter by project ID. + has_project: Filter by tasks that are associated with a project. + custom_properties: Filter by custom property values. + follower_ids: List of user IDs to filter by followers. + associated_node_ids: List of association IDs to filter by. + creator_ids: List of user IDs to filter by creator. + include_associations: Include association data in the response. + parent_id: List of task IDs to filter by. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3251,31 +4216,52 @@ async def get_tasks_async( query_params.append(f"parentId={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() - async def create_task_async( + return ItemPaged(get_next, extract_data) + + def create_task( self, - input: CreateTask, + input: CreateTask | Mapping[str, Any], space_id: str, *, timeout: Optional[float] = None, @@ -3287,13 +4273,30 @@ async def create_task_async( Create task Create a task. + + Swagger operation ID: `CreateTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/planner/v2/spaces/{quote(str(space_id), safe='')}/tasks" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3307,6 +4310,7 @@ async def create_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3314,7 +4318,7 @@ async def create_task_async( return json.loads(response.text) - async def get_task_async( + def get_task( self, space_id: str, task_id: str, @@ -3328,6 +4332,22 @@ async def get_task_async( Get task Get a single task by ID. + + Swagger operation ID: `GetTask`. + + Args: + space_id: Space ID. + task_id: Task ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3339,7 +4359,7 @@ async def get_task_async( f"/{quote(str(task_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3353,6 +4373,7 @@ async def get_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3360,7 +4381,7 @@ async def get_task_async( return json.loads(response.text) - async def delete_task_async( + def delete_task( self, space_id: str, task_id: str, @@ -3374,6 +4395,22 @@ async def delete_task_async( Delete task Delete a task. + + Swagger operation ID: `DeleteTask`. + + Args: + space_id: Space ID. + task_id: Task ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3385,7 +4422,7 @@ async def delete_task_async( f"/{quote(str(task_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -3399,6 +4436,7 @@ async def delete_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3406,9 +4444,9 @@ async def delete_task_async( return json.loads(response.text) - async def update_task_async( + def update_task( self, - input: UpdateTask, + input: UpdateTask | Mapping[str, Any], space_id: str, task_id: str, *, @@ -3421,6 +4459,24 @@ async def update_task_async( Update task Update an existing task. + + Swagger operation ID: `UpdateTask`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + space_id: Space ID. + task_id: Task ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3432,7 +4488,7 @@ async def update_task_async( f"/{quote(str(task_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -3446,6 +4502,7 @@ async def update_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/sendgrid.py b/src/azure/connectors/sendgrid.py index 29b27d3..dcf5c7d 100644 --- a/src/azure/connectors/sendgrid.py +++ b/src/azure/connectors/sendgrid.py @@ -5,21 +5,41 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "SendgridClient", + "AddGlobalSuppressRequestAndResponse", + "Bounce", + "Bounces", + "EmailAttachment", + "EmailIsUnsubscribedResponse", + "EmailRequest", + "EmailResponse", + "GetGlobalSuppressEmptyResponse", + "GetGlobalSuppressResponse", + "ObjectEntity", + "Recipient", + "RecipientList", + "RecipientLists", + "Recipients", + "ScopeList", +] + # Type Definitions @@ -29,7 +49,7 @@ class AddGlobalSuppressRequestAndResponse: Response for Add a global suppression """ - recipient_emails: Optional[List[str]] = None + recipient_emails: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Recipient email""" @@ -39,7 +59,7 @@ class GetGlobalSuppressResponse: Response for Get the global suppression """ - recipient_email: Optional[str] = None + recipient_email: Optional[str] = dataclass_field(default=None, kw_only=True) """Recipient email""" @@ -49,14 +69,14 @@ class ObjectEntity: Response for Add recipient to list """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) """ -Bounces = List["Bounce"] +Bounces = List["Bounce | Mapping[str, Any]"] @dataclass @@ -65,8 +85,9 @@ class EmailIsUnsubscribedResponse: Response for Check if email is in unsubscribed email list """ - is_unsubscribed: Optional[bool] = field( + is_unsubscribed: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isUnsubscribed"}, ) """Is Email Unsubscribed""" @@ -78,7 +99,12 @@ class RecipientLists: Response for List Recipient Lists """ - lists: Optional[List[RecipientList]] = None + lists: Optional[ + List[RecipientList | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of recipient lists""" @@ -88,7 +114,12 @@ class Recipients: Response for List Recipients """ - recipients: Optional[List[Recipient]] = None + recipients: Optional[ + List[Recipient | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of recipients""" @@ -98,7 +129,7 @@ class EmailResponse: Definition: EmailResponse """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """Status message from send email response""" @@ -108,7 +139,7 @@ class GetGlobalSuppressEmptyResponse: Definition: GetGlobalSuppressEmptyResponse """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -121,36 +152,41 @@ class EmailRequest: Definition: EmailRequest """ - attachments: Optional[List[EmailAttachment]] = None + attachments: Optional[ + List[EmailAttachment | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Attachments""" - from_: Optional[str] = field(default=None, metadata={"wire_name": "from"}) + from_: str = dataclass_field(metadata={"wire_name": "from"}) """ Origination address of your email. Must be a valid email address from your domain """ - fromname: Optional[str] = None + fromname: Optional[str] = dataclass_field(default=None, kw_only=True) """Origination name of your email""" - to: Optional[str] = None + to: str """Valid email addresses separated by a semicolon or comma""" - toname: Optional[str] = None + toname: Optional[str] = dataclass_field(default=None, kw_only=True) """ A display name for each email address separated by a semicolon or comma """ - subject: Optional[str] = None + subject: str """Subject of your email""" - text: Optional[str] = None + text: str """Content of your email""" - ishtml: Optional[bool] = None + ishtml: bool """Specify whether the content of the email is HTML or plain text""" - cc: Optional[str] = None + cc: Optional[str] = dataclass_field(default=None, kw_only=True) """Valid email addresses separated by a semicolon or comma""" - ccname: Optional[str] = None + ccname: Optional[str] = dataclass_field(default=None, kw_only=True) """ A display name for each CC email address separated by a semicolon or comma """ - bcc: Optional[str] = None + bcc: Optional[str] = dataclass_field(default=None, kw_only=True) """Valid email addresses separated by a semicolon or comma""" - bccname: Optional[str] = None + bccname: Optional[str] = dataclass_field(default=None, kw_only=True) """ A display name for each BCC email address separated by a semicolon or comma """ @@ -162,11 +198,11 @@ class EmailAttachment: Definition: EmailAttachment """ - content: Optional[str] = None + content: Optional[str] = dataclass_field(default=None, kw_only=True) """Attachment file content""" - filename: Optional[str] = None + filename: Optional[str] = dataclass_field(default=None, kw_only=True) """Attachment file name""" - contenttype: Optional[str] = None + contenttype: Optional[str] = dataclass_field(default=None, kw_only=True) """Type of content in the attachment.""" @@ -176,11 +212,11 @@ class RecipientList: Definition: RecipientList """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique list id""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name""" - recipient_count: Optional[int] = None + recipient_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Recipient count""" @@ -190,13 +226,13 @@ class Recipient: Definition: Recipient """ - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address""" - last_name: Optional[str] = None + last_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Last name""" - first_name: Optional[str] = None + first_name: Optional[str] = dataclass_field(default=None, kw_only=True) """First name""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique recipient id""" @@ -206,7 +242,7 @@ class ScopeList: Definition: ScopeList """ - scopes: Optional[List[str]] = None + scopes: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """List of scopes""" @@ -216,13 +252,13 @@ class Bounce: Definition: Bounce """ - created: Optional[int] = None + created: Optional[int] = dataclass_field(default=None, kw_only=True) """Created""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email""" - reason: Optional[str] = None + reason: Optional[str] = dataclass_field(default=None, kw_only=True) """Reason""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status""" @@ -234,16 +270,16 @@ class SendgridClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -254,8 +290,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -263,8 +299,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -276,7 +312,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -291,9 +327,48 @@ def __init__( def connector_name(self) -> str: return "sendgrid" - async def add_global_suppression_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def add_global_suppression( self, - input: AddGlobalSuppressRequestAndResponse, + input: AddGlobalSuppressRequestAndResponse | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -304,10 +379,26 @@ async def add_global_suppression_async( Add a global suppression Add a global suppression + + Swagger operation ID: `AddGlobalSuppression`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/suppressions/global" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -321,6 +412,7 @@ async def add_global_suppression_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -328,7 +420,7 @@ async def add_global_suppression_async( return json.loads(response.text) - async def get_global_suppression_async( + def get_global_suppression( self, email: str, *, @@ -341,13 +433,28 @@ async def get_global_suppression_async( Get the global suppression Get the global suppression + + Swagger operation ID: `GetGlobalSuppression`. + + Args: + email: The email to check. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/suppressions/global/{quote(str(email), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -361,6 +468,7 @@ async def get_global_suppression_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -368,7 +476,7 @@ async def get_global_suppression_async( return json.loads(response.text) - async def delete_global_suppression_async( + def delete_global_suppression( self, email: str, *, @@ -381,13 +489,28 @@ async def delete_global_suppression_async( Delete the global suppression Delete the global suppression + + Swagger operation ID: `DeleteGlobalSuppression`. + + Args: + email: The email to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/suppressions/global/{quote(str(email), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -401,9 +524,10 @@ async def delete_global_suppression_async( request_url, response.status, response.text, + response=response, ) - async def add_recipient_to_list_async( + def add_recipient_to_list( self, list_id: str, recipient_id: str, @@ -417,6 +541,22 @@ async def add_recipient_to_list_async( Add recipient to list Add an individual recipient to a recipient list. + + Swagger operation ID: `AddRecipientToList`. + + Args: + list_id: Unique id of the recipient list. + recipient_id: Unique id of the recipient. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -428,7 +568,7 @@ async def add_recipient_to_list_async( f"/{quote(str(recipient_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -442,6 +582,7 @@ async def add_recipient_to_list_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -449,7 +590,7 @@ async def add_recipient_to_list_async( return json.loads(response.text) - async def get_bounce_async( + def list_bounce( self, email: str, *, @@ -457,39 +598,79 @@ async def get_bounce_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get bounce for an email Get a specific bounce for a given email address. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetBounce`. + + Args: + email: The email to check. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/suppression/bounces/{quote(str(email), safe='')}" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def delete_bounce_async( + def delete_bounce( self, email: str, *, @@ -502,13 +683,28 @@ async def delete_bounce_async( Delete an email from bounce list Delete an email address from your bounce list. + + Swagger operation ID: `DeleteBounce`. + + Args: + email: The email to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/suppression/bounces/{quote(str(email), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -522,9 +718,10 @@ async def delete_bounce_async( request_url, response.status, response.text, + response=response, ) - async def check_email_is_in_unsubscribes_list_async( + def check_email_is_in_unsubscribes_list( self, email: str, *, @@ -537,13 +734,28 @@ async def check_email_is_in_unsubscribes_list_async( Check if email is in unsubscribed email list Check if email is in unsubscribed email list. + + Swagger operation ID: `CheckEmailIsInUnsubscribesList`. + + Args: + email: The email to check. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/unsubscribes/{quote(str(email), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -557,6 +769,7 @@ async def check_email_is_in_unsubscribes_list_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -564,9 +777,9 @@ async def check_email_is_in_unsubscribes_list_async( return json.loads(response.text) - async def send_email_async( + def send_email( self, - input: EmailRequest, + input: EmailRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -577,10 +790,26 @@ async def send_email_async( Send email Sends an email (V4). Limited to 1000 recipients. + + Swagger operation ID: `SendEmailV4`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v4/mail/send" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -594,6 +823,7 @@ async def send_email_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -601,74 +831,152 @@ async def send_email_async( return json.loads(response.text) - async def list_recipient_lists_async( + def list_recipient_lists( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List Recipient Lists Retrieves all the recipient lists. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListRecipientLists`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v3/contactdb/lists" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("lists", []): + yield item + + return None, items() - async def list_recipients_async( + return ItemPaged(get_next, extract_data) + + def list_recipients( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List Recipients Retrieves all registered recipients. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListRecipients`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v3/contactdb/recipients" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("recipients", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/servicebus.py b/src/azure/connectors/servicebus.py index 9a3c3eb..be45ef4 100644 --- a/src/azure/connectors/servicebus.py +++ b/src/azure/connectors/servicebus.py @@ -5,25 +5,39 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "ServicebusClient", + "CreateTopicSubscriptionInput", + "ObjectEntity", + "SendMessagesInput", + "ServiceBusEntity", + "ServiceBusMessage", + "Subscription", + "SubscriptionCorrelationFilter", + "SubscriptionFilter", + "TRIGGER_OPERATIONS", +] + # Type Definitions -SendMessagesInput = List["ServiceBusMessage"] +SendMessagesInput = List["ServiceBusMessage | Mapping[str, Any]"] @dataclass @@ -32,70 +46,90 @@ class ServiceBusMessage: Response for When a message is received in a queue (auto-complete) """ - content_data: Optional[str] = field( + content_data: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentData"}, ) """Content of the message""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentType"}, ) """Content type of the message content""" - properties: Optional[Dict[str, str]] = field( + properties: Optional[Dict[str, str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Key-value pairs for each brokered property""" - message_id: Optional[str] = field( + message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageId"}, ) """ This is a user-defined value that Service Bus can use to identify duplicate messages, if enabled. """ - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "To"}, + ) """Send to address""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """Address of the queue to reply to""" - reply_to_session_id: Optional[str] = field( + reply_to_session_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyToSessionId"}, ) """Identifier of the session to reply to""" - label: Optional[str] = field(default=None, metadata={"wire_name": "Label"}) + label: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Label"}, + ) """Application specific label""" - scheduled_enqueue_time_utc: Optional[str] = field( + scheduled_enqueue_time_utc: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ScheduledEnqueueTimeUtc"}, ) """Date and time, in UTC, when the message will be added to the queue""" - session_id: Optional[str] = field( + session_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SessionId"}, ) """Identifier of the session""" - correlation_id: Optional[str] = field( + correlation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CorrelationId"}, ) """Identifier of the correlation""" - sequence_number: Optional[int] = field( + sequence_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SequenceNumber"}, ) """Identifier of the sequence number""" - lock_token: Optional[str] = field( + lock_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LockToken"}, ) """The lock token of the message as a string.""" - time_to_live: Optional[str] = field( + time_to_live: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TimeToLive"}, ) """ @@ -110,7 +144,7 @@ class CreateTopicSubscriptionInput: Create a topic subscription """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -123,8 +157,9 @@ class Subscription: Response for Create a topic subscription """ - subscription_name: Optional[str] = field( + subscription_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SubscriptionName"}, ) """Subscription name.""" @@ -136,10 +171,15 @@ class ServiceBusEntity: Response for Get all entities """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The entity name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name for the entity""" @@ -151,7 +191,7 @@ class ObjectEntity: Response for Get metadata of a filter """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -164,8 +204,11 @@ class SubscriptionFilter: Definition: SubscriptionFilter """ - correlation_filter: Optional[SubscriptionCorrelationFilter] = field( + correlation_filter: Optional[ + SubscriptionCorrelationFilter | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CorrelationFilter"}, ) @@ -176,45 +219,60 @@ class SubscriptionCorrelationFilter: Definition: SubscriptionCorrelationFilter """ - correlation_id: Optional[str] = field( + correlation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CorrelationId"}, ) """Identifier of the correlation""" - label: Optional[str] = field(default=None, metadata={"wire_name": "Label"}) + label: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Label"}, + ) """Application specific label""" - message_id: Optional[str] = field( + message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MessageId"}, ) """ This is a user-defined value that Service Bus can use to identify duplicate messages, if enabled. """ - properties: Optional[Dict[str, str]] = field( + properties: Optional[Dict[str, str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Properties"}, ) """Key-value pairs for each brokered property""" - reply_to: Optional[str] = field( + reply_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyTo"}, ) """Address of the queue to reply to""" - reply_to_session_id: Optional[str] = field( + reply_to_session_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReplyToSessionId"}, ) """Identifier of the session to reply to""" - session_id: Optional[str] = field( + session_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SessionId"}, ) """Identifier of the session""" - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "To"}, + ) """Send to address""" - content_type: Optional[str] = field( + content_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentType"}, ) """Content type of the message content""" @@ -228,16 +286,16 @@ class ServicebusClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -248,8 +306,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -257,8 +315,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -270,7 +328,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -285,12 +343,51 @@ def __init__( def connector_name(self) -> str: return "servicebus" - async def send_message_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def send_message( self, - input: ServiceBusMessage, + input: ServiceBusMessage | Mapping[str, Any], entity_name: str, - system_properties: Optional[str] = None, *, + system_properties: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -300,6 +397,26 @@ async def send_message_async( Send message This operation sends a message to a queue or topic. + + Swagger operation ID: `SendMessage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entity_name: Name of the queue or topic. + system_properties: System properties - None or Run Details. Run + Details will add run metadata property details as custom + properties in the message. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -314,7 +431,7 @@ async def send_message_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -328,14 +445,15 @@ async def send_message_async( request_url, response.status, response.text, + response=response, ) - async def send_messages_async( + def send_messages( self, input: SendMessagesInput, entity_name: str, - system_properties: Optional[str] = None, *, + system_properties: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -345,6 +463,25 @@ async def send_messages_async( Send one or more messages This operation sends one or more messages to a queue or topic. + + Swagger operation ID: `SendMessages`. + + Args: + input: The request body. + entity_name: Name of the queue or topic. + system_properties: System properties - None or Run Details. Run + Details will add run metadata property details as custom + properties in the message. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -361,7 +498,7 @@ async def send_messages_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -375,15 +512,16 @@ async def send_messages_async( request_url, response.status, response.text, + response=response, ) - async def complete_message_in_queue_async( + def complete_message_in_queue( self, queue_name: str, lock_token: str, + *, queue_type: Optional[str] = None, session_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -393,6 +531,24 @@ async def complete_message_in_queue_async( Complete the message in a queue The operation completes a message in a queue. + + Swagger operation ID: `CompleteMessageInQueue`. + + Args: + queue_name: Name of the queue. + lock_token: Lock token of the message to complete. + queue_type: Queue type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -418,7 +574,7 @@ async def complete_message_in_queue_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -432,15 +588,16 @@ async def complete_message_in_queue_async( request_url, response.status, response.text, + response=response, ) - async def abandon_message_in_queue_async( + def abandon_message_in_queue( self, queue_name: str, lock_token: str, + *, queue_type: Optional[str] = None, session_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -450,6 +607,24 @@ async def abandon_message_in_queue_async( Abandon the message in a queue The operation abandons a message in a queue. + + Swagger operation ID: `AbandonMessageInQueue`. + + Args: + queue_name: Name of the queue. + lock_token: Lock token of the message to abandon. + queue_type: Queue type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -475,7 +650,7 @@ async def abandon_message_in_queue_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -489,15 +664,16 @@ async def abandon_message_in_queue_async( request_url, response.status, response.text, + response=response, ) - async def get_deferred_message_from_queue_async( + def get_deferred_message_from_queue( self, queue_name: str, sequence_number: int, + *, queue_type: Optional[str] = None, session_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -507,6 +683,24 @@ async def get_deferred_message_from_queue_async( Get deferred message from a queue The operation gets a deferred message from a queue. + + Swagger operation ID: `GetDeferredMessageFromQueue`. + + Args: + queue_name: Name of the queue. + sequence_number: Sequence number of message. + queue_type: Queue type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -532,7 +726,7 @@ async def get_deferred_message_from_queue_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -546,6 +740,7 @@ async def get_deferred_message_from_queue_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -553,13 +748,13 @@ async def get_deferred_message_from_queue_async( return json.loads(response.text) - async def defer_message_in_queue_async( + def defer_message_in_queue( self, queue_name: str, lock_token: str, + *, queue_type: Optional[str] = None, session_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -569,6 +764,24 @@ async def defer_message_in_queue_async( Defer the message in a queue The operation defers a message in a queue. + + Swagger operation ID: `DeferMessageInQueue`. + + Args: + queue_name: Name of the queue. + lock_token: Lock token of the message to defer. + queue_type: Queue type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -594,7 +807,7 @@ async def defer_message_in_queue_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -608,16 +821,17 @@ async def defer_message_in_queue_async( request_url, response.status, response.text, + response=response, ) - async def dead_letter_message_in_queue_async( + def dead_letter_message_in_queue( self, queue_name: str, lock_token: str, + *, session_id: Optional[str] = None, dead_letter_reason: Optional[str] = None, dead_letter_error_description: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -627,6 +841,25 @@ async def dead_letter_message_in_queue_async( Dead-letter the message in a queue The operation moves the message to the Dead-Letter Queue. + + Swagger operation ID: `DeadLetterMessageInQueue`. + + Args: + queue_name: Name of the queue. + lock_token: Lock token of the message to dead-letter. + session_id: Session id. + dead_letter_reason: Dead letter reason. + dead_letter_error_description: Dead letter error description. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -657,7 +890,7 @@ async def dead_letter_message_in_queue_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -671,14 +904,15 @@ async def dead_letter_message_in_queue_async( request_url, response.status, response.text, + response=response, ) - async def renew_lock_on_message_in_queue_async( + def renew_lock_on_message_in_queue( self, queue_name: str, lock_token: str, - queue_type: Optional[str] = None, *, + queue_type: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -688,6 +922,23 @@ async def renew_lock_on_message_in_queue_async( Renew lock on the message in a queue The operation renews lock on a message in a queue. + + Swagger operation ID: `RenewLockOnMessageInQueue`. + + Args: + queue_name: Name of the queue. + lock_token: Lock token of the message to renew lock. + queue_type: Queue type - Main or DeadLetter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -708,7 +959,7 @@ async def renew_lock_on_message_in_queue_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -722,25 +973,49 @@ async def renew_lock_on_message_in_queue_async( request_url, response.status, response.text, + response=response, ) - async def get_messages_from_queue_with_peek_lock_async( + def list_messages_from_queue_with_peek_lock( self, queue_name: str, + *, max_message_count: Optional[int] = None, queue_type: Optional[str] = None, session_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get messages from a queue (peek-lock) The operation receives messages from a queue with peek-lock. If maximum message count is not provided, it reads 20 messages. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMessagesFromQueueWithPeekLock`. + + Args: + queue_name: Name of the queue. + max_message_count: The maximum number of messages to return in the + batch. + queue_type: Queue type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -767,29 +1042,50 @@ async def get_messages_from_queue_with_peek_lock_async( query_params.append(f"sessionId={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def close_session_in_queue_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def close_session_in_queue( self, queue_name: str, session_id: str, @@ -803,6 +1099,22 @@ async def close_session_in_queue_async( Close a session in a queue The operation closes a session in a queue. + + Swagger operation ID: `CloseSessionInQueue`. + + Args: + queue_name: Name of a queue. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -812,7 +1124,7 @@ async def close_session_in_queue_async( f"/close" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -826,9 +1138,10 @@ async def close_session_in_queue_async( request_url, response.status, response.text, + response=response, ) - async def renew_lock_on_session_in_queue_async( + def renew_lock_on_session_in_queue( self, queue_name: str, session_id: str, @@ -842,6 +1155,22 @@ async def renew_lock_on_session_in_queue_async( Renew lock on the session in a queue The operation renews a session in a queue. + + Swagger operation ID: `RenewLockOnSessionInQueue`. + + Args: + queue_name: Name of the queue. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -851,7 +1180,7 @@ async def renew_lock_on_session_in_queue_async( f"/renewlock" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -865,16 +1194,17 @@ async def renew_lock_on_session_in_queue_async( request_url, response.status, response.text, + response=response, ) - async def complete_message_in_topic_async( + def complete_message_in_topic( self, topic_name: str, subscription_name: str, lock_token: str, + *, subscription_type: Optional[str] = None, session_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -884,6 +1214,25 @@ async def complete_message_in_topic_async( Complete the message in a topic subscription The operation completes a message in a topic subscription. + + Swagger operation ID: `CompleteMessageInTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + lock_token: Lock token of the message to complete. + subscription_type: Subscription type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -911,7 +1260,7 @@ async def complete_message_in_topic_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -925,16 +1274,17 @@ async def complete_message_in_topic_async( request_url, response.status, response.text, + response=response, ) - async def abandon_message_in_topic_async( + def abandon_message_in_topic( self, topic_name: str, subscription_name: str, lock_token: str, + *, subscription_type: Optional[str] = None, session_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -944,6 +1294,25 @@ async def abandon_message_in_topic_async( Abandon the message in a topic subscription The operation abandons a message in a topic subscription. + + Swagger operation ID: `AbandonMessageInTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + lock_token: Lock token of the message to abandon. + subscription_type: Subscription type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -971,7 +1340,7 @@ async def abandon_message_in_topic_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -985,16 +1354,17 @@ async def abandon_message_in_topic_async( request_url, response.status, response.text, + response=response, ) - async def get_deferred_message_from_topic_async( + def get_deferred_message_from_topic( self, topic_name: str, subscription_name: str, sequence_number: int, + *, subscription_type: Optional[str] = None, session_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1004,6 +1374,25 @@ async def get_deferred_message_from_topic_async( Get deferred message from a topic subscription The operation gets a deferred message from a topic subscription. + + Swagger operation ID: `GetDeferredMessageFromTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + sequence_number: Sequence number of message. + subscription_type: Queue type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1031,7 +1420,7 @@ async def get_deferred_message_from_topic_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1045,6 +1434,7 @@ async def get_deferred_message_from_topic_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1052,14 +1442,14 @@ async def get_deferred_message_from_topic_async( return json.loads(response.text) - async def defer_message_in_topic_async( + def defer_message_in_topic( self, topic_name: str, subscription_name: str, lock_token: str, + *, subscription_type: Optional[str] = None, session_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1069,6 +1459,25 @@ async def defer_message_in_topic_async( Defer the message in a topic subscription The operation defers a message in a topic subscription. + + Swagger operation ID: `DeferMessageInTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + lock_token: Lock token of the message to defer. + subscription_type: Subscription type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1096,7 +1505,7 @@ async def defer_message_in_topic_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1110,17 +1519,18 @@ async def defer_message_in_topic_async( request_url, response.status, response.text, + response=response, ) - async def dead_letter_message_in_topic_async( + def dead_letter_message_in_topic( self, topic_name: str, subscription_name: str, lock_token: str, + *, session_id: Optional[str] = None, dead_letter_reason: Optional[str] = None, dead_letter_error_description: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1130,6 +1540,26 @@ async def dead_letter_message_in_topic_async( Dead-letter the message in a topic subscription The operation moves the message to the topic Dead-Letter Queue. + + Swagger operation ID: `DeadLetterMessageInTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + lock_token: Lock token of the message to dead-letter. + session_id: Session id. + dead_letter_reason: Dead letter reason. + dead_letter_error_description: Dead letter error description. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1162,7 +1592,7 @@ async def dead_letter_message_in_topic_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1176,15 +1606,16 @@ async def dead_letter_message_in_topic_async( request_url, response.status, response.text, + response=response, ) - async def renew_lock_on_message_in_topic_async( + def renew_lock_on_message_in_topic( self, topic_name: str, subscription_name: str, lock_token: str, - subscription_type: Optional[str] = None, *, + subscription_type: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1194,6 +1625,24 @@ async def renew_lock_on_message_in_topic_async( Renew lock on the message in a topic subscription The operation renews lock on a message in a topic subscription. + + Swagger operation ID: `RenewLockOnMessageInTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + lock_token: Lock token of the message to renew lock. + subscription_type: Subscription type - Main or DeadLetter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1216,7 +1665,7 @@ async def renew_lock_on_message_in_topic_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1230,15 +1679,16 @@ async def renew_lock_on_message_in_topic_async( request_url, response.status, response.text, + response=response, ) - async def create_topic_subscription_async( + def create_topic_subscription( self, - input: CreateTopicSubscriptionInput, + input: CreateTopicSubscriptionInput | Mapping[str, Any], topic_name: str, subscription_name: str, - subscription_filter_type: Optional[str] = None, *, + subscription_filter_type: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1248,6 +1698,25 @@ async def create_topic_subscription_async( Create a topic subscription The operation creates a topic subscription. + + Swagger operation ID: `CreateTopicSubscription`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + subscription_filter_type: Filter type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1264,7 +1733,7 @@ async def create_topic_subscription_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1278,6 +1747,7 @@ async def create_topic_subscription_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1285,7 +1755,7 @@ async def create_topic_subscription_async( return json.loads(response.text) - async def delete_topic_subscription_async( + def delete_topic_subscription( self, topic_name: str, subscription_name: str, @@ -1299,6 +1769,22 @@ async def delete_topic_subscription_async( Delete a topic subscription The operation deletes a topic subscription. + + Swagger operation ID: `DeleteTopicSubscription`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1307,7 +1793,7 @@ async def delete_topic_subscription_async( f"/{quote(str(subscription_name), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1321,27 +1807,52 @@ async def delete_topic_subscription_async( request_url, response.status, response.text, + response=response, ) - async def get_messages_from_topic_with_peek_lock_async( + def list_messages_from_topic_with_peek_lock( self, topic_name: str, subscription_name: str, + *, max_message_count: Optional[int] = None, subscription_type: Optional[str] = None, session_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get messages from a topic subscription (peek-lock) The operation receives messages from a topic subscription with peek-lock. If maximum message count is not provided, it reads 20 messages. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMessagesFromTopicWithPeekLock`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + max_message_count: The maximum number of messages to return in the + batch. + subscription_type: Subscription type - Main or DeadLetter. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1370,29 +1881,50 @@ async def get_messages_from_topic_with_peek_lock_async( query_params.append(f"sessionId={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def close_session_in_topic_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def close_session_in_topic( self, topic_name: str, subscription_name: str, @@ -1407,6 +1939,23 @@ async def close_session_in_topic_async( Close a session in the topic The operation closes a session in the topic. + + Swagger operation ID: `CloseSessionInTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1418,7 +1967,7 @@ async def close_session_in_topic_async( f"/close" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1432,9 +1981,10 @@ async def close_session_in_topic_async( request_url, response.status, response.text, + response=response, ) - async def renew_lock_on_session_in_topic_async( + def renew_lock_on_session_in_topic( self, topic_name: str, subscription_name: str, @@ -1449,6 +1999,23 @@ async def renew_lock_on_session_in_topic_async( Renew lock on the session in a topic subscription The operation renews a session in a topic subscription. + + Swagger operation ID: `RenewLockOnSessionInTopic`. + + Args: + topic_name: Name of the topic. + subscription_name: Name of the topic subscription. + session_id: Session id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1460,7 +2027,7 @@ async def renew_lock_on_session_in_topic_async( f"/renewlock" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1474,190 +2041,386 @@ async def renew_lock_on_session_in_topic_async( request_url, response.status, response.text, + response=response, ) - async def get_entities_async( + def list_entities( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get all entities This operation gets all queues and topics in the Service Bus namespace. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetEntities`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/entities" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_system_properties_async( + def list_system_properties( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[str]: """ Get the list of system properties This operation gets list of properties. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetSystemProperties`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[str]: An Azure Core pager over connector results. Consume + it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/systemproperties" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[str]: + for item in page: + yield item + + return None, items() - async def get_queues_async( + return ItemPaged(get_next, extract_data) + + def list_queues( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[str]: """ Get all queues This operation gets all queues in the Service Bus namespace. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetQueues`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[str]: An Azure Core pager over connector results. Consume + it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/queues" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[str]: + for item in page: + yield item - async def get_session_options_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_session_options( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[str]: """ Get session options This operation gets the list of options for session handling - None, Next available. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetSessionOptions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[str]: An Azure Core pager over connector results. Consume + it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/sessionoptions" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[str]: + for item in page: + yield item + + return None, items() - async def get_topics_async( + return ItemPaged(get_next, extract_data) + + def list_topics( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[str]: """ Get all topics This operation gets all topics in the Service Bus namespace. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTopics`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[str]: An Azure Core pager over connector results. Consume + it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/topics" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[str]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_subscriptions_async( + def list_subscriptions( self, topic_name: str, *, @@ -1665,12 +2428,31 @@ async def get_subscriptions_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[str]: """ Get the subscriptions for a topic This operation gets the list of subscriptions for a topic in the Service Bus namespace. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetSubscriptions`. + + Args: + topic_name: Topic name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[str]: An Azure Core pager over connector results. Consume + it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1678,29 +2460,50 @@ async def get_subscriptions_async( f"/{quote(quote(str(topic_name), safe=''), safe='')}" f"/subscriptions" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[str]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[str]: + for item in page: + yield item + + return None, items() - async def get_subscription_filter_async( + return ItemPaged(get_next, extract_data) + + def get_subscription_filter( self, subscription_filter_type: str, *, @@ -1713,6 +2516,21 @@ async def get_subscription_filter_async( Get metadata of a filter Get metadata of a filter. + + Swagger operation ID: `GetSubscriptionFilterV2`. + + Args: + subscription_filter_type: Subscription filter type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/subscriptionfilterV2" query_params = [] @@ -1723,7 +2541,7 @@ async def get_subscription_filter_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1737,6 +2555,7 @@ async def get_subscription_filter_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/sharepointonline.py b/src/azure/connectors/sharepointonline.py index 77448cc..79b3732 100644 --- a/src/azure/connectors/sharepointonline.py +++ b/src/azure/connectors/sharepointonline.py @@ -5,21 +5,105 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "SharepointonlineClient", + "ApplicationPermissionIdentity", + "ApprovalData", + "ApproveHubSiteJoinResponse", + "BlobDataSetsMetadata", + "BlobMetadata", + "BlobMetadataPage", + "BlobMetadataResponse", + "CopyFileParameters", + "CopyFolderParameters", + "CreateAgreementsSolutionDocumentInput", + "CreateApprovalRequestInput", + "CreateContentAssemblyDocumentInput", + "CreateNewDocumentSetParameters", + "CreateNewDocumentSetResponse", + "CreateNewFolderParameters", + "CreateNewFolderResponse", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "DeletedItem", + "DeletedItemList", + "FileCheckInParameters", + "FormFieldMetadata", + "GetItemChangesMetadataResponse", + "GetItemChangesResponse", + "GetItemResponse", + "GroupPermissionIdentity", + "HubSiteJoinApprovalOutput", + "Item", + "ItemGrantAccessBody", + "ItemPermissionAddBody", + "ItemPermissionCreateLinkBody", + "ItemPermissionRecipient", + "ItemPermissionUpdateBody", + "ItemReference", + "ItemsList", + "MoveFileParameters", + "MoveFolderParameters", + "ObjectEntity", + "PassThroughNativeQuery", + "PatchFileItemInput", + "PatchFileItemResponse", + "PatchFileItemWithPredictedValuesParameters", + "PatchItemInput", + "PatchItemResponse", + "Permission", + "PermissionIdentitySet", + "PermissionsList", + "PostItemInput", + "PostItemResponse", + "Procedure", + "PublishedResult", + "SPBlobMetadataResponse", + "SPContentType", + "SPForASelectedFileResponse", + "SPListEntity", + "SPListExpandedUser", + "SPListItemAttachment", + "SetApprovalStatusOutput", + "SharePointHttpRequestBodyParameters", + "SharePointIds", + "SharingInvitation", + "SharingLink", + "SharingLinkPermission", + "SharingLinkPermissionIdentitySet", + "SharingLinkUserPermissionIdentity", + "SubmitDocGenFormInput", + "Table", + "TableCapabilitiesMetadata", + "TableCountRestrictionsMetadata", + "TableFilterRestrictionsMetadata", + "TableForm", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TablesList", + "TabularDataSetsMetadata", + "UserPermissionIdentity", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +113,7 @@ class CreateAgreementsSolutionDocumentInput: Agreements Solution - Generate document within Agreements Solution workspace """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -42,48 +126,74 @@ class SPBlobMetadataResponse: Response for Agreements Solution - Generate document within Agreements Solution workspace """ - item_id: Optional[int] = field( + item_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ItemId"}, ) """ The value that can be used to Get or Update file properties in libraries. """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The filelocator of the file or folder.""" @@ -95,7 +205,12 @@ class TablesList: Response for Get all lists and libraries """ - value: Optional[List[Table]] = None + value: Optional[ + List[Table | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Tables""" @@ -105,8 +220,9 @@ class ApproveHubSiteJoinResponse: Response for Approve hub site join request """ - approval_token: Optional[str] = field( + approval_token: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ApprovalToken"}, ) """Approval Token""" @@ -118,7 +234,7 @@ class SharingLinkPermission: Response for Create sharing link for a file or folder """ - link: Optional[SharingLink] = None + link: Optional[SharingLink | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -127,41 +243,66 @@ class BlobMetadata: Response for Copy file (deprecated) """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The filelocator of the file or folder.""" @@ -173,41 +314,66 @@ class BlobMetadataResponse: Response for Update file """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique id of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - last_modified: Optional[str] = field( + last_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastModified"}, ) """The date and time the file or folder was last modified.""" - size: Optional[int] = field(default=None, metadata={"wire_name": "Size"}) + size: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Size"}, + ) """The size of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """The etag of the file or folder.""" - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The filelocator of the file or folder.""" @@ -219,7 +385,7 @@ class CreateNewDocumentSetResponse: Response for Create new document set """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -232,7 +398,7 @@ class CreateNewFolderResponse: Response for Create new folder """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -245,35 +411,45 @@ class SPListExpandedUser: Response for Resolve person """ - claims: Optional[str] = field( + claims: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Claims"}, ) """user claims""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """user title""" - email: Optional[str] = field(default=None, metadata={"wire_name": "Email"}) + email: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Email"}, + ) """user email""" - picture: Optional[str] = field( + picture: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Picture"}, ) """user picture""" - department: Optional[str] = field( + department: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Department"}, ) """user department""" - job_title: Optional[str] = field( + job_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JobTitle"}, ) """user job title""" - type_: Optional[str] = field( + type_: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.type"}, ) @@ -284,50 +460,66 @@ class TableForm: Response for Get form metadata (preview) """ - form_id: Optional[str] = field( + form_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FormID"}, ) """Gets or sets the form ID""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Gets or sets the form display name""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "Type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Type"}, + ) """Gets or sets the form type""" - link: Optional[str] = field(default=None, metadata={"wire_name": "Link"}) + link: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Link"}, + ) """Gets or sets the form link/URL""" - created_by: Optional[str] = field( + created_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CreatedBy"}, ) """Gets or sets the user who created the form""" - created: Optional[str] = field( + created: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Created"}, ) """Gets or sets the date the form was created""" - modified: Optional[str] = field( + modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Modified"}, ) """Gets or sets the date the form was last modified""" - modified_by: Optional[str] = field( + modified_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ModifiedBy"}, ) """Gets or sets the user who last modified the form""" - output_format: Optional[str] = field( + output_format: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OutputFormat"}, ) """ Gets or sets the output format (e.g. \"Word document\", \"PDF document\", \"None\") """ - fields_metadata: Optional[List[FormFieldMetadata]] = field( + fields_metadata: Optional[List[FormFieldMetadata | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FieldsMetadata"}, ) """Gets or sets Form Fields""" @@ -339,7 +531,7 @@ class SubmitDocGenFormInput: Generate a document from a form (preview) """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -352,10 +544,16 @@ class ItemsList: Response for Get files (properties only) """ - value: Optional[List[Item]] = None + value: Optional[ + List[Item | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Items""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -367,7 +565,7 @@ class PostItemInput: Create item """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -380,7 +578,7 @@ class PostItemResponse: Response for Create item """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -393,7 +591,7 @@ class GetItemResponse: Response for Get item """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -406,7 +604,7 @@ class PatchItemInput: Update item """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -419,7 +617,7 @@ class PatchItemResponse: Response for Update item """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -432,7 +630,7 @@ class CreateApprovalRequestInput: Create an approval request for an item or file """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -445,10 +643,7 @@ class ApprovalData: Response for Create an approval request for an item or file """ - approval_id: Optional[str] = field( - default=None, - metadata={"wire_name": "ApprovalId"}, - ) + approval_id: str = dataclass_field(metadata={"wire_name": "ApprovalId"}) """The ID of the approval request created""" @@ -458,7 +653,7 @@ class GetItemChangesResponse: Response for Get changes for an item or a file (properties only) """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -471,8 +666,9 @@ class Item: Response for Get file properties """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) @@ -483,7 +679,7 @@ class PatchFileItemInput: Update file properties """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -496,7 +692,7 @@ class PatchFileItemResponse: Response for Update file properties """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -509,25 +705,33 @@ class SetApprovalStatusOutput: Response for Set content approval status """ - e_tag: Optional[str] = field(default=None, metadata={"wire_name": "ETag"}) + e_tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETag"}, + ) """ETag of the item after the approval status was set""" - approval_link: Optional[str] = field( + approval_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ApprovalLink"}, ) """A link to the item that needs approval""" - publish_start_date: Optional[str] = field( + publish_start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PublishStartDate"}, ) """Date time at which the item will be Published""" - content_approval_status: Optional[str] = field( + content_approval_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentApprovalStatus"}, ) """The content approval status of the list item""" - scheduled_version: Optional[str] = field( + scheduled_version: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ScheduledVersion"}, ) """The version of the item that has been scheduled""" @@ -539,15 +743,21 @@ class SPListItemAttachment: Response for Get attachments """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """File identifier""" - absolute_uri: Optional[str] = field( + absolute_uri: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AbsoluteUri"}, ) """Link to attachment""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Name""" @@ -559,7 +769,12 @@ class DeletedItemList: Response for When a file is deleted """ - value: Optional[List[DeletedItem]] = None + value: Optional[ + List[DeletedItem | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Deleted Items""" @@ -569,7 +784,7 @@ class CreateContentAssemblyDocumentInput: Generate document using Microsoft Syntex (preview) """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -582,15 +797,21 @@ class Table: Response for Get list views """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the table. The name is used at runtime.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the table.""" - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DynamicProperties"}, ) """Additional table properties provided by the connector to the clients.""" @@ -602,7 +823,12 @@ class DataSetsList: Response for Get datasets """ - value: Optional[List[DataSet]] = None + value: Optional[ + List[DataSet | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of datasets""" @@ -612,26 +838,30 @@ class TableMetadata: Response for Agreements Solution - Get template fields """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Table name""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Table title""" - x_ms_permission: Optional[str] = field( + x_ms_permission: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-permission"}, ) """Table permission""" - x_ms_capabilities: Optional[TableCapabilitiesMetadata] = field( + x_ms_capabilities: Optional[TableCapabilitiesMetadata | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-capabilities"}, ) - schema: Optional[ObjectEntity] = None - referenced_entities: Optional[ObjectEntity] = field( + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + referenced_entities: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "referencedEntities"}, ) - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webUrl"}, ) """URL link""" @@ -643,7 +873,7 @@ class ObjectEntity: Response for Get thumbnail size options """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -656,10 +886,15 @@ class SPListEntity: Response for Returns User fields for a list """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The Id of the SPField""" - entity_type: Optional[str] = field( + entity_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntityType"}, ) """What type of entity (field) this is""" @@ -671,7 +906,7 @@ class GetItemChangesMetadataResponse: Response for Get metadata about the return type of the GetItemChanges operation """ - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -680,8 +915,9 @@ class ApplicationPermissionIdentity: Definition: ApplicationPermissionIdentity """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Application display name""" @@ -693,15 +929,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -713,7 +951,12 @@ class BlobMetadataPage: Definition: BlobMetadataPage """ - value: Optional[List[BlobMetadata]] = None + value: Optional[ + List[BlobMetadata | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Blob metadata collection.""" @@ -723,23 +966,19 @@ class CopyFileParameters: Definition: CopyFileParameters """ - source_file_id: Optional[str] = field( - default=None, + source_file_id: str = dataclass_field( metadata={"wire_name": "sourceFileId"}, ) """File Identifier""" - destination_dataset: Optional[str] = field( - default=None, + destination_dataset: str = dataclass_field( metadata={"wire_name": "destinationDataset"}, ) """Example: https://contoso.sharepoint.com/sites/sitename""" - destination_folder_path: Optional[str] = field( - default=None, + destination_folder_path: str = dataclass_field( metadata={"wire_name": "destinationFolderPath"}, ) """Destination Folder""" - name_conflict_behavior: Optional[int] = field( - default=None, + name_conflict_behavior: int = dataclass_field( metadata={"wire_name": "nameConflictBehavior"}, ) """Pick one of the options available""" @@ -751,23 +990,19 @@ class CopyFolderParameters: Definition: CopyFolderParameters """ - source_folder_id: Optional[str] = field( - default=None, + source_folder_id: str = dataclass_field( metadata={"wire_name": "sourceFolderId"}, ) """File Identifier""" - destination_dataset: Optional[str] = field( - default=None, + destination_dataset: str = dataclass_field( metadata={"wire_name": "destinationDataset"}, ) """Example: https://contoso.sharepoint.com/sites/sitename""" - destination_folder_path: Optional[str] = field( - default=None, + destination_folder_path: str = dataclass_field( metadata={"wire_name": "destinationFolderPath"}, ) """Destination Folder""" - name_conflict_behavior: Optional[int] = field( - default=None, + name_conflict_behavior: int = dataclass_field( metadata={"wire_name": "nameConflictBehavior"}, ) """Pick one of the options available""" @@ -779,15 +1014,15 @@ class CreateNewDocumentSetParameters: Definition: CreateNewDocumentSetParameters """ - path: Optional[str] = None + path: str """Example: folder1/folder2/dsName""" - content_type_id: Optional[str] = field( - default=None, + content_type_id: str = dataclass_field( metadata={"wire_name": "contentTypeId"}, ) """Example: 0x0120D520""" - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DynamicProperties"}, ) @@ -798,7 +1033,7 @@ class CreateNewFolderParameters: Definition: CreateNewFolderParameters """ - path: Optional[str] = None + path: str """Example: folder1/folder2/folder3""" @@ -808,14 +1043,24 @@ class DataSet: Definition: DataSet """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Dataset name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Dataset display name""" - query: Optional[List[PassThroughNativeQuery]] = None + query: Optional[ + List[PassThroughNativeQuery | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Pass-through Native Queries""" @@ -825,8 +1070,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -835,33 +1090,45 @@ class DeletedItem: Definition: DeletedItem """ - id: Optional[int] = field(default=None, metadata={"wire_name": "ID"}) + id: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID"}, + ) """List item id""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """ File name of the item in document libraries, display name of the item in lists """ - file_name_with_extension: Optional[str] = field( + file_name_with_extension: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileNameWithExtension"}, ) """ File name with extension of the item in document libraries, same as Name of the item in lists """ - deleted_by_user_name: Optional[str] = field( + deleted_by_user_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DeletedByUserName"}, ) """The name of the user who deleted this item""" - time_deleted: Optional[str] = field( + time_deleted: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TimeDeleted"}, ) """When this item was deleted""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """A true/false value to indicate if the item is a folder""" @@ -873,12 +1140,9 @@ class FileCheckInParameters: Definition: FileCheckInParameters """ - comment: Optional[str] = None + comment: str """Type comments describing what has changed in this version""" - checkin_type: Optional[int] = field( - default=None, - metadata={"wire_name": "checkinType"}, - ) + checkin_type: int = dataclass_field(metadata={"wire_name": "checkinType"}) """Select the type of version you would like to check in""" @@ -888,22 +1152,33 @@ class FormFieldMetadata: Definition: FormFieldMetadata """ - id: Optional[str] = field(default=None, metadata={"wire_name": "ID"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID"}, + ) """Gets or sets the field ID""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Gets or sets the field Name""" - is_required: Optional[bool] = field( + is_required: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsRequired"}, ) """Gets or sets a value indicating whether the field is required""" - data_type: Optional[str] = field( + data_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DataType"}, ) """Gets or sets the field data type""" - default_value: Optional[str] = field( + default_value: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DefaultValue"}, ) """Gets or sets the default value""" @@ -915,8 +1190,9 @@ class GroupPermissionIdentity: Definition: GroupPermissionIdentity """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Group display name""" @@ -928,23 +1204,27 @@ class HubSiteJoinApprovalOutput: Definition: HubSiteJoinApprovalOutput """ - requesting_site_url: Optional[str] = field( + requesting_site_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequestingSiteUrl"}, ) """Requesting Site Url""" - requesting_site_id: Optional[str] = field( + requesting_site_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequestingSiteId"}, ) """Requesting Site Id""" - requesting_site_title: Optional[str] = field( + requesting_site_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RequestingSiteTitle"}, ) """Requesting Site Title""" - approval_correlation_id: Optional[str] = field( + approval_correlation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ApprovalCorrelationId"}, ) """Approval Correlation Id""" @@ -956,22 +1236,21 @@ class ItemGrantAccessBody: Definition: ItemGrantAccessBody """ - recipients: Optional[str] = None + recipients: str """A collection of recipients who will receive the sharing invitation""" - role_value: Optional[str] = field( - default=None, - metadata={"wire_name": "roleValue"}, - ) + role_value: str = dataclass_field(metadata={"wire_name": "roleValue"}) """Specify a role that is to be granted to the recipients""" - email_body: Optional[str] = field( + email_body: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "emailBody"}, ) """ A plain text formatted message that is included in the sharing invitation """ - send_email: Optional[bool] = field( + send_email: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sendEmail"}, ) """ @@ -985,33 +1264,31 @@ class ItemPermissionAddBody: Definition: ItemPermissionAddBody """ - recipients: Optional[List[ItemPermissionRecipient]] = None + recipients: List[ItemPermissionRecipient | Mapping[str, Any]] """ A collection of recipients who will receive access and the sharing invitation. """ - roles: Optional[List[str]] = None + roles: List[str] """ Specify the roles that are be granted to the recipients of the sharing invitation. """ - require_sign_in: Optional[bool] = field( - default=None, + require_sign_in: bool = dataclass_field( metadata={"wire_name": "requireSignIn"}, ) """ Specifies where the recipient of the invitation is required to sign-in to view the shared item. """ - send_invitation: Optional[bool] = field( - default=None, + send_invitation: bool = dataclass_field( metadata={"wire_name": "sendInvitation"}, ) """ Specifies if an email or post is generated (true) or if the permission is just created (false). """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """ A plain text formatted message that is included in the sharing invitation. Maximum length 2000 characters. @@ -1024,15 +1301,16 @@ class ItemPermissionCreateLinkBody: Definition: ItemPermissionCreateLinkBody """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """The type of sharing link to create""" - scope: Optional[str] = None + scope: str """ Choose who your sharing link gives access to. \"Anyone\" option will only work if your administrator has enabled it. """ - expiration_date_time: Optional[str] = field( + expiration_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "expirationDateTime"}, ) """ @@ -1047,7 +1325,7 @@ class ItemPermissionRecipient: Definition: ItemPermissionRecipient """ - email: Optional[str] = None + email: str """ The email address for the recipient, if the recipient has an associated email address. @@ -1060,7 +1338,7 @@ class ItemPermissionUpdateBody: Definition: ItemPermissionUpdateBody """ - roles: Optional[List[str]] = None + roles: List[str] """Specify updated roles for this permission.""" @@ -1070,12 +1348,13 @@ class ItemReference: Definition: ItemReference """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the parent item""" - path: Optional[str] = None + path: Optional[str] = dataclass_field(default=None, kw_only=True) """Path that can be used to navigate to the parent item""" - sharepoint_ids: Optional[SharePointIds] = field( + sharepoint_ids: Optional[SharePointIds | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sharepointIds"}, ) @@ -1086,23 +1365,19 @@ class MoveFileParameters: Definition: MoveFileParameters """ - source_file_id: Optional[str] = field( - default=None, + source_file_id: str = dataclass_field( metadata={"wire_name": "sourceFileId"}, ) """File Identifier""" - destination_dataset: Optional[str] = field( - default=None, + destination_dataset: str = dataclass_field( metadata={"wire_name": "destinationDataset"}, ) """Example: https://contoso.sharepoint.com/sites/sitename""" - destination_folder_path: Optional[str] = field( - default=None, + destination_folder_path: str = dataclass_field( metadata={"wire_name": "destinationFolderPath"}, ) """Destination Folder""" - name_conflict_behavior: Optional[int] = field( - default=None, + name_conflict_behavior: int = dataclass_field( metadata={"wire_name": "nameConflictBehavior"}, ) """Pick one of the options available""" @@ -1114,23 +1389,19 @@ class MoveFolderParameters: Definition: MoveFolderParameters """ - source_folder_id: Optional[str] = field( - default=None, + source_folder_id: str = dataclass_field( metadata={"wire_name": "sourceFolderId"}, ) """File Identifier""" - destination_dataset: Optional[str] = field( - default=None, + destination_dataset: str = dataclass_field( metadata={"wire_name": "destinationDataset"}, ) """Example: https://contoso.sharepoint.com/sites/sitename""" - destination_folder_path: Optional[str] = field( - default=None, + destination_folder_path: str = dataclass_field( metadata={"wire_name": "destinationFolderPath"}, ) """Destination Folder""" - name_conflict_behavior: Optional[int] = field( - default=None, + name_conflict_behavior: int = dataclass_field( metadata={"wire_name": "nameConflictBehavior"}, ) """Pick one of the options available""" @@ -1142,8 +1413,9 @@ class PassThroughNativeQuery: Definition: PassThroughNativeQuery """ - language: Optional[str] = field( + language: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Language"}, ) """Query language""" @@ -1155,13 +1427,15 @@ class PatchFileItemWithPredictedValuesParameters: Definition: PatchFileItemWithPredictedValuesParameters """ - model_id: Optional[str] = field( + model_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "modelId"}, ) """Enter modelId of the Model which is used for prediction""" - predict_result: Optional[str] = field( + predict_result: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "predictResult"}, ) """Enter request content in JSON""" @@ -1173,27 +1447,37 @@ class Permission: Definition: Permission """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Permission id""" - granted_to: Optional[PermissionIdentitySet] = field( + granted_to: Optional[PermissionIdentitySet | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "grantedTo"}, ) - granted_to_identities: Optional[List[SharingLinkPermissionIdentitySet]] = field( + granted_to_identities: Optional[ + List[SharingLinkPermissionIdentitySet | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "grantedToIdentities"}, ) """ For link type permissions, the details of the users to whom permission was granted """ - invitation: Optional[SharingInvitation] = None - inherited_from: Optional[ItemReference] = field( + invitation: Optional[ + SharingInvitation | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, + ) + inherited_from: Optional[ItemReference | Mapping[str, Any]] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "inheritedFrom"}, ) - link: Optional[SharingLink] = None - roles: Optional[List[str]] = None + link: Optional[SharingLink | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + roles: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """The type of permission - read, write, owner, member""" @@ -1203,9 +1487,24 @@ class PermissionIdentitySet: Definition: PermissionIdentitySet """ - application: Optional[ApplicationPermissionIdentity] = None - group: Optional[GroupPermissionIdentity] = None - user: Optional[UserPermissionIdentity] = None + application: Optional[ + ApplicationPermissionIdentity | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + group: Optional[ + GroupPermissionIdentity | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + user: Optional[ + UserPermissionIdentity | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1214,7 +1513,12 @@ class PermissionsList: Definition: PermissionsList """ - value: Optional[List[Permission]] = None + value: Optional[ + List[Permission | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Permissions""" @@ -1224,10 +1528,15 @@ class Procedure: Definition: Procedure """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Procedure name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Procedure display name""" @@ -1239,8 +1548,7 @@ class PublishedResult: Definition: PublishedResult """ - is_file_published: Optional[bool] = field( - default=None, + is_file_published: bool = dataclass_field( metadata={"wire_name": "IsFilePublished"}, ) """ @@ -1255,13 +1563,13 @@ class SharePointHttpRequestBodyParameters: Definition: SharePointHttpRequestBodyParameters """ - method: Optional[str] = None + method: str """Http Method""" - uri: Optional[str] = None + uri: str """Example: _api/web/lists/getbytitle('Documents')""" - headers: Optional[Dict[str, str]] = None + headers: Optional[Dict[str, str]] = dataclass_field(default=None, kw_only=True) """Enter JSON object of request headers""" - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """Enter request content in JSON""" @@ -1271,41 +1579,48 @@ class SharePointIds: Definition: SharePointIds """ - list_id: Optional[str] = field( + list_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "listId"}, ) """The unique identifier (guid) for the item's list in SharePoint""" - list_item_id: Optional[str] = field( + list_item_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "listItemId"}, ) """An integer identifier for the item within the containing list""" - list_item_unique_id: Optional[str] = field( + list_item_unique_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "listItemUniqueId"}, ) """ The unique identifier (guid) for the item within OneDrive for Business or a SharePoint site """ - site_id: Optional[str] = field( + site_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "siteId"}, ) """The unique identifier (guid) for the item's site collection (SPSite)""" - site_url: Optional[str] = field( + site_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "siteUrl"}, ) """The SharePoint URL for the site that contains the item""" - tenant_id: Optional[str] = field( + tenant_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tenantId"}, ) """The unique identifier (guid) for the tenancy""" - web_id: Optional[str] = field( + web_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webId"}, ) """The unique identifier (guid) for the item's site (SPWeb)""" @@ -1317,12 +1632,13 @@ class SharingInvitation: Definition: SharingInvitation """ - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """ The email address provided for the recipient of the sharing invitation """ - sign_in_required: Optional[bool] = field( + sign_in_required: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "signInRequired"}, ) """ @@ -1337,8 +1653,9 @@ class SharingLink: Definition: SharingLink """ - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webUrl"}, ) """A link to the item""" @@ -1350,7 +1667,12 @@ class SharingLinkPermissionIdentitySet: Definition: SharingLinkPermissionIdentitySet """ - user: Optional[SharingLinkUserPermissionIdentity] = None + user: Optional[ + SharingLinkUserPermissionIdentity | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1359,12 +1681,13 @@ class SharingLinkUserPermissionIdentity: Definition: SharingLinkUserPermissionIdentity """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """User display name""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """User email""" @@ -1374,9 +1697,17 @@ class SPContentType: Definition: SPContentType """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """Content type Id""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Content type name""" @@ -1386,15 +1717,21 @@ class SPForASelectedFileResponse: Definition: SPForASelectedFileResponse """ - id: Optional[int] = field(default=None, metadata={"wire_name": "ID"}) + id: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID"}, + ) """File Identifier""" - item_url: Optional[str] = field( + item_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "itemUrl"}, ) """File Url""" - file_name: Optional[str] = field( + file_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fileName"}, ) """File Name""" @@ -1406,34 +1743,49 @@ class TableCapabilitiesMetadata: Definition: TableCapabilitiesMetadata """ - sort_restrictions: Optional[TableSortRestrictionsMetadata] = field( + sort_restrictions: Optional[ + TableSortRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sortRestrictions"}, ) - filter_restrictions: Optional[TableFilterRestrictionsMetadata] = field( + filter_restrictions: Optional[ + TableFilterRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterRestrictions"}, ) - select_restrictions: Optional[TableSelectRestrictionsMetadata] = field( + select_restrictions: Optional[ + TableSelectRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selectRestrictions"}, ) - count_restrictions: Optional[TableCountRestrictionsMetadata] = field( + count_restrictions: Optional[ + TableCountRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "countRestrictions"}, ) - is_only_server_pagable: Optional[bool] = field( + is_only_server_pagable: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isOnlyServerPagable"}, ) """Server paging restrictions""" - filter_function_support: Optional[List[str]] = field( + filter_function_support: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterFunctionSupport"}, ) """List of supported filter capabilities""" - server_paging_options: Optional[List[str]] = field( + server_paging_options: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "serverPagingOptions"}, ) """List of supported server-driven paging capabilities""" @@ -1445,7 +1797,7 @@ class TableCountRestrictionsMetadata: Definition: TableCountRestrictionsMetadata """ - countable: Optional[bool] = None + countable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has countable columns""" @@ -1455,15 +1807,17 @@ class TableFilterRestrictionsMetadata: Definition: TableFilterRestrictionsMetadata """ - filterable: Optional[bool] = None + filterable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has filterable columns""" - non_filterable_properties: Optional[List[str]] = field( + non_filterable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nonFilterableProperties"}, ) """List of non filterable properties""" - required_properties: Optional[List[str]] = field( + required_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredProperties"}, ) """List of required properties""" @@ -1475,7 +1829,7 @@ class TableSelectRestrictionsMetadata: Definition: TableSelectRestrictionsMetadata """ - selectable: Optional[bool] = None + selectable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has selectable columns""" @@ -1485,15 +1839,17 @@ class TableSortRestrictionsMetadata: Definition: TableSortRestrictionsMetadata """ - sortable: Optional[bool] = None + sortable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has sortable columns""" - unsortable_properties: Optional[List[str]] = field( + unsortable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "unsortableProperties"}, ) """List of unsortable properties""" - ascending_only_properties: Optional[List[str]] = field( + ascending_only_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ascendingOnlyProperties"}, ) """List of properties which support ascending order only""" @@ -1505,25 +1861,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -1535,12 +1895,13 @@ class UserPermissionIdentity: Definition: UserPermissionIdentity """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """User display name""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """User email""" @@ -1552,16 +1913,16 @@ class SharepointonlineClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -1572,8 +1933,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -1581,8 +1942,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -1594,7 +1955,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -1616,7 +1977,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -1648,13 +2009,13 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def create_agreements_solution_document_async( + def create_agreements_solution_document( self, - input: CreateAgreementsSolutionDocumentInput, + input: CreateAgreementsSolutionDocumentInput | Mapping[str, Any], dataset: str, template: str, - document_name: Optional[str] = None, *, + document_name: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1667,6 +2028,25 @@ async def create_agreements_solution_document_async( Use this action to create documents based on modern templates in a Agreements Solution workspace. This is behind a payment wall currently in planning (either license or PayG). + + Swagger operation ID: `CreateAgreementsSolutionDocument`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + template: Agreements Solution template. + document_name: Document file name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1686,7 +2066,7 @@ async def create_agreements_solution_document_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1700,6 +2080,7 @@ async def create_agreements_solution_document_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1707,7 +2088,7 @@ async def create_agreements_solution_document_async( return json.loads(response.text) - async def get_all_tables_async( + def list_all_tables( self, dataset: str, *, @@ -1715,11 +2096,30 @@ async def get_all_tables_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get all lists and libraries Get all lists and libraries. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAllTables`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1727,29 +2127,50 @@ async def get_all_tables_async( f"/{quote(quote(str(dataset), safe=''), safe='')}" f"/alltables" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def approve_hub_site_join_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def approve_hub_site_join( self, dataset: str, joining_site_id: str, @@ -1765,6 +2186,22 @@ async def approve_hub_site_join_async( Approve hub site join request. This will return an approval token that can be used to complete the join request using the join hub site action. + + Swagger operation ID: `ApproveHubSiteJoin`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + joining_site_id: Id of the requesting site. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1780,7 +2217,7 @@ async def approve_hub_site_join_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1794,6 +2231,7 @@ async def approve_hub_site_join_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1801,11 +2239,11 @@ async def approve_hub_site_join_async( return json.loads(response.text) - async def cancel_hub_site_join_approval_async( + def cancel_hub_site_join_approval( self, dataset: str, - approval_correlation_id: Optional[str] = None, *, + approval_correlation_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1817,6 +2255,23 @@ async def cancel_hub_site_join_approval_async( Cancel hub join request. If applicable, you should specify the same Approval Correlation Id as used in the \"Set hub site join status to pending\" action. + + Swagger operation ID: `CancelHubSiteJoinApproval`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + approval_correlation_id: Approval correlation identifier for this + request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1833,7 +2288,7 @@ async def cancel_hub_site_join_approval_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1847,11 +2302,12 @@ async def cancel_hub_site_join_approval_async( request_url, response.status, response.text, + response=response, ) - async def create_sharing_link_async( + def create_sharing_link( self, - input: ItemPermissionCreateLinkBody, + input: ItemPermissionCreateLinkBody | Mapping[str, Any], dataset: str, table: str, id: int, @@ -1865,6 +2321,25 @@ async def create_sharing_link_async( Create sharing link for a file or folder Create sharing link for a file or folder. + + Swagger operation ID: `CreateSharingLink`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + id: Id of the file or folder item. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1883,7 +2358,7 @@ async def create_sharing_link_async( f"/createLink" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1897,6 +2372,7 @@ async def create_sharing_link_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1904,13 +2380,13 @@ async def create_sharing_link_async( return json.loads(response.text) - async def copy_file_async( + def copy_file( self, dataset: str, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1920,6 +2396,25 @@ async def copy_file_async( Copy file (deprecated) Copies a file to a SharePoint site. + + Swagger operation ID: `CopyFile`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + source: Path to the source file. + destination: Path to the destination file. + overwrite: Whether or not to overwrite the destination file if it + exists. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1945,7 +2440,7 @@ async def copy_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1959,6 +2454,7 @@ async def copy_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1966,9 +2462,9 @@ async def copy_file_async( return json.loads(response.text) - async def copy_file_2_async( + def copy_file_2( self, - input: CopyFileParameters, + input: CopyFileParameters | Mapping[str, Any], dataset: str, *, timeout: Optional[float] = None, @@ -1982,6 +2478,23 @@ async def copy_file_2_async( Copies a file. Works in a similar way to the \"Copy to\" command in SharePoint libraries. Returns information about the new file after copy. + + Swagger operation ID: `CopyFileAsync`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1990,7 +2503,7 @@ async def copy_file_2_async( f"/copyFileAsync" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2004,6 +2517,7 @@ async def copy_file_2_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2011,9 +2525,9 @@ async def copy_file_2_async( return json.loads(response.text) - async def copy_folder_async( + def copy_folder( self, - input: CopyFolderParameters, + input: CopyFolderParameters | Mapping[str, Any], dataset: str, *, timeout: Optional[float] = None, @@ -2027,6 +2541,23 @@ async def copy_folder_async( Copies a folder. Works in a similar way to the \"Copy to\" command in SharePoint libraries. Returns information about the new folder after copy. + + Swagger operation ID: `CopyFolderAsync`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2035,7 +2566,7 @@ async def copy_folder_async( f"/copyFolderAsync" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2049,6 +2580,7 @@ async def copy_folder_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2056,7 +2588,7 @@ async def copy_folder_async( return json.loads(response.text) - async def create_file_async( + def create_file( self, input: bytes, dataset: str, @@ -2073,6 +2605,25 @@ async def create_file_async( Uploads a file to a SharePoint site. Make sure to pick an existing library. + + Swagger operation ID: `CreateFile`. + + Args: + input: The binary request body. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + folder_path: Must start with an existing library. Add folders if + needed. + name: Name of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2091,7 +2642,7 @@ async def create_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -2108,6 +2659,7 @@ async def create_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2115,7 +2667,7 @@ async def create_file_async( return json.loads(response.text) - async def get_file_metadata_async( + def get_file_metadata( self, dataset: str, id: str, @@ -2131,6 +2683,22 @@ async def get_file_metadata_async( Gets information about the file such as size, etag, created date, etc. Uses a file identifier to pick the file. Use \"Get file properties\" action to get to the values stored in the columns in the library. + + Swagger operation ID: `GetFileMetadata`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + id: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2140,7 +2708,7 @@ async def get_file_metadata_async( f"/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2154,6 +2722,7 @@ async def get_file_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2161,7 +2730,7 @@ async def get_file_metadata_async( return json.loads(response.text) - async def update_file_async( + def update_file( self, input: bytes, dataset: str, @@ -2176,6 +2745,23 @@ async def update_file_async( Update file Updates the contents of the file specified by the file identifier. + + Swagger operation ID: `UpdateFile`. + + Args: + input: The binary request body. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + id: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2185,7 +2771,7 @@ async def update_file_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, @@ -2202,6 +2788,7 @@ async def update_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2209,7 +2796,7 @@ async def update_file_async( return json.loads(response.text) - async def delete_file_async( + def delete_file( self, dataset: str, id: str, @@ -2223,6 +2810,22 @@ async def delete_file_async( Delete file Deletes the file specified by the file identifier. + + Swagger operation ID: `DeleteFile`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + id: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2232,7 +2835,7 @@ async def delete_file_async( f"/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2246,14 +2849,15 @@ async def delete_file_async( request_url, response.status, response.text, + response=response, ) - async def get_file_content_async( + def get_file_content( self, dataset: str, id: str, - infer_content_type: Optional[bool] = None, *, + infer_content_type: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2264,6 +2868,23 @@ async def get_file_content_async( Gets file contents using the file identifier. The contents can be copied somewhere else, or be used as an attachment. + + Swagger operation ID: `GetFileContent`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + id: Select a file. + infer_content_type: Infer content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2282,7 +2903,7 @@ async def get_file_content_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2296,11 +2917,12 @@ async def get_file_content_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_file_thumbnail_async( + def get_file_thumbnail( self, dataset: str, id: str, @@ -2315,6 +2937,23 @@ async def get_file_thumbnail_async( Get file thumbnail Gets the thumbnail of a file by its file identifier. + + Swagger operation ID: `GetFileThumbnail`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + id: Select a file. + size: The size of the thumbnail to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2332,7 +2971,7 @@ async def get_file_thumbnail_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2346,11 +2985,12 @@ async def get_file_thumbnail_async( request_url, response.status, response.text, + response=response, ) return response.content - async def list_root_folder_async( + def list_root_folder( self, dataset: str, *, @@ -2358,39 +2998,79 @@ async def list_root_folder_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List root folder Returns files in the root SharePoint folder. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListRootFolder`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/datasets/{quote(quote(str(dataset), safe=''), safe='')}/folders" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def list_folder_async( + return ItemPaged(get_next, extract_data) + + def list_folder( self, dataset: str, id: str, @@ -2399,11 +3079,31 @@ async def list_folder_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List folder Returns files contained in a SharePoint folder. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListFolder`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + id: Unique identifier of the folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2412,29 +3112,50 @@ async def list_folder_async( f"/folders" f"/{quote(str(id), safe='')}" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def get_file_metadata_by_path_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_file_metadata_by_path( self, dataset: str, path: str, @@ -2450,6 +3171,22 @@ async def get_file_metadata_by_path_async( Gets information about the file such as size, etag, created date, etc. Uses a file path to pick the file. Use \"Get file properties\" action to get to the values stored in the columns in the library. + + Swagger operation ID: `GetFileMetadataByPath`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + path: Select a file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2466,7 +3203,7 @@ async def get_file_metadata_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2480,6 +3217,7 @@ async def get_file_metadata_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2487,12 +3225,12 @@ async def get_file_metadata_by_path_async( return json.loads(response.text) - async def get_file_content_by_path_async( + def get_file_content_by_path( self, dataset: str, path: str, - infer_content_type: Optional[bool] = None, *, + infer_content_type: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2502,6 +3240,23 @@ async def get_file_content_by_path_async( Get file content using path Gets file contents using the file path. + + Swagger operation ID: `GetFileContentByPath`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + path: Select a file. + infer_content_type: Infer content-type based on extension. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2523,7 +3278,7 @@ async def get_file_content_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2537,11 +3292,12 @@ async def get_file_content_by_path_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_folder_metadata_async( + def get_folder_metadata( self, dataset: str, id: str, @@ -2556,6 +3312,22 @@ async def get_folder_metadata_async( Gets information about the folder. Uses a file identifier to pick the folder. + + Swagger operation ID: `GetFolderMetadata`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + id: Select a folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2571,7 +3343,7 @@ async def get_folder_metadata_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2585,6 +3357,7 @@ async def get_folder_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2592,7 +3365,7 @@ async def get_folder_metadata_async( return json.loads(response.text) - async def get_folder_metadata_by_path_async( + def get_folder_metadata_by_path( self, dataset: str, path: str, @@ -2607,6 +3380,22 @@ async def get_folder_metadata_by_path_async( Gets information about the folder. Uses a folder path to pick the folder. + + Swagger operation ID: `GetFolderMetadataByPath`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + path: Select a folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2623,7 +3412,7 @@ async def get_folder_metadata_by_path_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2637,6 +3426,7 @@ async def get_folder_metadata_by_path_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2644,9 +3434,9 @@ async def get_folder_metadata_by_path_async( return json.loads(response.text) - async def http_request_async( + def http_request( self, - input: SharePointHttpRequestBodyParameters, + input: SharePointHttpRequestBodyParameters | Mapping[str, Any], dataset: str, *, timeout: Optional[float] = None, @@ -2660,6 +3450,23 @@ async def http_request_async( Construct a SharePoint REST API to invoke. Note - This action may execute any SharePoint REST API you have access to. Please proceed with caution. + + Swagger operation ID: `HttpRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2668,7 +3475,7 @@ async def http_request_async( f"/httprequest" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2682,15 +3489,16 @@ async def http_request_async( request_url, response.status, response.text, + response=response, ) - async def join_hub_site_async( + def join_hub_site( self, dataset: str, hub_site_id: str, + *, approval_token: Optional[str] = None, approval_correlation_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2703,6 +3511,25 @@ async def join_hub_site_async( to complete the join successfully if that hub requires approval. If applicable, you should specify the same Approval Correlation Id as used in the \"Set hub site join status to pending\" action. + + Swagger operation ID: `JoinHubSite`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + hub_site_id: Id of the hub site. + approval_token: Approval token for this request. + approval_correlation_id: Approval correlation identifier for this + request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2728,7 +3555,7 @@ async def join_hub_site_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -2742,11 +3569,12 @@ async def join_hub_site_async( request_url, response.status, response.text, + response=response, ) - async def move_file_async( + def move_file( self, - input: MoveFileParameters, + input: MoveFileParameters | Mapping[str, Any], dataset: str, *, timeout: Optional[float] = None, @@ -2760,6 +3588,23 @@ async def move_file_async( Moves a file. Works in a similar way to the \"Move to\" command in SharePoint libraries. Returns information about the new file after move. + + Swagger operation ID: `MoveFileAsync`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2768,7 +3613,7 @@ async def move_file_async( f"/moveFileAsync" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2782,6 +3627,7 @@ async def move_file_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2789,9 +3635,9 @@ async def move_file_async( return json.loads(response.text) - async def move_folder_async( + def move_folder( self, - input: MoveFolderParameters, + input: MoveFolderParameters | Mapping[str, Any], dataset: str, *, timeout: Optional[float] = None, @@ -2805,6 +3651,23 @@ async def move_folder_async( Moves a folder. Works in a similar way to the \"Move to\" command in SharePoint libraries. Returns information about the new folder after move. + + Swagger operation ID: `MoveFolderAsync`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2813,7 +3676,7 @@ async def move_folder_async( f"/moveFolderAsync" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2827,6 +3690,7 @@ async def move_folder_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2834,11 +3698,11 @@ async def move_folder_async( return json.loads(response.text) - async def notify_hub_site_join_approval_started_async( + def notify_hub_site_join_approval_started( self, dataset: str, - approval_correlation_id: Optional[str] = None, *, + approval_correlation_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2851,6 +3715,23 @@ async def notify_hub_site_join_approval_started_async( Approval Correlation Id is an optional parameter that helps SharePoint identify a particular hub join request. The requesting site can only have one pending request at a given time. + + Swagger operation ID: `NotifyHubSiteJoinApprovalStarted`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + approval_correlation_id: Approval correlation identifier for this + request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2867,7 +3748,7 @@ async def notify_hub_site_join_approval_started_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -2881,9 +3762,10 @@ async def notify_hub_site_join_approval_started_async( request_url, response.status, response.text, + response=response, ) - async def get_tables_async( + def list_tables( self, dataset: str, *, @@ -2891,41 +3773,81 @@ async def get_tables_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get lists Gets SharePoint lists from a site. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTables`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/datasets/{quote(quote(str(dataset), safe=''), safe='')}/tables" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def create_new_document_set_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def create_new_document_set( self, - input: CreateNewDocumentSetParameters, + input: CreateNewDocumentSetParameters | Mapping[str, Any], dataset: str, table: str, *, @@ -2938,6 +3860,24 @@ async def create_new_document_set_async( Create new document set Creates a new document set list item. + + Swagger operation ID: `CreateNewDocumentSet`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2948,7 +3888,7 @@ async def create_new_document_set_async( f"/createnewdocumentset" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2962,6 +3902,7 @@ async def create_new_document_set_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2969,13 +3910,13 @@ async def create_new_document_set_async( return json.loads(response.text) - async def create_new_folder_async( + def create_new_folder( self, - input: CreateNewFolderParameters, + input: CreateNewFolderParameters | Mapping[str, Any], dataset: str, table: str, - view: Optional[str] = None, *, + view: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2985,6 +3926,26 @@ async def create_new_folder_async( Create new folder Creates a new folder or folder path. + + Swagger operation ID: `CreateNewFolder`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list or library name. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3003,7 +3964,7 @@ async def create_new_folder_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3017,6 +3978,7 @@ async def create_new_folder_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3024,14 +3986,14 @@ async def create_new_folder_async( return json.loads(response.text) - async def search_for_user_async( + def search_for_user( self, dataset: str, table: str, entity_id: str, search_value: str, - view: Optional[str] = None, *, + view: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3043,6 +4005,26 @@ async def search_for_user_async( Returns a single matching user value so it can be assigned to a column of type person. If there are no matches, or multiple matches, this action will error out. + + Swagger operation ID: `SearchForUser`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: Pick the list or library that the column is in. + entity_id: Pick the column you want to assign the value to. + search_value: Use the email address, or the full name of the user. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3067,7 +4049,7 @@ async def search_for_user_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3081,6 +4063,7 @@ async def search_for_user_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3088,7 +4071,7 @@ async def search_for_user_async( return json.loads(response.text) - async def get_table_form_async( + def get_table_form( self, dataset: str, table: str, @@ -3108,6 +4091,23 @@ async def get_table_form_async( part of AI in SharePoint Public Preview. For more info on getting started, see: https://learn.microsoft.com/sharepoint/dev/declarative-customization/structured-documents. + + Swagger operation ID: `GetTableForm`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + form: Form identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3119,7 +4119,7 @@ async def get_table_form_async( f"/{quote(quote(str(form), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3133,6 +4133,7 @@ async def get_table_form_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3140,14 +4141,14 @@ async def get_table_form_async( return json.loads(response.text) - async def submit_doc_gen_form_async( + def submit_doc_gen_form( self, - input: SubmitDocGenFormInput, + input: SubmitDocGenFormInput | Mapping[str, Any], dataset: str, table: str, form: str, - view: Optional[str] = None, *, + view: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3161,6 +4162,26 @@ async def submit_doc_gen_form_async( data source. Document generation forms is a part of AI in SharePoint Public Preview. For more info on getting started, see: https://learn.microsoft.com/sharepoint/dev/declarative-customization/structured-documents. + + Swagger operation ID: `SubmitDocGenForm`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint document library name. + form: Form identifier. + view: This parameter does nothing. Please do not use. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3181,7 +4202,7 @@ async def submit_doc_gen_form_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3195,6 +4216,7 @@ async def submit_doc_gen_form_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3202,22 +4224,22 @@ async def submit_doc_gen_form_async( return json.loads(response.text) - async def get_file_items_async( + def list_file_items( self, dataset: str, table: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, folder_path: Optional[str] = None, view_scope_option: Optional[str] = None, view: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get files (properties only) @@ -3228,8 +4250,35 @@ async def get_file_items_async( On-Premises Data Gateway, the name of the library to connect to may need to be entered manually. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetFileItems`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + folder_path: Select a folder, or leave blank for the whole library. + view_scope_option: Return entries contained in sub-folders (default + = true). + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3272,11 +4321,18 @@ async def get_file_items_async( query_params.append(f"view={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -3289,45 +4345,81 @@ async def get_file_items_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_items_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def list_items( self, dataset: str, table: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, folder_path: Optional[str] = None, view_scope_option: Optional[str] = None, view: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get items Gets items from a SharePoint list. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItems`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + top: Total number of entries to retrieve (default = all). + folder_path: Select a folder, or leave blank for the whole list. + view_scope_option: Return entries contained in sub-folders (default + = true). + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3370,11 +4462,18 @@ async def get_items_async( query_params.append(f"view={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -3387,29 +4486,38 @@ async def get_items_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def post_item_async( + return ItemPaged(get_next, extract_data) + + def post_item( self, - input: PostItemInput, + input: PostItemInput | Mapping[str, Any], dataset: str, table: str, - view: Optional[str] = None, *, + view: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3419,6 +4527,26 @@ async def post_item_async( Create item Creates a new item in a SharePoint list. + + Swagger operation ID: `PostItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3437,7 +4565,7 @@ async def post_item_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3451,6 +4579,7 @@ async def post_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3458,13 +4587,13 @@ async def post_item_async( return json.loads(response.text) - async def get_item_async( + def get_item( self, dataset: str, table: str, id: int, - view: Optional[str] = None, *, + view: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3474,6 +4603,25 @@ async def get_item_async( Get item Gets a single item by its id from a SharePoint list. + + Swagger operation ID: `GetItem`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + id: Unique identifier of item to be retrieved. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3493,7 +4641,7 @@ async def get_item_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3507,6 +4655,7 @@ async def get_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3514,7 +4663,7 @@ async def get_item_async( return json.loads(response.text) - async def delete_item_async( + def delete_item( self, dataset: str, table: str, @@ -3529,6 +4678,23 @@ async def delete_item_async( Delete item Deletes an item from a SharePoint list. + + Swagger operation ID: `DeleteItem`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + id: Unique identifier of item to be deleted. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3540,7 +4706,7 @@ async def delete_item_async( f"/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -3554,16 +4720,17 @@ async def delete_item_async( request_url, response.status, response.text, + response=response, ) - async def patch_item_async( + def patch_item( self, - input: PatchItemInput, + input: PatchItemInput | Mapping[str, Any], dataset: str, table: str, id: int, - view: Optional[str] = None, *, + view: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3573,6 +4740,27 @@ async def patch_item_async( Update item Updates an item in a SharePoint list. + + Swagger operation ID: `PatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + id: Unique identifier of item to be updated. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3592,7 +4780,7 @@ async def patch_item_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -3606,6 +4794,7 @@ async def patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3613,9 +4802,9 @@ async def patch_item_async( return json.loads(response.text) - async def create_approval_request_async( + def create_approval_request( self, - input: CreateApprovalRequestInput, + input: CreateApprovalRequestInput | Mapping[str, Any], dataset: str, table: str, id: int, @@ -3630,6 +4819,26 @@ async def create_approval_request_async( Create an approval request for an item or file Creates an approval request for an item or file. + + Swagger operation ID: `CreateApprovalRequest`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list or library name. + id: Id of the item the approval request is being created for. + approval_type: Select an approval type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3649,7 +4858,7 @@ async def create_approval_request_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3663,6 +4872,7 @@ async def create_approval_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3670,16 +4880,16 @@ async def create_approval_request_async( return json.loads(response.text) - async def get_item_changes_async( + def get_item_changes( self, dataset: str, table: str, id: int, since: str, + *, until: Optional[str] = None, include_drafts: Optional[bool] = None, view: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3690,6 +4900,31 @@ async def get_item_changes_async( Returns information about columns that have changed within a given time window. Note: The list must have Versioning turned on. + + Swagger operation ID: `GetItemChanges`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list or library name. + id: Id of the item you want to fetch changes for. + since: Trigger Window Start token or an item version label (ex: + 3.0) or an ISO 8601 date (YYYY-MM-DDThh:mmZ). + until: Trigger Window End token or an item version label (ex: 3.0) + or an ISO 8601 date (YYYY-MM-DDThh:mmZ). If blank, defaults to + latest version. + include_drafts: Boolean for whether to consider changes from minor + (draft) versions. + view: Returns only columns defined in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3724,7 +4959,7 @@ async def get_item_changes_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -3738,6 +4973,7 @@ async def get_item_changes_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3745,9 +4981,9 @@ async def get_item_changes_async( return json.loads(response.text) - async def check_in_file_async( + def check_in_file( self, - input: FileCheckInParameters, + input: FileCheckInParameters | Mapping[str, Any], dataset: str, table: str, id: int, @@ -3762,6 +4998,25 @@ async def check_in_file_async( Check in a checked out file in a document library, which makes the version of the document available to others. + + Swagger operation ID: `CheckInFile`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + id: Id of the list item the file is attached to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3774,7 +5029,7 @@ async def check_in_file_async( f"/checkinfile" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3788,9 +5043,10 @@ async def check_in_file_async( request_url, response.status, response.text, + response=response, ) - async def check_out_file_async( + def check_out_file( self, dataset: str, table: str, @@ -3807,6 +5063,23 @@ async def check_out_file_async( Check out a file in a document library to prevent others from editing the document, and your changes from being visible until the documented is checked in. + + Swagger operation ID: `CheckOutFile`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + id: Id of the list item the file is attached to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3819,7 +5092,7 @@ async def check_out_file_async( f"/checkoutfile" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -3833,9 +5106,10 @@ async def check_out_file_async( request_url, response.status, response.text, + response=response, ) - async def discard_file_check_out_async( + def discard_file_check_out( self, dataset: str, table: str, @@ -3855,6 +5129,23 @@ async def discard_file_check_out_async( versions, a new version is created each time you check a file back into the library. By discarding the checkout, you can avoid making new versions when you haven't made any changes to the file. + + Swagger operation ID: `DiscardFileCheckOut`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + id: Id of the list item the file is attached to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3867,7 +5158,7 @@ async def discard_file_check_out_async( f"/discardfilecheckout" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -3881,15 +5172,16 @@ async def discard_file_check_out_async( request_url, response.status, response.text, + response=response, ) - async def get_file_item_async( + def get_file_item( self, dataset: str, table: str, id: int, - view: Optional[str] = None, *, + view: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -3904,6 +5196,25 @@ async def get_file_item_async( the contents of the file. When using this with the On-Premises Data Gateway, the name of the library to connect to may need to be entered manually. + + Swagger operation ID: `GetFileItem`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + id: Unique identifier of item to be retrieved. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3924,7 +5235,7 @@ async def get_file_item_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3938,6 +5249,7 @@ async def get_file_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3945,9 +5257,9 @@ async def get_file_item_async( return json.loads(response.text) - async def grant_access_async( + def grant_access( self, - input: ItemGrantAccessBody, + input: ItemGrantAccessBody | Mapping[str, Any], dataset: str, table: str, id: int, @@ -3961,6 +5273,26 @@ async def grant_access_async( Grant access to an item or a folder Grant access to an item or a folder in SharePoint to specific people. + + Swagger operation ID: `GrantAccess`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list or library name. + id: Unique identifier of the item or folder you want to grant + access to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3973,7 +5305,7 @@ async def grant_access_async( f"/grantaccess" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3987,16 +5319,17 @@ async def grant_access_async( request_url, response.status, response.text, + response=response, ) - async def patch_file_item_async( + def patch_file_item( self, - input: PatchFileItemInput, + input: PatchFileItemInput | Mapping[str, Any], dataset: str, table: str, id: int, - view: Optional[str] = None, *, + view: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4009,6 +5342,27 @@ async def patch_file_item_async( specified by the item id. Use \"Update file\" action to update file contents. When using this with the On-Premises Data Gateway, the name of the library to connect to may need to be entered manually. + + Swagger operation ID: `PatchFileItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + id: Unique identifier of item to be updated. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4029,7 +5383,7 @@ async def patch_file_item_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -4043,6 +5397,7 @@ async def patch_file_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4050,9 +5405,9 @@ async def patch_file_item_async( return json.loads(response.text) - async def patch_file_item_with_predicted_values_async( + def patch_file_item_with_predicted_values( self, - input: PatchFileItemWithPredictedValuesParameters, + input: PatchFileItemWithPredictedValuesParameters | Mapping[str, Any], dataset: str, table: str, id: int, @@ -4067,6 +5422,25 @@ async def patch_file_item_with_predicted_values_async( Updates the values stored in library columns for a file analyzed by the model specified by the ModelId. + + Swagger operation ID: `PatchFileItemWithPredictedValues`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: Library Name. + id: Unique identifier of item to be updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4079,7 +5453,7 @@ async def patch_file_item_with_predicted_values_async( f"/patchfileitemwithpredictedvalues" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4093,6 +5467,7 @@ async def patch_file_item_with_predicted_values_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4100,15 +5475,15 @@ async def patch_file_item_with_predicted_values_async( return json.loads(response.text) - async def set_approval_status_async( + def set_approval_status( self, dataset: str, table: str, id: int, approval_action: str, + *, comments: Optional[str] = None, entity_tag: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4121,6 +5496,26 @@ async def set_approval_status_async( has content approval turned on. You must provide an ETag for pages and files. You can get the ETag using the Get File Metadata action. This action is only available for SharePoint Online and SharePoint 2019. + + Swagger operation ID: `SetApprovalStatus`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint library name. + id: Id of the item you are setting the status of. + approval_action: Pick the approval action. + comments: Add the comments from the approver. + entity_tag: Add an ETag (required for files and pages). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4150,7 +5545,7 @@ async def set_approval_status_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -4164,6 +5559,7 @@ async def set_approval_status_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4171,7 +5567,7 @@ async def set_approval_status_async( return json.loads(response.text) - async def unshare_item_async( + def unshare_item( self, dataset: str, table: str, @@ -4187,6 +5583,23 @@ async def unshare_item_async( Delete all links giving access to an item or a file and remove all people with direct access except for owners. + + Swagger operation ID: `UnshareItem`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list or library name. + id: Unique identifier of the item or file you want to stop sharing. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4199,7 +5612,7 @@ async def unshare_item_async( f"/unshare" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -4213,9 +5626,10 @@ async def unshare_item_async( request_url, response.status, response.text, + response=response, ) - async def get_item_attachments_async( + def list_item_attachments( self, dataset: str, table: str, @@ -4225,13 +5639,34 @@ async def get_item_attachments_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get attachments Returns the list of attachments for the specified list item. You can add a \"Get attachment content\" step and use the \"File identifier\" property returned by this action to get to the contents of the file. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItemAttachments`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + item_id: Id of the list item to get attachments from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4243,29 +5678,50 @@ async def get_item_attachments_async( f"/{quote(quote(str(item_id), safe=''), safe='')}" f"/attachments" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def create_attachment_async( + return ItemPaged(get_next, extract_data) + + def create_attachment( self, input: bytes, dataset: str, @@ -4282,6 +5738,25 @@ async def create_attachment_async( Add attachment Adds a new attachment to the specified list item. + + Swagger operation ID: `CreateAttachment`. + + Args: + input: The binary request body. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + item_id: Id of the list item to attach the file to. + display_name: File name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4301,7 +5776,7 @@ async def create_attachment_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -4318,6 +5793,7 @@ async def create_attachment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4325,7 +5801,7 @@ async def create_attachment_async( return json.loads(response.text) - async def delete_attachment_async( + def delete_attachment( self, dataset: str, table: str, @@ -4341,6 +5817,24 @@ async def delete_attachment_async( Delete attachment Deletes the specified attachment. + + Swagger operation ID: `DeleteAttachment`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + item_id: Id of the list item the file is attached to. + attachment_id: File identifier for the attachment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4354,7 +5848,7 @@ async def delete_attachment_async( f"/{quote(str(attachment_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -4368,9 +5862,10 @@ async def delete_attachment_async( request_url, response.status, response.text, + response=response, ) - async def get_attachment_content_async( + def get_attachment_content( self, dataset: str, table: str, @@ -4387,6 +5882,24 @@ async def get_attachment_content_async( Returns file contents using the file identifier. The contents can be copied somewhere else, or be used as an attachment. + + Swagger operation ID: `GetAttachmentContent`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + item_id: Id of the list item the file is attached to. + attachment_id: File identifier for the attachment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4401,7 +5914,7 @@ async def get_attachment_content_async( f"/$value" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4415,20 +5928,21 @@ async def get_attachment_content_async( request_url, response.status, response.text, + response=response, ) return response.content - async def create_content_assembly_document_async( + def create_content_assembly_document( self, - input: CreateContentAssemblyDocumentInput, + input: CreateContentAssemblyDocumentInput | Mapping[str, Any], dataset: str, table: str, template: str, + *, folder_path: Optional[str] = None, file_name: Optional[str] = None, view: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4441,6 +5955,28 @@ async def create_content_assembly_document_async( Microsoft Syntex. This preview requires a Syntex license. Pricing is subject to change. For more info see: https://docs.microsoft.com/en-us/microsoft-365/contentunderstanding/content-assembly. + + Swagger operation ID: `CreateContentAssemblyDocument`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint document library name. + template: Document template. + folder_path: Must start with an existing library. + file_name: Document file name. + view: This parameter does nothing. Please do not use. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4471,7 +6007,7 @@ async def create_content_assembly_document_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4485,6 +6021,7 @@ async def create_content_assembly_document_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4492,7 +6029,7 @@ async def create_content_assembly_document_async( return json.loads(response.text) - async def get_table_views_async( + def list_table_views( self, dataset: str, table: str, @@ -4501,11 +6038,31 @@ async def get_table_views_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get list views Gets views from a SharePoint list. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTableViews`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4515,35 +6072,56 @@ async def get_table_views_async( f"/{quote(quote(str(table), safe=''), safe='')}" f"/views" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def extract_folder_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def extract_folder( self, dataset: str, source: str, destination: str, - overwrite: Optional[bool] = None, *, + overwrite: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4553,6 +6131,25 @@ async def extract_folder_async( Extract folder Extracts an archive file into a SharePoint folder (example: .zip). + + Swagger operation ID: `ExtractFolderV2`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + source: Path to the source file. + destination: Path to the destination folder. + overwrite: Whether or not to overwrite the destination file if it + exists. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4578,7 +6175,7 @@ async def extract_folder_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -4592,6 +6189,7 @@ async def extract_folder_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4599,43 +6197,82 @@ async def extract_folder_async( return json.loads(response.text) - async def get_data_sets_async( + def list_data_sets( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get datasets Gets the most recently used SharePoint sites. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetDataSets`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/datasets" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_agreements_solution_templates_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_agreements_solution_templates( self, dataset: str, *, @@ -4643,11 +6280,30 @@ async def get_agreements_solution_templates_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Agreements Solution - Get Templates Gets templates from a Agreements Solution workspace. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAgreementsSolutionTemplates`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4656,29 +6312,50 @@ async def get_agreements_solution_templates_async( f"/agreements" f"/templates" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def get_agreements_solution_template_fields_async( + return ItemPaged(get_next, extract_data) + + def get_agreements_solution_template_fields( self, dataset: str, template: str, @@ -4692,6 +6369,22 @@ async def get_agreements_solution_template_fields_async( Agreements Solution - Get template fields Gets fields from template in a Agreements Solution workspace. + + Swagger operation ID: `GetAgreementsSolutionTemplateFields`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + template: Agreements Solution template. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4703,7 +6396,7 @@ async def get_agreements_solution_template_fields_async( f"/fields" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4717,6 +6410,7 @@ async def get_agreements_solution_template_fields_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4724,7 +6418,7 @@ async def get_agreements_solution_template_fields_async( return json.loads(response.text) - async def get_tables_for_libraries_async( + def list_tables_for_libraries( self, dataset: str, *, @@ -4732,11 +6426,30 @@ async def get_tables_for_libraries_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get libraries Get libraries + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTablesForLibraries`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4745,29 +6458,50 @@ async def get_tables_for_libraries_async( f"/tablesfor" f"/libraries" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def get_thumbnail_size_options_async( + return ItemPaged(get_next, extract_data) + + def get_thumbnail_size_options( self, *, timeout: Optional[float] = None, @@ -4779,10 +6513,24 @@ async def get_thumbnail_size_options_async( Get thumbnail size options Internal operation to get thumbnail size options. + + Swagger operation ID: `GetThumbnailSizeOptions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/getThumbnailSizeOptions" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4796,6 +6544,7 @@ async def get_thumbnail_size_options_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4803,13 +6552,13 @@ async def get_thumbnail_size_options_async( return json.loads(response.text) - async def get_table_async( + def get_table( self, dataset: str, table: str, + *, view: Optional[str] = None, content_type_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -4819,6 +6568,25 @@ async def get_table_async( Get list metadata Gets metadata from a SharePoint list. + + Swagger operation ID: `GetTable`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + view: Avoid column threshold issues by only using columns defined + in a view. + content_type_id: Contentype Id to filter columns by content type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4842,7 +6610,7 @@ async def get_table_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4856,6 +6624,7 @@ async def get_table_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4863,7 +6632,7 @@ async def get_table_async( return json.loads(response.text) - async def get_tables_for_lists_and_libraries_async( + def list_tables_for_lists_and_libraries( self, dataset: str, *, @@ -4871,11 +6640,30 @@ async def get_tables_for_lists_and_libraries_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get lists and libraries Get lists and libraries + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTablesForListsAndLibraries`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4884,43 +6672,86 @@ async def get_tables_for_lists_and_libraries_async( f"/tablesfor" f"/listsandlibraries" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def get_entities_for_user_async( - self, - dataset: str, + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_entities_for_user( + self, + dataset: str, table: str, - view: Optional[str] = None, *, + view: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Returns User fields for a list Returns User fields for a list. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetEntitiesForUser`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + view: Avoid column threshold issues by only using columns defined + in a view. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4939,29 +6770,50 @@ async def get_entities_for_user_async( query_params.append(f"view={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def get_table_forms_async( + return ItemPaged(get_next, extract_data) + + def list_table_forms( self, dataset: str, table: str, @@ -4970,11 +6822,31 @@ async def get_table_forms_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get list forms Gets forms from a SharePoint list. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTableForms`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4984,29 +6856,50 @@ async def get_table_forms_async( f"/{quote(quote(str(table), safe=''), safe='')}" f"/forms" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def get_doc_gen_forms_async( + return ItemPaged(get_next, extract_data) + + def list_doc_gen_forms( self, dataset: str, table: str, @@ -5015,12 +6908,32 @@ async def get_doc_gen_forms_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get document generation forms Gets published document generation forms from a SharePoint document library. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetDocGenForms`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint document library name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5030,29 +6943,50 @@ async def get_doc_gen_forms_async( f"/{quote(quote(str(table), safe=''), safe='')}" f"/docgenforms" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def get_doc_gen_form_fields_async( + return ItemPaged(get_next, extract_data) + + def get_doc_gen_form_fields( self, dataset: str, table: str, @@ -5067,6 +7001,23 @@ async def get_doc_gen_form_fields_async( Get document generation form fields Gets fields from a document generation form in a SharePoint list. + + Swagger operation ID: `GetDocGenFormFields`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list name. + form: Form identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5079,7 +7030,7 @@ async def get_doc_gen_form_fields_async( f"/fields" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5093,6 +7044,7 @@ async def get_doc_gen_form_fields_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5100,45 +7052,84 @@ async def get_doc_gen_form_fields_async( return json.loads(response.text) - async def get_view_scope_options_async( + def list_view_scope_options( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get SPViewScope options to use for folder querying behavior Default - Only query current folder (non-recursive). Return both Files and Folders. RecursiveAll - Recursively query the folder. Return both Files and Folders. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetViewScopeOptions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/getViewScopeOptions" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def get_tables_for_lightweight_approval_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_tables_for_lightweight_approval( self, dataset: str, *, @@ -5146,11 +7137,30 @@ async def get_tables_for_lightweight_approval_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get lists and libraries where lightweight approvals is enabled Get lists and libraries where lightweight approvals is enabled + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTablesForLightweightApproval`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5159,29 +7169,50 @@ async def get_tables_for_lightweight_approval_async( f"/tablesfor" f"/lightweightapproval" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_approval_types_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_approval_types( self, *, timeout: Optional[float] = None, @@ -5193,10 +7224,24 @@ async def get_approval_types_async( Get available approval request types Internal operation to get the available approval request types. + + Swagger operation ID: `GetApprovalTypes`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/getApprovalTypes" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5210,6 +7255,7 @@ async def get_approval_types_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5217,7 +7263,7 @@ async def get_approval_types_async( return json.loads(response.text) - async def get_approval_schema_async( + def get_approval_schema( self, approval_type: int, *, @@ -5231,6 +7277,21 @@ async def get_approval_schema_async( Internal operation to fetch the schema for approval request creation based on the approval type. + + Swagger operation ID: `GetApprovalSchema`. + + Args: + approval_type: Type of approval request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/getApprovalSchema" query_params = [] @@ -5241,7 +7302,7 @@ async def get_approval_schema_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5255,6 +7316,7 @@ async def get_approval_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5262,7 +7324,7 @@ async def get_approval_schema_async( return json.loads(response.text) - async def get_item_changes_metadata_async( + def get_item_changes_metadata( self, dataset: str, table: str, @@ -5276,6 +7338,22 @@ async def get_item_changes_metadata_async( Get metadata about the return type of the GetItemChanges operation Get metadata about the return type of the GetItemChanges operation. + + Swagger operation ID: `GetItemChangesMetadata`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint list or library name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5288,7 +7366,7 @@ async def get_item_changes_metadata_async( f"/changes" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5302,6 +7380,7 @@ async def get_item_changes_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5309,7 +7388,7 @@ async def get_item_changes_metadata_async( return json.loads(response.text) - async def get_tables_for_approval_async( + def list_tables_for_approval( self, dataset: str, *, @@ -5317,11 +7396,30 @@ async def get_tables_for_approval_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get libraries where Content Approval is supported Get libraries where Content Approval is supported + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTablesForApproval`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5330,29 +7428,50 @@ async def get_tables_for_approval_async( f"/tablesfor" f"/approval" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - async def get_day_of_week_options_async( + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_day_of_week_options( self, *, timeout: Optional[float] = None, @@ -5364,10 +7483,24 @@ async def get_day_of_week_options_async( When to send updates Internal operation to get day of week options. + + Swagger operation ID: `GetDayOfWeekOptions`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/getDayOfWeekOptions" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5381,6 +7514,7 @@ async def get_day_of_week_options_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5388,7 +7522,7 @@ async def get_day_of_week_options_async( return json.loads(response.text) - async def get_content_assembly_templates_async( + def list_content_assembly_templates( self, dataset: str, table: str, @@ -5397,11 +7531,31 @@ async def get_content_assembly_templates_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get document library templates Gets templates from a SharePoint document library. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetContentAssemblyTemplates`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint document library name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5411,29 +7565,50 @@ async def get_content_assembly_templates_async( f"/{quote(quote(str(table), safe=''), safe='')}" f"/templates" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def get_content_assembly_placeholders_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_content_assembly_placeholders( self, dataset: str, table: str, @@ -5448,6 +7623,23 @@ async def get_content_assembly_placeholders_async( Get placeholders from template Gets placeholders from template in a SharePoint document library. + + Swagger operation ID: `GetContentAssemblyPlaceholders`. + + Args: + dataset: Example: https://contoso.sharepoint.com/sites/sitename. + table: SharePoint document library name. + template: Document template. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5460,7 +7652,7 @@ async def get_content_assembly_placeholders_async( f"/placeholders" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5474,6 +7666,7 @@ async def get_content_assembly_placeholders_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/shifts.py b/src/azure/connectors/shifts.py index efbf2d0..05ec936 100644 --- a/src/azure/connectors/shifts.py +++ b/src/azure/connectors/shifts.py @@ -5,21 +5,84 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Literal, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Literal, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "ShiftsClient", + "Activities", + "CreateShiftRequest", + "CreateTimeOffRequest", + "DraftOpenShift", + "DraftShift", + "DraftTimeOff", + "EditOpenShiftRequest", + "GetAllTeamsResponse", + "GetTimeOffReasonsResponse", + "ListOfferShiftRequestsResponse", + "ListOpenShiftChangeRequestsResponse", + "ListOpenShiftsCrossTeamResponse", + "ListOpenShiftsResponse", + "ListSchedulingGroupsResponse", + "ListShiftsCrossTeamResponse", + "ListShiftsResponse", + "ListSwapShiftsChangeRequestsResponse", + "ListTimeOffRequestsResponse", + "ListTimesOffCrossTeamResponse", + "ListTimesOffResponse", + "OfferShiftRequestApproveInput", + "OfferShiftRequestApproveResponse", + "OfferShiftRequestDeclineInput", + "OfferShiftRequestDeclineResponse", + "OfferShiftRequestResponse", + "OpenShiftChangeRequestApproveInput", + "OpenShiftChangeRequestApproveResponse", + "OpenShiftChangeRequestDeclineInput", + "OpenShiftChangeRequestDeclineResponse", + "OpenShiftChangeRequestResponse", + "OpenShiftResponse", + "ScheduleResponse", + "SchedulingGroupInfo", + "SchedulingGroupResponse", + "SharedOpenShift", + "SharedShift", + "SharedTimeOff", + "ShiftResponse", + "Subscription", + "SwapShiftsChangeRequestApproveInput", + "SwapShiftsChangeRequestApproveResponse", + "SwapShiftsChangeRequestDeclineInput", + "SwapShiftsChangeRequestDeclineResponse", + "SwapShiftsChangeRequestResponse", + "TeamInfo", + "Theme", + "TimeOffRequestApproveInput", + "TimeOffRequestApproveResponse", + "TimeOffRequestDeclineInput", + "TimeOffRequestDeclineResponse", + "TimeOffRequestResponse", + "TimeOffResponse", + "UserInfo", + "WebHookRequest", + "WebhookNotificationEntity", + "WebhookPushResponse", + "WebhookPushResponseResourceEntity", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,20 +92,23 @@ class ScheduleResponse: Response for Get a Schedule's details """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the Schedule.""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "timeZone"}, ) """The Time Zone of the Schedule.""" - provision_status: Optional[str] = field( + provision_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "provisionStatus"}, ) """The Provision Status of the Schedule.""" - provision_status_code: Optional[str] = field( + provision_status_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "provisionStatusCode"}, ) """The Provision Status Code of the Schedule.""" @@ -54,14 +120,21 @@ class ListTimesOffResponse: Response for List all Time Off instances in a team """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[TimeOffResponse]] = None + value: Optional[ + List[TimeOffResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Time Off instances""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -73,37 +146,44 @@ class TimeOffResponse: Response for Create a new Time Off instance """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the Time Off.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - user_id: Optional[str] = field( + user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userId"}, ) """Assigned To User ID.""" - user_info: Optional[UserInfo] = field( + user_info: Optional[UserInfo | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userInfo"}, ) - team_info: Optional[TeamInfo] = field( + team_info: Optional[TeamInfo | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "teamInfo"}, ) - shared_time_off: Optional[SharedTimeOff] = field( + shared_time_off: Optional[SharedTimeOff | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sharedTimeOff"}, ) - draft_time_off: Optional[DraftTimeOff] = field( + draft_time_off: Optional[DraftTimeOff | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "draftTimeOff"}, ) @@ -114,14 +194,21 @@ class ListShiftsResponse: Response for List all Shifts in a team """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[ShiftResponse]] = None + value: Optional[ + List[ShiftResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Shifts""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -133,46 +220,55 @@ class ShiftResponse: Response for Create a new Shift """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the Shift.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - user_id: Optional[str] = field( + user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userId"}, ) """Assigned To User ID.""" - scheduling_group_id: Optional[str] = field( + scheduling_group_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "schedulingGroupId"}, ) """Scheduling Group ID.""" - scheduling_group_info: Optional[SchedulingGroupInfo] = field( + scheduling_group_info: Optional[SchedulingGroupInfo | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "schedulingGroupInfo"}, ) - user_info: Optional[UserInfo] = field( + user_info: Optional[UserInfo | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userInfo"}, ) - team_info: Optional[TeamInfo] = field( + team_info: Optional[TeamInfo | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "teamInfo"}, ) - shared_shift: Optional[SharedShift] = field( + shared_shift: Optional[SharedShift | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sharedShift"}, ) - draft_shift: Optional[DraftShift] = field( + draft_shift: Optional[DraftShift | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "draftShift"}, ) @@ -183,14 +279,21 @@ class ListOpenShiftsResponse: Response for List all Open Shifts in a team """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[OpenShiftResponse]] = None + value: Optional[ + List[OpenShiftResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Open Shifts""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -202,37 +305,44 @@ class OpenShiftResponse: Response for Create a new Open Shift """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the Open Shift.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - scheduling_group_id: Optional[str] = field( + scheduling_group_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "schedulingGroupId"}, ) """Scheduling Group ID""" - scheduling_group_info: Optional[SchedulingGroupInfo] = field( + scheduling_group_info: Optional[SchedulingGroupInfo | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "schedulingGroupInfo"}, ) - team_info: Optional[TeamInfo] = field( + team_info: Optional[TeamInfo | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "teamInfo"}, ) - shared_open_shift: Optional[SharedOpenShift] = field( + shared_open_shift: Optional[SharedOpenShift | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sharedOpenShift"}, ) - draft_open_shift: Optional[DraftOpenShift] = field( + draft_open_shift: Optional[DraftOpenShift | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "draftOpenShift"}, ) @@ -243,14 +353,16 @@ class GetTimeOffReasonsResponse: Response for List all Time Off Reasons in a team """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """The list of Time Off Reasons.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -262,14 +374,21 @@ class ListSchedulingGroupsResponse: Response for List all Scheduling Groups in a team """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[SchedulingGroupResponse]] = None + value: Optional[ + List[SchedulingGroupResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Scheduling Groups.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -281,23 +400,26 @@ class SchedulingGroupResponse: Response for Get a Scheduling Group """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the Scheduling Group.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The display name for the Scheduling Group.""" - is_active: Optional[bool] = field( + is_active: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isActive"}, ) """ Indicates whether the Scheduling Group can be used when creating new entities or updating existing ones. """ - user_ids: Optional[List[str]] = field( + user_ids: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userIds"}, ) """List of IDs of users in the Scheduling Group.""" @@ -309,14 +431,21 @@ class ListTimeOffRequestsResponse: Response for List all Time Off requests in a team """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[TimeOffRequestResponse]] = None + value: Optional[ + List[TimeOffRequestResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Time Off requests.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -328,67 +457,79 @@ class TimeOffRequestResponse: Response for Get a Time Off request """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the Time Off request.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - assigned_to: Optional[str] = field( + assigned_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignedTo"}, ) """The person the request is assigned to: 'manager' or 'recipient'""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """'approved', 'pending' or 'declined'""" - sender_date_time: Optional[str] = field( + sender_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderDateTime"}, ) """Time when the request was sent""" - sender_message: Optional[str] = field( + sender_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderMessage"}, ) """The message from the request sender""" - sender_user_id: Optional[str] = field( + sender_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderUserId"}, ) """The ID of the user that sent the request""" - manager_action_date_time: Optional[str] = field( + manager_action_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionDateTime"}, ) """Time when the manager responded""" - manager_action_message: Optional[str] = field( + manager_action_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionMessage"}, ) """The message from the manager""" - manager_user_id: Optional[str] = field( + manager_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerUserId"}, ) """The ID of the manager that responded""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """Start of time requested off""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """End of time requested off""" - time_off_reason_id: Optional[str] = field( + time_off_reason_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "timeOffReasonId"}, ) """The ID of the Time Off Reason""" @@ -400,7 +541,7 @@ class TimeOffRequestApproveInput: Approve a Time Off request """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """ A message from the manager to the sender/recipient when a request is accepted. @@ -413,7 +554,7 @@ class TimeOffRequestApproveResponse: Response for Approve a Time Off request """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -426,7 +567,7 @@ class TimeOffRequestDeclineInput: Decline a Time Off request """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """ A message from the manager to the sender/recipient when a request is declined. @@ -439,7 +580,7 @@ class TimeOffRequestDeclineResponse: Response for Decline a Time Off request """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -452,14 +593,21 @@ class ListOfferShiftRequestsResponse: Response for List all Offer Shift requests in a team """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[OfferShiftRequestResponse]] = None + value: Optional[ + List[OfferShiftRequestResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Offer Shift requests.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -471,72 +619,85 @@ class OfferShiftRequestResponse: Response for Get an Offer Shift request """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the Offer Shift request.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - assigned_to: Optional[str] = field( + assigned_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignedTo"}, ) """The person the request is assigned to: 'manager' or 'recipient'""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """'approved', 'pending' or 'declined'""" - sender_date_time: Optional[str] = field( + sender_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderDateTime"}, ) """Time when the request was sent""" - sender_message: Optional[str] = field( + sender_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderMessage"}, ) """The message from the request sender""" - sender_user_id: Optional[str] = field( + sender_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderUserId"}, ) """The ID of the user that sent the request""" - sender_shift_id: Optional[str] = field( + sender_shift_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderShiftId"}, ) """The ID of the Shift from the sender""" - recipient_action_date_time: Optional[str] = field( + recipient_action_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientActionDateTime"}, ) """Time when the recipient responded""" - recipient_action_message: Optional[str] = field( + recipient_action_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientActionMessage"}, ) """The message from the recipient""" - recipient_user_id: Optional[str] = field( + recipient_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientUserId"}, ) """The ID of the recipient of the request""" - manager_action_date_time: Optional[str] = field( + manager_action_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionDateTime"}, ) """Time when the manager responded""" - manager_action_message: Optional[str] = field( + manager_action_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionMessage"}, ) """The message from the manager""" - manager_user_id: Optional[str] = field( + manager_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerUserId"}, ) """The ID of the manager that responded""" @@ -548,7 +709,7 @@ class OfferShiftRequestApproveInput: Approve an Offer Shift request """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """A message when a request is accepted.""" @@ -558,7 +719,7 @@ class OfferShiftRequestApproveResponse: Response for Approve an Offer Shift request """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -571,7 +732,7 @@ class OfferShiftRequestDeclineInput: Decline an Offer Shift request """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """A message when a request is declined.""" @@ -581,7 +742,7 @@ class OfferShiftRequestDeclineResponse: Response for Decline an Offer Shift request """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -594,14 +755,21 @@ class ListSwapShiftsChangeRequestsResponse: Response for List all Swap Shifts requests in a team """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[SwapShiftsChangeRequestResponse]] = None + value: Optional[ + List[SwapShiftsChangeRequestResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Swap Shifts Change Requests.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -613,77 +781,91 @@ class SwapShiftsChangeRequestResponse: Response for Get a Swap Shifts request """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the Swap Shift request.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - assigned_to: Optional[str] = field( + assigned_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignedTo"}, ) """The person the request is assigned to: 'manager' or 'recipient'""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """'approved', 'pending' or 'declined'""" - sender_date_time: Optional[str] = field( + sender_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderDateTime"}, ) """Time when the request was sent""" - sender_message: Optional[str] = field( + sender_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderMessage"}, ) """The message from the request sender""" - sender_user_id: Optional[str] = field( + sender_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderUserId"}, ) """The ID of the user that sent the request""" - sender_shift_id: Optional[str] = field( + sender_shift_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderShiftId"}, ) """The ID of the Shift from the sender""" - recipient_action_date_time: Optional[str] = field( + recipient_action_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientActionDateTime"}, ) """Time when the recipient responded""" - recipient_action_message: Optional[str] = field( + recipient_action_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientActionMessage"}, ) """The message from the recipient""" - recipient_user_id: Optional[str] = field( + recipient_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientUserId"}, ) """The ID of the recipient of the request""" - recipient_shift_id: Optional[str] = field( + recipient_shift_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientShiftId"}, ) """The ID of the Shift from the recipient""" - manager_action_date_time: Optional[str] = field( + manager_action_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionDateTime"}, ) """Time when the manager responded""" - manager_action_message: Optional[str] = field( + manager_action_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionMessage"}, ) """The message from the manager""" - manager_user_id: Optional[str] = field( + manager_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerUserId"}, ) """The ID of the manager that responded""" @@ -695,7 +877,7 @@ class SwapShiftsChangeRequestApproveInput: Approve a Swap Shifts request """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """A message when a request is accepted.""" @@ -705,7 +887,7 @@ class SwapShiftsChangeRequestApproveResponse: Response for Approve a Swap Shifts request """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -718,7 +900,7 @@ class SwapShiftsChangeRequestDeclineInput: Decline a Swap Shifts request """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """A message when a request is declined.""" @@ -728,7 +910,7 @@ class SwapShiftsChangeRequestDeclineResponse: Response for Decline a Swap Shifts request """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -741,14 +923,21 @@ class ListOpenShiftChangeRequestsResponse: Response for List all Open Shift requests in a team """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[OpenShiftChangeRequestResponse]] = None + value: Optional[ + List[OpenShiftChangeRequestResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Open Shift Change Requests.""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -760,57 +949,67 @@ class OpenShiftChangeRequestResponse: Response for Get an Open Shift request """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the Open Shift Change request.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - assigned_to: Optional[str] = field( + assigned_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignedTo"}, ) """The person the request is assigned to: 'manager' or 'recipient'""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """'approved', 'pending' or 'declined'""" - sender_date_time: Optional[str] = field( + sender_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderDateTime"}, ) """Time when the request was sent""" - sender_message: Optional[str] = field( + sender_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderMessage"}, ) """The message from the request sender""" - sender_user_id: Optional[str] = field( + sender_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderUserId"}, ) """The ID of the user that sent the request""" - manager_action_date_time: Optional[str] = field( + manager_action_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionDateTime"}, ) """Time when the manager responded""" - manager_action_message: Optional[str] = field( + manager_action_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionMessage"}, ) """The message from the manager""" - manager_user_id: Optional[str] = field( + manager_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerUserId"}, ) """The ID of the manager that responded""" - open_shift_id: Optional[str] = field( + open_shift_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "openShiftId"}, ) """The ID of the Open Shift being requested""" @@ -822,7 +1021,7 @@ class OpenShiftChangeRequestApproveInput: Approve an Open Shift request """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """ A message from the manager to the sender/recipient when a request is accepted. @@ -835,7 +1034,7 @@ class OpenShiftChangeRequestApproveResponse: Response for Approve an Open Shift request """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -848,7 +1047,7 @@ class OpenShiftChangeRequestDeclineInput: Decline an Open Shift request """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """ A message from the manager to the sender/recipient when a request is declined. @@ -861,7 +1060,7 @@ class OpenShiftChangeRequestDeclineResponse: Response for Decline an Open Shift request """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -874,14 +1073,21 @@ class ListOpenShiftsCrossTeamResponse: Response for List all Open Shifts from my teams """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[OpenShiftResponse]] = None + value: Optional[ + List[OpenShiftResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Open Shifts""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -893,14 +1099,21 @@ class ListShiftsCrossTeamResponse: Response for List all Shifts from my teams """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[ShiftResponse]] = None + value: Optional[ + List[ShiftResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Shifts""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -912,14 +1125,21 @@ class ListTimesOffCrossTeamResponse: Response for List all Times Off from my teams """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[TimeOffResponse]] = None + value: Optional[ + List[TimeOffResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Times off""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -931,11 +1151,12 @@ class GetAllTeamsResponse: Response for List teams """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of one or more Teams you are a part of.""" @@ -945,8 +1166,7 @@ class WebHookRequest: Definition: WebHookRequest """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "notificationUrl"}, ) """ @@ -960,7 +1180,12 @@ class WebhookPushResponse: Definition: WebhookPushResponse """ - value: Optional[List[WebhookNotificationEntity]] = None + value: Optional[ + List[WebhookNotificationEntity | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of values""" @@ -970,23 +1195,29 @@ class WebhookNotificationEntity: Definition: WebhookNotificationEntity """ - subscription_id: Optional[str] = field( + subscription_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "subscriptionId"}, ) """WebHook Subscription Id""" - expiration_date_time: Optional[str] = field( + expiration_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "expirationDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - change_type: Optional[str] = field( + change_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "changeType"}, ) """Resource change type (created/updated/deleted).""" - resource_data: Optional[WebhookPushResponseResourceEntity] = field( + resource_data: Optional[ + WebhookPushResponseResourceEntity | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resourceData"}, ) @@ -997,20 +1228,23 @@ class WebhookPushResponseResourceEntity: Definition: WebhookPushResponseResourceEntity """ - id_2: Optional[str] = field( + id_2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.id"}, ) """Full resource path.""" - type_: Optional[str] = field( + type_: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.type"}, ) """Resoure Type.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ID of the resource that is updated.""" - team_id: Optional[str] = field( + team_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "teamId"}, ) """ID of team where the update happened.""" @@ -1022,25 +1256,28 @@ class Subscription: Definition: Subscription """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier for the subscription.""" - resource: Optional[str] = None + resource: Optional[str] = dataclass_field(default=None, kw_only=True) """Specifies the resource that will be monitored for changes.""" - application_id: Optional[str] = field( + application_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "applicationId"}, ) """Identifier of the application used to create the subscription.""" - change_type: Optional[str] = field( + change_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "changeType"}, ) """ Indicates the type of change in the subscribed resource that will raise a notification. """ - client_state: Optional[str] = field( + client_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "clientState"}, ) """ @@ -1050,23 +1287,26 @@ class Subscription: clientState property sent with the subscription with the value of the clientState property received with each notification. """ - notification_url: Optional[str] = field( + notification_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notificationUrl"}, ) """ The URL of the endpoint that will receive the notifications. This URL must make use of the HTTPS protocol. """ - expiration_date_time: Optional[str] = field( + expiration_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "expirationDateTime"}, ) """ Specifies the date and time when the webhook subscription expires (UTC). """ - creator_id: Optional[str] = field( + creator_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "creatorId"}, ) """ @@ -1084,22 +1324,25 @@ class SharedTimeOff: Definition: SharedTimeOff """ - time_off_reason_id: Optional[str] = field( + time_off_reason_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "timeOffReasonId"}, ) """Time Off Reason ID.""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - theme: Optional[Theme] = None + theme: Optional[Theme] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1108,22 +1351,25 @@ class DraftTimeOff: Definition: DraftTimeOff """ - time_off_reason_id: Optional[str] = field( + time_off_reason_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "timeOffReasonId"}, ) """Time Off Reason ID.""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - theme: Optional[Theme] = None + theme: Optional[Theme] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1132,25 +1378,28 @@ class SharedShift: Definition: SharedShift """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display Name""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """Shift Notes""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - theme: Optional[Theme] = None - activities: Optional[Activities] = None + theme: Optional[Theme] = dataclass_field(default=None, kw_only=True) + activities: Optional[Activities] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1159,25 +1408,28 @@ class DraftShift: Definition: DraftShift """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display Name""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """Notes""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - theme: Optional[Theme] = None - activities: Optional[Activities] = None + theme: Optional[Theme] = dataclass_field(default=None, kw_only=True) + activities: Optional[Activities] = dataclass_field(default=None, kw_only=True) Theme = Literal[ @@ -1205,17 +1457,19 @@ class SchedulingGroupInfo: Definition: SchedulingGroupInfo """ - scheduling_group_id: Optional[str] = field( + scheduling_group_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "schedulingGroupId"}, ) """The unique ID of the Scheduling Group.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The display name for the Scheduling Group.""" - code: Optional[str] = None + code: Optional[str] = dataclass_field(default=None, kw_only=True) """The scheduling group code.""" @@ -1225,13 +1479,15 @@ class UserInfo: Definition: UserInfo """ - user_id: Optional[str] = field( + user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userId"}, ) """The ID of the user.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The display name of the user.""" @@ -1243,13 +1499,15 @@ class TeamInfo: Definition: TeamInfo """ - team_id: Optional[str] = field( + team_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "teamId"}, ) """The ID of the team.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The display name for the team.""" @@ -1261,13 +1519,15 @@ class EditOpenShiftRequest: Definition: EditOpenShiftRequest """ - scheduling_group_id: Optional[str] = field( + scheduling_group_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "schedulingGroupId"}, ) """Scheduling Group ID""" - shared_open_shift: Optional[Dict[str, Any]] = field( + shared_open_shift: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sharedOpenShift"}, ) @@ -1278,30 +1538,34 @@ class SharedOpenShift: Definition: SharedOpenShift """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display Name""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """Notes""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - theme: Optional[Theme] = None - open_slot_count: Optional[int] = field( + theme: Optional[Theme] = dataclass_field(default=None, kw_only=True) + open_slot_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "openSlotCount"}, ) """Open Slot Count""" - activities: Optional[Activities] = None + activities: Optional[Activities] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1310,30 +1574,34 @@ class DraftOpenShift: Definition: DraftOpenShift """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display Name""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """Notes""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - theme: Optional[Theme] = None - open_slot_count: Optional[int] = field( + theme: Optional[Theme] = dataclass_field(default=None, kw_only=True) + open_slot_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "openSlotCount"}, ) """Open Slot Count""" - activities: Optional[Activities] = None + activities: Optional[Activities] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1342,20 +1610,17 @@ class CreateShiftRequest: Definition: CreateShiftRequest """ - scheduling_group_id: Optional[str] = field( + scheduling_group_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "schedulingGroupId"}, ) """Scheduling Group ID""" - shared_shift: Optional[Dict[str, Any]] = field( - default=None, + shared_shift: Dict[str, Any] = dataclass_field( metadata={"wire_name": "sharedShift"}, ) """Shared version of the Shift.""" - user_id: Optional[str] = field( - default=None, - metadata={"wire_name": "userId"}, - ) + user_id: str = dataclass_field(metadata={"wire_name": "userId"}) """Assigned to User ID""" @@ -1365,15 +1630,11 @@ class CreateTimeOffRequest: Definition: CreateTimeOffRequest """ - shared_time_off: Optional[Dict[str, Any]] = field( - default=None, + shared_time_off: Dict[str, Any] = dataclass_field( metadata={"wire_name": "sharedTimeOff"}, ) """Shared version of a TimeOff.""" - user_id: Optional[str] = field( - default=None, - metadata={"wire_name": "userId"}, - ) + user_id: str = dataclass_field(metadata={"wire_name": "userId"}) """Assigned to User ID""" @@ -1385,16 +1646,16 @@ class ShiftsClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -1405,8 +1666,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -1414,8 +1675,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -1427,7 +1688,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -1449,7 +1710,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -1481,7 +1742,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def get_schedule_async( + def get_schedule( self, team_id: str, *, @@ -1495,13 +1756,28 @@ async def get_schedule_async( This operation returns details of a Schedule using the Schedule's unique ID. + + Swagger operation ID: `GetSchedule`. + + Args: + team_id: Add Team ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/teams/{quote(str(team_id), safe='')}/schedule" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1515,6 +1791,7 @@ async def get_schedule_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1522,25 +1799,44 @@ async def get_schedule_async( return json.loads(response.text) - async def list_times_off_async( + def list_times_off( self, team_id: str, + *, start_time: Optional[str] = None, end_time: Optional[str] = None, top: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List all Time Off instances in a team This operation returns all Time Off instances in a Schedule - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTimesOff`. + + Args: + team_id: Add Team ID. + start_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + end_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + top: Items per page (enable Pagination under .../Settings). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1564,11 +1860,18 @@ async def list_times_off_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1581,25 +1884,34 @@ async def list_times_off_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def create_time_off_async( + return ItemPaged(get_next, extract_data) + + def create_time_off( self, - input: CreateTimeOffRequest, + input: CreateTimeOffRequest | Mapping[str, Any], team_id: str, *, timeout: Optional[float] = None, @@ -1612,13 +1924,30 @@ async def create_time_off_async( This operation creates a new Time Off instance and assigns it to a member of the team + + Swagger operation ID: `CreateTimeOff`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/teams/{quote(str(team_id), safe='')}/schedule/timesoff" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1632,6 +1961,7 @@ async def create_time_off_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1639,7 +1969,7 @@ async def create_time_off_async( return json.loads(response.text) - async def get_time_off_async( + def get_time_off( self, team_id: str, time_off_id: str, @@ -1653,6 +1983,22 @@ async def get_time_off_async( Get a Time Off instance This operation returns details for a Time Off using its unique ID. + + Swagger operation ID: `GetTimeOff`. + + Args: + team_id: Add Team ID. + time_off_id: The unique ID of the Time Off. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1664,7 +2010,7 @@ async def get_time_off_async( f"/{quote(str(time_off_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1678,6 +2024,7 @@ async def get_time_off_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1685,7 +2032,7 @@ async def get_time_off_async( return json.loads(response.text) - async def delete_time_off_async( + def delete_time_off( self, team_id: str, time_off_id: str, @@ -1699,6 +2046,22 @@ async def delete_time_off_async( Delete a Time Off instance This operation deletes a Time Off using its unique ID. + + Swagger operation ID: `DeleteTimeOff`. + + Args: + team_id: Add Team ID. + time_off_id: The unique ID of the Time Off. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1710,7 +2073,7 @@ async def delete_time_off_async( f"/{quote(str(time_off_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1724,27 +2087,47 @@ async def delete_time_off_async( request_url, response.status, response.text, + response=response, ) - async def list_shifts_async( + def list_shifts( self, team_id: str, + *, start_time: Optional[str] = None, end_time: Optional[str] = None, top: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List all Shifts in a team This operation returns all Shifts assigned to members of a team - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListShifts`. + + Args: + team_id: Add Team ID. + start_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + end_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + top: Items per page (enable Pagination under .../Settings). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1768,11 +2151,18 @@ async def list_shifts_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1785,25 +2175,34 @@ async def list_shifts_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def create_shift_async( + return ItemPaged(get_next, extract_data) + + def create_shift( self, - input: CreateShiftRequest, + input: CreateShiftRequest | Mapping[str, Any], team_id: str, *, timeout: Optional[float] = None, @@ -1816,13 +2215,30 @@ async def create_shift_async( This operation creates a new Shift and assigns it to a member of the team + + Swagger operation ID: `CreateShift`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/teams/{quote(str(team_id), safe='')}/schedule/shifts" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1836,6 +2252,7 @@ async def create_shift_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1843,7 +2260,7 @@ async def create_shift_async( return json.loads(response.text) - async def get_shift_async( + def get_shift( self, team_id: str, shift_id: str, @@ -1857,6 +2274,22 @@ async def get_shift_async( Get a Shift This operation returns details for a Shift using the Shift's unique ID. + + Swagger operation ID: `GetShift`. + + Args: + team_id: Add Team ID. + shift_id: The unique ID of the Shift. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1868,7 +2301,7 @@ async def get_shift_async( f"/{quote(str(shift_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1882,6 +2315,7 @@ async def get_shift_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1889,7 +2323,7 @@ async def get_shift_async( return json.loads(response.text) - async def delete_shift_async( + def delete_shift( self, team_id: str, shift_id: str, @@ -1903,6 +2337,22 @@ async def delete_shift_async( Delete a Shift This operation deletes a Shift using the Shift's unique ID. + + Swagger operation ID: `DeleteShift`. + + Args: + team_id: Add Team ID. + shift_id: The unique ID of the Shift. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1914,7 +2364,7 @@ async def delete_shift_async( f"/{quote(str(shift_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1928,27 +2378,47 @@ async def delete_shift_async( request_url, response.status, response.text, + response=response, ) - async def list_open_shifts_async( + def list_open_shifts( self, team_id: str, + *, start_time: Optional[str] = None, end_time: Optional[str] = None, top: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List all Open Shifts in a team This operation returns all Open Shifts in a team. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListOpenShifts`. + + Args: + team_id: Add Team ID. + start_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + end_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + top: Items per page (enable Pagination under .../Settings). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1972,11 +2442,18 @@ async def list_open_shifts_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1989,25 +2466,34 @@ async def list_open_shifts_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def create_open_shift_async( + return ItemPaged(get_next, extract_data) + + def create_open_shift( self, - input: EditOpenShiftRequest, + input: EditOpenShiftRequest | Mapping[str, Any], team_id: str, *, timeout: Optional[float] = None, @@ -2019,13 +2505,30 @@ async def create_open_shift_async( Create a new Open Shift Create a new Open Shift in a Schedule. + + Swagger operation ID: `CreateOpenShift`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/teams/{quote(str(team_id), safe='')}/schedule/openShifts" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2039,6 +2542,7 @@ async def create_open_shift_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2046,7 +2550,7 @@ async def create_open_shift_async( return json.loads(response.text) - async def get_open_shift_async( + def get_open_shift( self, team_id: str, open_shift_id: str, @@ -2060,6 +2564,22 @@ async def get_open_shift_async( Get an Open Shift This operation returns details for an Open Shift. + + Swagger operation ID: `GetOpenShift`. + + Args: + team_id: Add Team ID. + open_shift_id: The unique ID of the Open Shift. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2071,7 +2591,7 @@ async def get_open_shift_async( f"/{quote(str(open_shift_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2085,6 +2605,7 @@ async def get_open_shift_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2092,9 +2613,9 @@ async def get_open_shift_async( return json.loads(response.text) - async def update_open_shift_async( + def update_open_shift( self, - input: EditOpenShiftRequest, + input: EditOpenShiftRequest | Mapping[str, Any], team_id: str, open_shift_id: str, *, @@ -2107,6 +2628,24 @@ async def update_open_shift_async( Update an Open Shift Update an Open Shift in a Schedule. + + Swagger operation ID: `UpdateOpenShift`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + open_shift_id: The unique ID of the Open Shift. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2118,7 +2657,7 @@ async def update_open_shift_async( f"/{quote(str(open_shift_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -2132,6 +2671,7 @@ async def update_open_shift_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2139,7 +2679,7 @@ async def update_open_shift_async( return json.loads(response.text) - async def delete_open_shift_async( + def delete_open_shift( self, team_id: str, open_shift_id: str, @@ -2153,6 +2693,22 @@ async def delete_open_shift_async( Delete an Open Shift This operation deletes an Open Shift. + + Swagger operation ID: `DeleteOpenShift`. + + Args: + team_id: Add Team ID. + open_shift_id: The unique ID of the Open Shift. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2164,7 +2720,7 @@ async def delete_open_shift_async( f"/{quote(str(open_shift_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2178,26 +2734,44 @@ async def delete_open_shift_async( request_url, response.status, response.text, + response=response, ) - async def list_time_off_reasons_async( + def list_time_off_reasons( self, team_id: str, - top: Optional[int] = None, *, + top: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List all Time Off Reasons in a team This operation returns the list of Time Off Reasons associated with a team. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTimeOffReasons`. + + Args: + team_id: Add Team ID. + top: Items per page (enable Pagination under .../Settings). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2215,11 +2789,18 @@ async def list_time_off_reasons_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2232,39 +2813,65 @@ async def list_time_off_reasons_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def list_scheduling_groups_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def list_scheduling_groups( self, team_id: str, - top: Optional[int] = None, *, + top: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List all Scheduling Groups in a team This operation returns all Scheduling Groups in a Schedule. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListSchedulingGroups`. + + Args: + team_id: Add Team ID. + top: Items per page (enable Pagination under .../Settings). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2282,11 +2889,18 @@ async def list_scheduling_groups_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2299,23 +2913,32 @@ async def list_scheduling_groups_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_scheduling_group_async( + return ItemPaged(get_next, extract_data) + + def get_scheduling_group( self, team_id: str, scheduling_group_id: str, @@ -2330,6 +2953,22 @@ async def get_scheduling_group_async( This operation returns details for a Scheduling Group using its unique ID. + + Swagger operation ID: `GetSchedulingGroup`. + + Args: + team_id: Add Team ID. + scheduling_group_id: The unique ID of the Scheduling Group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2341,7 +2980,7 @@ async def get_scheduling_group_async( f"/{quote(str(scheduling_group_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2355,6 +2994,7 @@ async def get_scheduling_group_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2362,24 +3002,42 @@ async def get_scheduling_group_async( return json.loads(response.text) - async def list_time_off_requests_async( + def list_time_off_requests( self, team_id: str, + *, top: Optional[int] = None, state: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List all Time Off requests in a team This operation returns all Time Off requests in a Schedule. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTimeOffRequests`. + + Args: + team_id: Add Team ID. + top: Items per page (enable Pagination under .../Settings). + state: Request state filter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2402,11 +3060,18 @@ async def list_time_off_requests_async( query_params.append(f"state={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2419,23 +3084,32 @@ async def list_time_off_requests_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_time_off_shift_request_async( + return ItemPaged(get_next, extract_data) + + def get_time_off_shift_request( self, team_id: str, time_off_request_id: str, @@ -2449,6 +3123,22 @@ async def get_time_off_shift_request_async( Get a Time Off request This operation returns a Time Off request by ID. + + Swagger operation ID: `GetTimeOffShiftRequest`. + + Args: + team_id: Add Team ID. + time_off_request_id: The unique ID of the Time Off request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2460,7 +3150,7 @@ async def get_time_off_shift_request_async( f"/{quote(str(time_off_request_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2474,6 +3164,7 @@ async def get_time_off_shift_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2481,9 +3172,9 @@ async def get_time_off_shift_request_async( return json.loads(response.text) - async def time_off_request_approve_async( + def time_off_request_approve( self, - input: TimeOffRequestApproveInput, + input: TimeOffRequestApproveInput | Mapping[str, Any], team_id: str, time_off_request_id: str, *, @@ -2496,6 +3187,24 @@ async def time_off_request_approve_async( Approve a Time Off request This operation allows managers to approve a Time Off request. + + Swagger operation ID: `TimeOffRequestApprove`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + time_off_request_id: The unique ID of the Time Off request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2508,7 +3217,7 @@ async def time_off_request_approve_async( f"/approve" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2522,6 +3231,7 @@ async def time_off_request_approve_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2529,9 +3239,9 @@ async def time_off_request_approve_async( return json.loads(response.text) - async def time_off_request_decline_async( + def time_off_request_decline( self, - input: TimeOffRequestDeclineInput, + input: TimeOffRequestDeclineInput | Mapping[str, Any], team_id: str, time_off_request_id: str, *, @@ -2544,6 +3254,24 @@ async def time_off_request_decline_async( Decline a Time Off request This operation allows managers to decline a Time Off request. + + Swagger operation ID: `TimeOffRequestDecline`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + time_off_request_id: The unique ID of the Time Off request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2556,7 +3284,7 @@ async def time_off_request_decline_async( f"/decline" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2570,6 +3298,7 @@ async def time_off_request_decline_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2577,24 +3306,42 @@ async def time_off_request_decline_async( return json.loads(response.text) - async def list_offer_shift_requests_async( + def list_offer_shift_requests( self, team_id: str, + *, top: Optional[int] = None, state: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List all Offer Shift requests in a team This operation returns all Offer Shift requests in a Schedule. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListOfferShiftRequests`. + + Args: + team_id: Add Team ID. + top: Items per page (enable Pagination under .../Settings). + state: Request state filter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2617,11 +3364,18 @@ async def list_offer_shift_requests_async( query_params.append(f"state={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2634,23 +3388,32 @@ async def list_offer_shift_requests_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_offer_shift_request_async( + return ItemPaged(get_next, extract_data) + + def get_offer_shift_request( self, team_id: str, offer_shift_request_id: str, @@ -2664,6 +3427,22 @@ async def get_offer_shift_request_async( Get an Offer Shift request This operation returns an Offer Shift request by ID. + + Swagger operation ID: `GetOfferShiftRequest`. + + Args: + team_id: Add Team ID. + offer_shift_request_id: The unique ID of the Offer Shift request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2675,7 +3454,7 @@ async def get_offer_shift_request_async( f"/{quote(str(offer_shift_request_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2689,6 +3468,7 @@ async def get_offer_shift_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2696,9 +3476,9 @@ async def get_offer_shift_request_async( return json.loads(response.text) - async def offer_shift_request_approve_async( + def offer_shift_request_approve( self, - input: OfferShiftRequestApproveInput, + input: OfferShiftRequestApproveInput | Mapping[str, Any], team_id: str, offer_shift_request_id: str, *, @@ -2712,6 +3492,24 @@ async def offer_shift_request_approve_async( This operation allows recipients/managers to approve an Offer Shift request. + + Swagger operation ID: `OfferShiftRequestApprove`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + offer_shift_request_id: The unique ID of the Offer Shift request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2724,7 +3522,7 @@ async def offer_shift_request_approve_async( f"/approve" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2738,6 +3536,7 @@ async def offer_shift_request_approve_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2745,9 +3544,9 @@ async def offer_shift_request_approve_async( return json.loads(response.text) - async def offer_shift_request_decline_async( + def offer_shift_request_decline( self, - input: OfferShiftRequestDeclineInput, + input: OfferShiftRequestDeclineInput | Mapping[str, Any], team_id: str, offer_shift_request_id: str, *, @@ -2760,6 +3559,24 @@ async def offer_shift_request_decline_async( Decline an Offer Shift request This operation allows users to decline an Offer Shift request. + + Swagger operation ID: `OfferShiftRequestDecline`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + offer_shift_request_id: The unique ID of the Offer Shift request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2772,7 +3589,7 @@ async def offer_shift_request_decline_async( f"/decline" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2786,6 +3603,7 @@ async def offer_shift_request_decline_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2793,24 +3611,42 @@ async def offer_shift_request_decline_async( return json.loads(response.text) - async def list_swap_shifts_change_requests_async( + def list_swap_shifts_change_requests( self, team_id: str, + *, top: Optional[int] = None, state: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List all Swap Shifts requests in a team This operation returns all Swap Shifts requests in a Schedule. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListSwapShiftsChangeRequests`. + + Args: + team_id: Add Team ID. + top: Items per page (enable Pagination under .../Settings). + state: Request state filter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2833,11 +3669,18 @@ async def list_swap_shifts_change_requests_async( query_params.append(f"state={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2850,23 +3693,32 @@ async def list_swap_shifts_change_requests_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_swap_shifts_change_request_async( + return ItemPaged(get_next, extract_data) + + def get_swap_shifts_change_request( self, team_id: str, swap_shifts_change_request_id: str, @@ -2880,6 +3732,22 @@ async def get_swap_shifts_change_request_async( Get a Swap Shifts request This operation returns a Swap Shifts request by ID. + + Swagger operation ID: `GetSwapShiftsChangeRequest`. + + Args: + team_id: Add Team ID. + swap_shifts_change_request_id: The unique ID of the request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2891,7 +3759,7 @@ async def get_swap_shifts_change_request_async( f"/{quote(str(swap_shifts_change_request_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2905,6 +3773,7 @@ async def get_swap_shifts_change_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2912,9 +3781,9 @@ async def get_swap_shifts_change_request_async( return json.loads(response.text) - async def swap_shifts_change_request_approve_async( + def swap_shifts_change_request_approve( self, - input: SwapShiftsChangeRequestApproveInput, + input: SwapShiftsChangeRequestApproveInput | Mapping[str, Any], team_id: str, swap_shifts_change_request_id: str, *, @@ -2927,6 +3796,24 @@ async def swap_shifts_change_request_approve_async( Approve a Swap Shifts request This operation allows a user to approve a Swap Shifts request. + + Swagger operation ID: `SwapShiftsChangeRequestApprove`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + swap_shifts_change_request_id: The unique ID of the request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2939,7 +3826,7 @@ async def swap_shifts_change_request_approve_async( f"/approve" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2953,6 +3840,7 @@ async def swap_shifts_change_request_approve_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2960,9 +3848,9 @@ async def swap_shifts_change_request_approve_async( return json.loads(response.text) - async def swap_shifts_change_request_decline_async( + def swap_shifts_change_request_decline( self, - input: SwapShiftsChangeRequestDeclineInput, + input: SwapShiftsChangeRequestDeclineInput | Mapping[str, Any], team_id: str, swap_shifts_change_request_id: str, *, @@ -2975,6 +3863,24 @@ async def swap_shifts_change_request_decline_async( Decline a Swap Shifts request This operation allows users to decline a Swap Shifts request. + + Swagger operation ID: `SwapShiftsChangeRequestDecline`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + swap_shifts_change_request_id: The unique ID of the request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2987,7 +3893,7 @@ async def swap_shifts_change_request_decline_async( f"/decline" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3001,6 +3907,7 @@ async def swap_shifts_change_request_decline_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3008,24 +3915,42 @@ async def swap_shifts_change_request_decline_async( return json.loads(response.text) - async def list_open_shift_change_requests_async( + def list_open_shift_change_requests( self, team_id: str, + *, top: Optional[int] = None, state: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List all Open Shift requests in a team This operation returns all Open Shift change requests in a Schedule. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListOpenShiftChangeRequests`. + + Args: + team_id: Add Team ID. + top: Items per page (enable Pagination under .../Settings). + state: Request state filter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3048,11 +3973,18 @@ async def list_open_shift_change_requests_async( query_params.append(f"state={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -3065,23 +3997,32 @@ async def list_open_shift_change_requests_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_open_shift_change_request_async( + return ItemPaged(get_next, extract_data) + + def get_open_shift_change_request( self, team_id: str, open_shift_change_request_id: str, @@ -3095,6 +4036,22 @@ async def get_open_shift_change_request_async( Get an Open Shift request This operation returns an Open Shift change request by ID. + + Swagger operation ID: `GetOpenShiftChangeRequest`. + + Args: + team_id: Add Team ID. + open_shift_change_request_id: The unique ID of the request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3106,7 +4063,7 @@ async def get_open_shift_change_request_async( f"/{quote(str(open_shift_change_request_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3120,6 +4077,7 @@ async def get_open_shift_change_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3127,9 +4085,9 @@ async def get_open_shift_change_request_async( return json.loads(response.text) - async def open_shift_change_request_approve_async( + def open_shift_change_request_approve( self, - input: OpenShiftChangeRequestApproveInput, + input: OpenShiftChangeRequestApproveInput | Mapping[str, Any], team_id: str, open_shift_change_request_id: str, *, @@ -3142,6 +4100,24 @@ async def open_shift_change_request_approve_async( Approve an Open Shift request This operation allows managers to approve an Open Shift request. + + Swagger operation ID: `OpenShiftChangeRequestApprove`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + open_shift_change_request_id: The unique ID of the request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3154,7 +4130,7 @@ async def open_shift_change_request_approve_async( f"/approve" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3168,6 +4144,7 @@ async def open_shift_change_request_approve_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3175,9 +4152,9 @@ async def open_shift_change_request_approve_async( return json.loads(response.text) - async def open_shift_change_request_decline_async( + def open_shift_change_request_decline( self, - input: OpenShiftChangeRequestDeclineInput, + input: OpenShiftChangeRequestDeclineInput | Mapping[str, Any], team_id: str, open_shift_change_request_id: str, *, @@ -3190,6 +4167,24 @@ async def open_shift_change_request_decline_async( Decline an Open Shift request This operation allows managers to decline an Open Shift request. + + Swagger operation ID: `OpenShiftChangeRequestDecline`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Add Team ID. + open_shift_change_request_id: The unique ID of the request. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3202,7 +4197,7 @@ async def open_shift_change_request_decline_async( f"/decline" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3216,6 +4211,7 @@ async def open_shift_change_request_decline_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3223,25 +4219,43 @@ async def open_shift_change_request_decline_async( return json.loads(response.text) - async def list_open_shifts_cross_team_async( + def list_open_shifts_cross_team( self, + *, start_time: Optional[str] = None, end_time: Optional[str] = None, top: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List all Open Shifts from my teams This operation returns Open Shifts that need to be filled from all your teams. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListOpenShiftsCrossTeam`. + + Args: + start_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + end_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + top: Items per page (enable Pagination under .../Settings). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/beta/me/joinedTeams/getOpenShifts" @@ -3264,11 +4278,18 @@ async def list_open_shifts_cross_team_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -3281,41 +4302,69 @@ async def list_open_shifts_cross_team_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def list_shifts_cross_team_async( + return ItemPaged(get_next, extract_data) + + def list_shifts_cross_team( self, + *, start_time: Optional[str] = None, end_time: Optional[str] = None, assigned_to_user_name: Optional[str] = None, top: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List all Shifts from my teams This operation returns assigned Shifts from all your teams. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListShiftsCrossTeam`. + + Args: + start_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + end_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + assigned_to_user_name: Assigned to user with name. + top: Items per page (enable Pagination under .../Settings). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/beta/me/joinedTeams/getShifts" @@ -3343,11 +4392,18 @@ async def list_shifts_cross_team_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -3360,41 +4416,69 @@ async def list_shifts_cross_team_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def list_times_off_cross_team_async( + def list_times_off_cross_team( self, + *, start_time: Optional[str] = None, end_time: Optional[str] = None, assigned_to_user_name: Optional[str] = None, top: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List all Times Off from my teams This operation returns times when people are off from all your teams. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTimesOffCrossTeam`. + + Args: + start_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + end_time: yyyy-MM-ddTHH:mm:ss.fffZ (UTC format). + assigned_to_user_name: Assigned to user with name. + top: How many times off to fetch. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/beta/me/joinedTeams/getTimesOff" @@ -3422,11 +4506,18 @@ async def list_times_off_cross_team_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -3439,58 +4530,106 @@ async def list_times_off_cross_team_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_all_teams_async( + return ItemPaged(get_next, extract_data) + + def list_all_teams( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List teams This operation retrieves a list of all the Teams (Office 365 Groups) you are a member of. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAllTeams`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/me/joinedTeams" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/signinghub.py b/src/azure/connectors/signinghub.py index fff7eba..2772f7c 100644 --- a/src/azure/connectors/signinghub.py +++ b/src/azure/connectors/signinghub.py @@ -5,21 +5,266 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Literal, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Literal, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "SigninghubClient", + "AccessAuthentication", + "AccessDurationByDate", + "AccessDurationByDateResponse", + "AccessDurationByDays", + "AccessDurationByDaysResponse", + "AccessResponse", + "AccessSecurityPasswordResponse", + "AccessSecuritySmsOtpResponse", + "AccessSecurityTOTPResponse", + "AccessUpdateRequest", + "AddAttachmentResponse", + "AddDocumentPackageRequest", + "AddFieldResponse", + "AddPackageResponse", + "AddQrCodeResponse", + "ApiBulkSignAction", + "ApplyTemplateRequest", + "ApproveRequest", + "AssignFieldRequest", + "AttachmentDownloadAttachmentResponse", + "AttachmentFieldResponse", + "AttachmentPermissionRequest", + "AttachmentPermissionResponse", + "Authentication", + "AuthenticationPassword", + "AuthenticationRequest", + "AuthenticationResponse", + "AuthenticationSigningResponse", + "AuthenticationSigningSmsOtp", + "AuthenticationSigningSmsOtpResponse", + "AuthenticationSmsOtp", + "AutoPlaceFieldRequest", + "AutoPlaceFieldsResponse", + "BulkSignActionDocumentModel", + "BulkSignActionFieldModel", + "BulkSignAuthentication", + "BulkSignPackagesStatus", + "BulkSignRequest", + "BulkSignResponse", + "BulkSignStatusRequest", + "BulkSignStatusResponse", + "CertifyPermission", + "CertifyPermissionResponse", + "CertifyPolicyRequest", + "CertifyPolicyResponse", + "CertifyResponse", + "ChangeServicePlanRequest", + "CheckBoxFieldRequest", + "CheckBoxFormFillingRequest", + "CheckboxFieldResponse", + "CollaboratorGroupResponse", + "CollaboratorPlaceholderResponse", + "CollaboratorResponse", + "CollaboratorRole", + "CommentFieldRecipientResponse", + "CommentFieldResponse", + "ContactResponse", + "ContactSortBy", + "DeclineByDetails", + "DeclineRequest", + "DeleteDocumentFieldRequest", + "DeliveryMethod", + "DetailedResponse", + "DigitalSignatureFieldRequest", + "DigitalSignatureFieldResponse", + "DocumentCertifyResponse", + "DocumentDetails", + "DocumentDetailsResponse", + "DocumentLogsActions", + "DocumentLogsActionsInformation", + "DocumentOwnedBy", + "DocumentOwner", + "DocumentPackageStatus", + "DocumentResponse", + "DocumentTemplateResponse", + "DocumentType", + "DocumentsDownloadDocumentBytesResponse", + "DocumentsTemplateResponse", + "DropDownFormFillingRequest", + "DropdownFieldResponse", + "DurationByDate", + "DurationByDateResponse", + "DurationByDays", + "DurationByDaysResponse", + "ECCLevelAPI", + "EciModeAPI", + "ElectronicSealRecipient", + "ElectronicSignatureFieldResponse", + "EmailDeletedDocument", + "EmptyResponse", + "EnterpriseAccessResponse", + "EnterpriseAccessSecuritySmsOtpResponse", + "EnterpriseAuthenticationResponse", + "EnterpriseAuthenticationSigningResponse", + "EnterpriseAuthenticationSigningSmsOtpResponse", + "EnterpriseTemplateResponse", + "EnterpriseTemplateRole", + "ErrorWithDescriptionResponse", + "FieldAuthentication", + "FieldDimension", + "FieldDimenssionResponse", + "FieldResponse", + "FieldType", + "FieldValidationValue", + "FieldValidationValueRule", + "FieldsAutoAssignFieldInput", + "FieldsResponse", + "FolderItemSortBy", + "Font", + "FontResponse", + "FormFillingRequest", + "GetAttachmentResponse", + "GetPackageDetailsResponse", + "GetPackagesResponse", + "GroupMemberResponse", + "HandSignature", + "HandSignatureFieldResponse", + "InPersonFieldRequest", + "InPersonFieldResponse", + "InitialFieldRequest", + "InitialFieldResponse", + "InitialFillingRequest", + "LegalNoticeResponse", + "ListBoxFieldResponse", + "ListBoxFormFillingRequest", + "MoveToRequest", + "NextSignerEmail", + "NotifyInactiveDeleteUser", + "NotifyUnUsedDeleteDocument", + "PackageDownloadPackageBytesResponse", + "PageResponse", + "PermissionAccessDuration", + "PermissionAccessDurationResponse", + "PermissionLegalNotice", + "PermissionLegalNoticeResponse", + "PlaceholderRequest", + "PostProcessRecipientRequest", + "PostProcessRecipientResponse", + "PostProcessResponse", + "PostProcessUpdateRequest", + "QrCodeColor", + "QrCodeLogo", + "QrCodeOptions", + "QrCodeRequest", + "QrCodeResponse", + "RadioBoxFieldRequest", + "RadioFieldResponse", + "RadioFormFillingRequest", + "RecipientAccessDurationDetails", + "RecipientDeclineDetails", + "ReminderRepeat", + "ReminderResponse", + "RenameDocumentPackageRequest", + "RenameDocumentRequest", + "RepeatRequest", + "Response", + "ServicePlanAuthenticationProfile", + "ServicePlanAutoDeleteDocument", + "ServicePlanAutoDeleteUser", + "ServicePlanCapacity", + "ServicePlanCapacityRequest", + "ServicePlanCertifyOption", + "ServicePlanElectronicSealServer", + "ServicePlanEmailOtp", + "ServicePlanEvidenceReport", + "ServicePlanLevelOfAssurance", + "ServicePlanOneTimePassword", + "ServicePlanProfile", + "ServicePlanSigningServer", + "ServicePlanSmsNotification", + "ServicePlanSmsOtp", + "ServicePlanSmtpServer", + "SignDocumentRequest", + "SignDocumentResponse", + "SignatureFieldAuthentication", + "SignatureFieldAuthenticationOtp", + "SignatureFieldAuthenticationTotp", + "SignatureFieldResponse", + "SigningAuthentication", + "SigningServerCapacity", + "SigningServerCsp", + "SigningServerSignatureAppearance", + "StartWorkflowResponse", + "TemplateDocumentResponse", + "TemplateResponse", + "TemplateSmartFormResponse", + "TemplateSortBy", + "TextBoxFieldRequest", + "TextFieldResponse", + "TextFormFillingRequest", + "TextboxType", + "TotpPermissionResponse", + "UniqueIdentifierFieldResponse", + "UpdateCertifyPolicyRequest", + "UpdateCheckBoxFieldRequest", + "UpdateCollaboratorResponse", + "UpdateDigitalSignatureFieldRequest", + "UpdateInPersonFieldRequest", + "UpdateInitialFieldRequest", + "UpdateQrCodeRequest", + "UpdateQrCodeResponse", + "UpdateRadioBoxFieldRequest", + "UpdateReminderRequest", + "UpdateTextBoxFieldRequest", + "UpdateWorkSpaceRequest", + "UploadDocument", + "UploadDocumentLibraryCertifyResponse", + "UploadDocumentLibraryResponse", + "UploadDocumentLibraryTemplateResponse", + "UploadDocumentMetaInfoDetail", + "ValidationRule", + "VerificationResponse", + "WorflowGroupRequest", + "WorflowUserRequest", + "WorkSpaceMembers", + "WorkSpaceOwner", + "WorkSpaceResponse", + "WorkflowCollaboratorRole", + "WorkflowDetailUpdateRequest", + "WorkflowDetailsResponse", + "WorkflowDocumentsResponse", + "WorkflowEvidenceReportDownloadBytesResponse", + "WorkflowGatekeeperResponse", + "WorkflowGatekeeperUserResponse", + "WorkflowHistoryResponse", + "WorkflowMode", + "WorkflowModes", + "WorkflowPermission", + "WorkflowPermissionResponse", + "WorkflowPermissionsUpdateRequest", + "WorkflowPlaceholderUpdateRequest", + "WorkflowRecipient", + "WorkflowResponse", + "WorkflowType", + "WorkflowUserReorderRequest", + "WorkflowUserResponse", + "WorkflowUserUpdateRequest", + "WorkflowWorkflowAddGroupInput", + "WorkflowWorkflowAddPlaceholderInput", + "WorkflowWorkflowAddUserInput", +] + # Type Definitions @@ -29,7 +274,7 @@ class EmptyResponse: Response for Delete Attachment """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -42,7 +287,7 @@ class AttachmentDownloadAttachmentResponse: Response for Download Attachment """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -55,9 +300,9 @@ class GetAttachmentResponse: Response for Get Attachments """ - attachment_id: Optional[int] = None + attachment_id: int """Attachment id""" - attachment_name: Optional[str] = None + attachment_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Attachment name""" @@ -67,7 +312,7 @@ class AddAttachmentResponse: Response for Upload Attachment """ - attachment_id: Optional[int] = None + attachment_id: int """Attachment id""" @@ -77,9 +322,9 @@ class AddFieldResponse: Response for Add CheckBox Field """ - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the field created in the document.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time of field creation.""" @@ -89,19 +334,19 @@ class ContactResponse: Response for Get Contacts """ - id: Optional[int] = None + id: int """id of the contact.""" - user_name: Optional[str] = None + user_name: Optional[str] = dataclass_field(default=None, kw_only=True) """User name of the contact.""" - user_email: Optional[str] = None + user_email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the contact.""" - mobile_number: Optional[str] = None + mobile_number: Optional[str] = dataclass_field(default=None, kw_only=True) """Mobile number of the contact.""" - enterprise: Optional[bool] = None + enterprise: bool """True, if contact is enterprise.""" - user_national_id: Optional[str] = None + user_national_id: Optional[str] = dataclass_field(default=None, kw_only=True) """National identity number of the contact""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """DateTime when contact is added.""" @@ -111,7 +356,7 @@ class DocumentResponse: Response for Delete Document """ - package_name: Optional[str] = None + package_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Document Package name""" @@ -121,7 +366,7 @@ class DocumentsDownloadDocumentBytesResponse: Response for Download Document """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -134,8 +379,13 @@ class CertifyPolicyResponse: Response for Get Certify Policy for a document """ - certify: Optional[CertifyPermissionResponse] = None - lock_form_fields: Optional[bool] = None + certify: Optional[ + CertifyPermissionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + lock_form_fields: bool """ True if forms fields are to be locked in the PDF after the last digital signature on the current document. @@ -148,31 +398,41 @@ class DocumentDetailsResponse: Response for Get Document Details """ - document_id: Optional[int] = None + document_id: int """ID of the newly created document.""" - document_name: Optional[str] = None + document_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the document.""" - document_order: Optional[int] = None - document_type: Optional[str] = None + document_order: int + document_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Type of the document e.g. \"PDF\".""" - document_width: Optional[int] = None + document_width: int """Width of the document in PDF format.""" - document_height: Optional[int] = None + document_height: int """Height of the document in PDF format.""" - document_source: Optional[str] = None + document_source: Optional[str] = dataclass_field(default=None, kw_only=True) """Identifies where the document was uploaded e.g. \"My App\".""" - document_pages: Optional[int] = None + document_pages: int """Total pages of the document.""" - form_fields: Optional[bool] = None + form_fields: bool """True if document has form fields.""" - lock_form_fields: Optional[bool] = None + lock_form_fields: bool """True if locking of form fields with the last signature is enabled.""" - uploaded_on: Optional[str] = None + uploaded_on: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time when the document was uploaded.""" - modified_on: Optional[str] = None + modified_on: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time when the document was last modified.""" - certify: Optional[DocumentCertifyResponse] = None - template: Optional[DocumentTemplateResponse] = None + certify: Optional[ + DocumentCertifyResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + template: Optional[ + DocumentTemplateResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -181,37 +441,52 @@ class UploadDocumentLibraryResponse: Response for Add or Update Document from Library """ - document_id: Optional[int] = None + document_id: int """ID of the newly created document.""" - document_name: Optional[str] = None + document_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the document.""" - document_size: Optional[int] = None + document_size: int """Uploaded document size in bytes""" - document_order: Optional[int] = None + document_order: int """Order of the document""" - document_type: Optional[str] = None + document_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Type of the document e.g. \"PDF\".""" - document_source: Optional[str] = None + document_source: Optional[str] = dataclass_field(default=None, kw_only=True) """Identifies where the document was uploaded e.g. \"My App\".""" - document_width: Optional[int] = None + document_width: int """Width of the document in PDF format.""" - document_height: Optional[int] = None + document_height: int """Height of the document in PDF format.""" - document_pages: Optional[int] = None + document_pages: int """Total pages of the document.""" - uploaded_on: Optional[str] = None + uploaded_on: str """The date and time when the document was uploaded.""" - modified_on: Optional[str] = None + modified_on: str """The date and time when the document was last modified.""" - form_fields: Optional[bool] = None + form_fields: bool """True if document has form fields.""" - lock_form_fields: Optional[bool] = None + lock_form_fields: bool """True if locking of form fields with the last signature is enabled.""" - certify: Optional[UploadDocumentLibraryCertifyResponse] = None - template: Optional[UploadDocumentLibraryTemplateResponse] = None - package_name: Optional[str] = None + certify: Optional[ + UploadDocumentLibraryCertifyResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + template: Optional[ + UploadDocumentLibraryTemplateResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + package_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Package name""" - metadata: Optional[UploadDocumentMetaInfoDetail] = None + metadata: Optional[ + UploadDocumentMetaInfoDetail | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -220,49 +495,56 @@ class UploadDocument: Response for Upload Document """ - document_id_2: Optional[int] = field( - default=None, - metadata={"wire_name": "documentId"}, - ) + document_id_2: int = dataclass_field(metadata={"wire_name": "documentId"}) """ This property is retained for backward compatibility and will be removed in later versions. Use document_id instead. """ - documentid: Optional[int] = None + documentid: int """ The document ID to be used later to share, download and get status of the document. will be removed later document_id will be used """ - document_id: Optional[int] = None + document_id: int """ The document ID to be used later to share, download and get status of the document. """ - document_name: Optional[str] = None + document_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the document.""" - document_order: Optional[int] = None + document_order: int """Document order in package""" - document_type: Optional[str] = None + document_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Type of the document e.g. \"PDF\".""" - document_source: Optional[str] = None + document_source: Optional[str] = dataclass_field(default=None, kw_only=True) """Identifies where the document was uploaded e.g. \"My App\".""" - document_width: Optional[int] = None + document_width: int """Width of the document in PDF format.""" - document_height: Optional[int] = None + document_height: int """Height of the document in PDF format.""" - document_pages: Optional[int] = None + document_pages: int """Total pages of the document.""" - uploaded_on: Optional[str] = None + uploaded_on: str """The date and time when the document was uploaded.""" - modified_on: Optional[str] = None + modified_on: str """The date and time when the document was last modified.""" - lock_form_fields: Optional[bool] = None + lock_form_fields: bool """True if locking of form fields with the last signature is enabled.""" - certify: Optional[CertifyPermissionResponse] = None - document_size: Optional[int] = None + certify: Optional[ + CertifyPermissionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + document_size: int """Uploaded document size in bytes""" - metadata: Optional[UploadDocumentMetaInfoDetail] = None - package_name: Optional[str] = None + metadata: Optional[ + UploadDocumentMetaInfoDetail | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + package_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The document package name""" @@ -272,12 +554,27 @@ class EnterpriseAccessResponse: Response for Get Workflow User Authentication (Document Opening) of Enterprise Package """ - authentication: Optional[EnterpriseAuthenticationResponse] = None - authentication_signing: Optional[EnterpriseAuthenticationSigningResponse] = None - access_duration: Optional[PermissionAccessDurationResponse] = None + authentication: Optional[ + EnterpriseAuthenticationResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + authentication_signing: Optional[ + EnterpriseAuthenticationSigningResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + access_duration: Optional[ + PermissionAccessDurationResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) -FieldsAutoAssignFieldInput = List["AssignFieldRequest"] +FieldsAutoAssignFieldInput = List["AssignFieldRequest | Mapping[str, Any]"] @dataclass @@ -286,7 +583,7 @@ class AutoPlaceFieldsResponse: Response for AutoPlace Fields """ - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the field that was auto generated by the API.""" @@ -296,21 +593,91 @@ class FieldsResponse: Response for Get Document Fields """ - signature: Optional[List[DigitalSignatureFieldResponse]] = None + signature: Optional[ + List[DigitalSignatureFieldResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A list of all digital signatures in the document.""" - hand_signature: Optional[List[HandSignatureFieldResponse]] = None - electronic_signature: Optional[List[ElectronicSignatureFieldResponse]] = None - initials: Optional[List[InitialFieldResponse]] = None - in_person_signature: Optional[List[Dict[str, Any]]] = None - text: Optional[List[TextFieldResponse]] = None - radio: Optional[List[RadioFieldResponse]] = None - checkbox: Optional[List[CheckboxFieldResponse]] = None - dropdown: Optional[List[DropdownFieldResponse]] = None - listbox: Optional[List[ListBoxFieldResponse]] = None - qrcode: Optional[List[QrCodeResponse]] = None - attachment: Optional[List[AttachmentFieldResponse]] = None - comment: Optional[List[CommentFieldResponse]] = None - unique_identifier: Optional[List[UniqueIdentifierFieldResponse]] = None + hand_signature: Optional[ + List[HandSignatureFieldResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + electronic_signature: Optional[ + List[ElectronicSignatureFieldResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + initials: Optional[ + List[InitialFieldResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + in_person_signature: Optional[ + List[Dict[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + text: Optional[ + List[TextFieldResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + radio: Optional[ + List[RadioFieldResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + checkbox: Optional[ + List[CheckboxFieldResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + dropdown: Optional[ + List[DropdownFieldResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + listbox: Optional[ + List[ListBoxFieldResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + qrcode: Optional[ + List[QrCodeResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + attachment: Optional[ + List[AttachmentFieldResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + comment: Optional[ + List[CommentFieldResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + unique_identifier: Optional[ + List[UniqueIdentifierFieldResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -319,14 +686,14 @@ class AddPackageResponse: Response for Add Package """ - package_id: Optional[int] = None + package_id: int """ The package ID to be used later to share, download and get status of the document. """ - workflow_mode: Optional[str] = None + workflow_mode: Optional[str] = dataclass_field(default=None, kw_only=True) """The workflow mode that is set while adding package.""" - workflow_type: Optional[str] = None + workflow_type: Optional[str] = dataclass_field(default=None, kw_only=True) """ Type of the workflow. Possible values are \"SERIAL\", \"PARALLEL\", \"INDIVIDUAL\" and \"CUSTOM\". @@ -339,7 +706,7 @@ class PackageDownloadPackageBytesResponse: Response for Download Package """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -352,48 +719,63 @@ class GetPackagesResponse: Response for Get Packages """ - package_id: Optional[int] = None + package_id: int """Package ID of the document package.""" - package_name: Optional[str] = None + package_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the document package.""" - package_owner: Optional[str] = None + package_owner: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the document package owner.""" - owner_name: Optional[str] = None + owner_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the document package owner.""" - shared_package: Optional[bool] = None + shared_package: bool """Shared Package""" - gatekeeper_package: Optional[bool] = None + gatekeeper_package: bool """Gatekeeper Package""" - package_status: Optional[str] = None + package_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Document status for the current logged in user. Possible values are \"DRAFT\", \"INPROGRESS\", \"PENDING\", \"DECLINED\", or \"COMPLETED\". """ - extension: Optional[str] = None + extension: Optional[str] = dataclass_field(default=None, kw_only=True) """Document Package extension""" - workflow_mode: Optional[str] = None + workflow_mode: Optional[str] = dataclass_field(default=None, kw_only=True) """Workflow Mode""" - folder: Optional[str] = None + folder: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the folder which contains the document package.""" - folder_id: Optional[int] = None + folder_id: int """Id of the folder which contains the document package.""" - unread: Optional[bool] = None + unread: bool """True, if the document is not read by the recipient yet.""" - next_signer: Optional[str] = None + next_signer: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the next signer if the document is in shared state.""" - next_signer_email: Optional[List[NextSignerEmail]] = None + next_signer_email: Optional[ + List[NextSignerEmail | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """ An object containing next signers username and email address. In case of group signer it will have a list of email addresses of all the group members. """ - uploaded_on: Optional[str] = None + uploaded_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time when the document was uploaded.""" - modified_on: Optional[str] = None + modified_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time when the document was last modified.""" - access_duration: Optional[RecipientAccessDurationDetails] = None - decline: Optional[RecipientDeclineDetails] = None - size: Optional[int] = None + access_duration: Optional[ + RecipientAccessDurationDetails | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + decline: Optional[ + RecipientDeclineDetails | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + size: int """Size of the document in bytes.""" @@ -403,20 +785,25 @@ class GetPackageDetailsResponse: Response for Get Package Details """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the document package.""" - owner: Optional[DocumentOwner] = None - read_only: Optional[bool] = None + owner: Optional[DocumentOwner | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + read_only: bool """ True if the applied template is read only. User will not be able to make any changes if a read only template is applied. """ - document_status: Optional[str] = None + document_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Document status for the current logged in user. Possible values are \"DRAFT\", \"INPROGRESS\", \"PENDING\", \"DECLINED\", or \"COMPLETED\". """ - documents: Optional[List[DocumentDetails]] = None + documents: Optional[ + List[DocumentDetails | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -425,11 +812,11 @@ class AddQrCodeResponse: Response for Add QR Code """ - data: Optional[str] = None + data: str """QR Code generated data""" - field_name: Optional[str] = None + field_name: str """Name of the field created in the document.""" - value: Optional[str] = None + value: str """Value will be the base64 of QrCode image""" @@ -439,7 +826,7 @@ class UpdateQrCodeResponse: Response for Update QR Code """ - value: Optional[str] = None + value: str """Value will be the base64 of QrCode image""" @@ -449,28 +836,38 @@ class TemplateResponse: Response for Get Templates """ - template_id: Optional[int] = None + template_id: int """Id of the template is returned here """ - template_name: Optional[str] = None + template_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the template.""" - template_public: Optional[bool] = None + template_public: bool """ Response is \"true\" if enterprise template is marked as public. Otherwise \"false\" would be returned """ - read_only: Optional[bool] = None + read_only: bool """ Response of \"true\" if the template is read only, and user cannot make any changes to the workflow after applying this template. Otherwise \"false\". """ - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time when the template was created""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the template""" - enterprise: Optional[bool] = None + enterprise: bool """True, if user belong to an enterprise.""" - documents: Optional[List[TemplateDocumentResponse]] = None - smart_form: Optional[TemplateSmartFormResponse] = None + documents: Optional[ + List[TemplateDocumentResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + smart_form: Optional[ + TemplateSmartFormResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -479,9 +876,9 @@ class SignatureFieldResponse: Response for Add Digital Signature Field """ - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the field created in the document.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time of field creation.""" @@ -491,8 +888,8 @@ class BulkSignResponse: Response for Bulk Sign Packages """ - status: Optional[str] = None - transaction_id: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) + transaction_id: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -501,8 +898,13 @@ class BulkSignStatusResponse: Response for Bulk Signing Status """ - status: Optional[str] = None - packages: Optional[List[BulkSignPackagesStatus]] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) + packages: Optional[ + List[BulkSignPackagesStatus | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -511,18 +913,23 @@ class SignDocumentResponse: Response for Sign Document """ - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the field for which the verification was requested.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Returns the status of signature field. Values are SIGNED, PENDING. Status helps in eIDAS enabled remote authorized signing. If sign request is sent to mobile the status is pending. """ - transaction_id: Optional[str] = None + transaction_id: Optional[str] = dataclass_field(default=None, kw_only=True) """This parameter is used while RAS signing""" - verification: Optional[VerificationResponse] = None - authentication_access_token: Optional[str] = None + verification: Optional[ + VerificationResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + authentication_access_token: Optional[str] = dataclass_field(default=None, kw_only=True) """It will contain the OIDC id_token when user is authenticated via OIDC""" @@ -532,26 +939,36 @@ class EnterpriseTemplateResponse: Response for Get Enterprise Templates """ - id: Optional[int] = None + id: int """Id of the template """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the template.""" - public: Optional[bool] = None + public: bool """ Response is \"true\" if enterprise template is marked as public. Otherwise \"false\" would be returned """ - read_only: Optional[bool] = None + read_only: bool """ Response of \"true\" if the template is read only, and user cannot make any changes to the workflow after applying this template. Otherwise \"false\". """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the template""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time when the template was created""" - roles: Optional[List[EnterpriseTemplateRole]] = None - documents: Optional[List[TemplateDocumentResponse]] = None + roles: Optional[ + List[EnterpriseTemplateRole | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + documents: Optional[ + List[TemplateDocumentResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -560,7 +977,7 @@ class WorkflowEvidenceReportDownloadBytesResponse: Response for Get Process Evidence Report """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -573,43 +990,63 @@ class WorkflowDetailsResponse: Response for Get Workflow Details """ - package_id: Optional[int] = None + package_id: int """Package ID of the document package.""" - package_name: Optional[str] = None + package_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the document package.""" - shared_package: Optional[bool] = None + shared_package: bool """shared package""" - package_owner: Optional[str] = None + package_owner: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the document package owner.""" - owner_name: Optional[str] = None + owner_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the document package owner.""" - package_status: Optional[str] = None + package_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Document status for the current logged in user. Possible values are \"DRAFT\", \"INPROGRESS\", \"PENDING\", \"DECLINED\", \"APPROVED\", \"UPDATED\" or \"COMPLETED\". """ - folder: Optional[str] = None + folder: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the folder which contains the document package.""" - folder_id: Optional[int] = None + folder_id: int """ID of the folder which contains the document package.""" - gatekeeper: Optional[bool] = None - next_signer: Optional[str] = None + gatekeeper: bool + next_signer: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the next signer if the document is in shared state.""" - next_signer_email: Optional[List[NextSignerEmail]] = None + next_signer_email: Optional[ + List[NextSignerEmail | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """ An object containing next signers username and email address. In case of group signer it will have a list of email addresses of all the group members. """ - uploaded_on: Optional[str] = None + uploaded_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time when the document was uploaded.""" - modified_on: Optional[str] = None + modified_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time when the document was last modified.""" - workflow: Optional[WorkflowResponse] = None - documents: Optional[List[WorkflowDocumentsResponse]] = None + workflow: Optional[ + WorkflowResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + documents: Optional[ + List[WorkflowDocumentsResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of documents that are uploaded in the package.""" - users: Optional[List[WorkflowUserResponse]] = None + users: Optional[ + List[WorkflowUserResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Recipients list for the workflow.""" @@ -619,25 +1056,40 @@ class WorkflowHistoryResponse: Response for Get Workflow History """ - package_id: Optional[int] = None + package_id: int """ID of the package for which the workflow history is requested.""" - package_name: Optional[str] = None - package_owner: Optional[str] = None + package_name: Optional[str] = dataclass_field(default=None, kw_only=True) + package_owner: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the package owner.""" - owner_name: Optional[str] = None + owner_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the package owner.""" - package_status: Optional[str] = None + package_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Status of the package/document with the current logged in user. Possible values are \"DRAFT\", \"INPROGRESS\", \"PENDING\", \"DECLINED\", \"APPROVED\", \"UPDATED\" or \"COMPLETED\". """ - next_signer: Optional[str] = None + next_signer: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the next recipient.""" - next_signer_email: Optional[List[NextSignerEmail]] = None + next_signer_email: Optional[ + List[NextSignerEmail | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Object having name and email address of the next recipient.""" - documents: Optional[List[WorkflowDocumentsResponse]] = None - actions: Optional[List[DocumentLogsActions]] = None + documents: Optional[ + List[WorkflowDocumentsResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + actions: Optional[ + List[DocumentLogsActions | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -646,16 +1098,21 @@ class ReminderResponse: Response for Get Workflow Reminder """ - enabled: Optional[bool] = None + enabled: bool """True, if reminders are enabled for the recipient""" - frequency: Optional[str] = None + frequency: Optional[str] = dataclass_field(default=None, kw_only=True) """Reminder Frequency. Possible Values are DAYS | HOURS. """ - remind_after: Optional[int] = None + remind_after: int """ The number of days after which the first reminder would be sent to workflow user. """ - repeat: Optional[ReminderRepeat] = None + repeat: Optional[ + ReminderRepeat | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -664,79 +1121,94 @@ class WorkflowRecipient: Response for Get Workflow Users """ - order: Optional[int] = None + order: int """Order of the recipient in the workflow.""" - user_email: Optional[str] = None + user_email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the recipient if user is not a group.""" - user_name: Optional[str] = None + user_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the recipient if user is not a group.""" - mobile_number: Optional[str] = None + mobile_number: Optional[str] = dataclass_field(default=None, kw_only=True) """Mobile number""" - delivery_method: Optional[str] = None + delivery_method: Optional[str] = dataclass_field(default=None, kw_only=True) """ Delivery method of recipient Possible values: EMAIL, SMS, or EMAIL_AND_SMS """ - user_photo_url: Optional[str] = None + user_photo_url: Optional[str] = dataclass_field(default=None, kw_only=True) """ API endpoint to access the resource, This will be provided only for main signers. e.g it will be null for group/delegator/gatekeeper etc. This URL does not make sure that signer image is exist. If image exist it will be provided by hitting the defined url otherwise it will be an empty string. """ - group_name: Optional[str] = None + group_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Group name of the recipient if recipient is a group.""" - group_members: Optional[List[GroupMemberResponse]] = None + group_members: Optional[ + List[GroupMemberResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """ A list of email addresses of the group members if recipient is a group. """ - delegatee: Optional[str] = None + delegatee: Optional[str] = dataclass_field(default=None, kw_only=True) """Delegatee email address, if recipient is not a group.""" - delegatee_name: Optional[str] = None + delegatee_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the delegatee user, if recipient is not a group.""" - role: Optional[str] = None + role: Optional[str] = dataclass_field(default=None, kw_only=True) """ Workflow role in which the recipient was added. This role is not the enterprise role. Possible values are \"SIGNER\", \"REVIEWER\",\"CARBON_COPY\" and \"EDITOR\". """ - reason: Optional[str] = None + reason: Optional[str] = dataclass_field(default=None, kw_only=True) """ Reason provided by the user when declining, approving or submitting a document. """ - process_status: Optional[str] = None + process_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Document processing status for the recipient. Possible values are \"UN_PROCESSED\", \"IN_PROGRESS\", \"SIGNED\", \"REVIEWED\", \"DECLINED\", \"EDITED\" or \"INVALID\". """ - processed_on: Optional[str] = None + processed_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time on which the document was processed.""" - processed_as: Optional[str] = None + processed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """ User may processed the field as COLLABORATOR , DELEGATOR, GROUP_MEMBER or OWNER. """ - processed_by: Optional[str] = None + processed_by: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the user who processed the document.""" - placeholder: Optional[str] = None + placeholder: Optional[str] = dataclass_field(default=None, kw_only=True) """Placeholder text if the recipient is a placeholder""" - signing_order: Optional[int] = None + signing_order: int """ Order in which the workflow will be signed by the recipients. This signing order is important when workflow type is set to \"CUSTOM\". """ - user_national_id: Optional[str] = None + user_national_id: Optional[str] = dataclass_field(default=None, kw_only=True) """ National identity number of the user. This helps to identify user in the workflow """ - guest_user: Optional[bool] = None + guest_user: bool """Gest user""" - email_language_code: Optional[str] = None + email_language_code: Optional[str] = dataclass_field(default=None, kw_only=True) """email language code""" - electronic_seal: Optional[ElectronicSealRecipient] = None - gatekeepers: Optional[WorkflowGatekeeperResponse] = None + electronic_seal: Optional[ + ElectronicSealRecipient | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + gatekeepers: Optional[ + WorkflowGatekeeperResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -745,21 +1217,31 @@ class WorkflowPermissionResponse: Response for Get Workflow User Permissions """ - print: Optional[bool] = None + print: Optional[bool] = dataclass_field(default=None, kw_only=True) """True, if printing is allowed for this recipient.""" - download: Optional[bool] = None + download: Optional[bool] = dataclass_field(default=None, kw_only=True) """True, if download is allowed.""" - add_text: Optional[bool] = None + add_text: Optional[bool] = dataclass_field(default=None, kw_only=True) """True, if add text annotation on the document is allowed.""" - change_recipients: Optional[bool] = None + change_recipients: Optional[bool] = dataclass_field(default=None, kw_only=True) """ True, if the recipient on the current order can change other recipients in the workflow after workflow is shared. """ - add_attachment: Optional[bool] = None + add_attachment: Optional[bool] = dataclass_field(default=None, kw_only=True) """True, if attachments and merging of PDF documents is allowed.""" - legal_notice: Optional[PermissionLegalNoticeResponse] = None - attachment: Optional[AttachmentPermissionResponse] = None + legal_notice: Optional[ + PermissionLegalNoticeResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + attachment: Optional[ + AttachmentPermissionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -768,17 +1250,17 @@ class StartWorkflowResponse: Response for Share Document Package """ - package_id: Optional[int] = None + package_id: int """ Package ID of the package just shared. Incase of individual sharing, more then one packages are created and shared with the recipients. API returns an array of packages along with IDs of newly created documents. """ - documents: Optional[List[int]] = None + documents: Optional[List[int]] = dataclass_field(default=None, kw_only=True) """Array of document IDs which were part of the package before sharing.""" -WorkflowWorkflowAddGroupInput = List["WorflowGroupRequest"] +WorkflowWorkflowAddGroupInput = List["WorflowGroupRequest | Mapping[str, Any]"] @dataclass @@ -787,13 +1269,23 @@ class CollaboratorGroupResponse: Response for Add Groups to Workflow """ - permission: Optional[WorkflowPermissionResponse] = None - reminder: Optional[ReminderResponse] = None - signing_order: Optional[int] = None + permission: Optional[ + WorkflowPermissionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + reminder: Optional[ + ReminderResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + signing_order: int """Signing order""" -WorkflowWorkflowAddPlaceholderInput = List["PlaceholderRequest"] +WorkflowWorkflowAddPlaceholderInput = List["PlaceholderRequest | Mapping[str, Any]"] @dataclass @@ -802,13 +1294,23 @@ class CollaboratorPlaceholderResponse: Response for Add Placeholder to Workflow """ - permission: Optional[WorkflowPermissionResponse] = None - reminder: Optional[ReminderResponse] = None - signing_order: Optional[int] = None + permission: Optional[ + WorkflowPermissionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + reminder: Optional[ + ReminderResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + signing_order: int """Signing order""" -WorkflowWorkflowAddUserInput = List["WorflowUserRequest"] +WorkflowWorkflowAddUserInput = List["WorflowUserRequest | Mapping[str, Any]"] @dataclass @@ -817,16 +1319,26 @@ class CollaboratorResponse: Response for Add Users to Workflow """ - user_email: Optional[str] = None + user_email: Optional[str] = dataclass_field(default=None, kw_only=True) """User email""" - signing_order: Optional[int] = None + signing_order: int """Signing order""" - guest_user: Optional[bool] = None + guest_user: bool """Is guest user""" - email_language_code: Optional[str] = None + email_language_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Email language code""" - permission: Optional[WorkflowPermissionResponse] = None - reminder: Optional[ReminderResponse] = None + permission: Optional[ + WorkflowPermissionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + reminder: Optional[ + ReminderResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -835,13 +1347,13 @@ class UpdateCollaboratorResponse: Response for Update Workflow User """ - user_email: Optional[str] = None + user_email: Optional[str] = dataclass_field(default=None, kw_only=True) """User email""" - signing_order: Optional[int] = None + signing_order: int """Signing order""" - guest_user: Optional[bool] = None + guest_user: bool """Is guest user""" - email_language_code: Optional[str] = None + email_language_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Email language code""" @@ -851,12 +1363,12 @@ class WorkSpaceResponse: Response for Get Shared Space """ - id: Optional[int] = None + id: int """Id of shared space""" - name: Optional[str] = None + name: str """Name of shared space""" - owner: Optional[WorkSpaceOwner] = None - members: Optional[List[WorkSpaceMembers]] = None + owner: WorkSpaceOwner | Mapping[str, Any] + members: List[WorkSpaceMembers | Mapping[str, Any]] """Members of shared space""" @@ -866,12 +1378,12 @@ class ErrorWithDescriptionResponse: Definition: ErrorWithDescriptionResponse """ - error: Optional[str] = None + error: Optional[str] = dataclass_field(default=None, kw_only=True) """ Error key to identify the error in programming and applications can respond based on the different error keys. """ - error_description: Optional[str] = None + error_description: Optional[str] = dataclass_field(default=None, kw_only=True) """ Error message against the error key returned. Client applications can present this error as it is or send their own error message. @@ -884,8 +1396,9 @@ class Response: Definition: Response """ - message: Optional[str] = field( + message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Message"}, ) """ @@ -901,10 +1414,15 @@ class DetailedResponse: Definition: DetailedResponse """ - error: Optional[str] = field(default=None, metadata={"wire_name": "Error"}) + error: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Error"}, + ) """Custom error code""" - message: Optional[str] = field( + message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Message"}, ) """ @@ -920,17 +1438,17 @@ class AuthenticationRequest: Definition: AuthenticationRequest """ - client_id: Optional[str] = None + client_id: str """ Application Name that you have configured in your Enterprise Account when configuring the integration options. """ - client_secret: Optional[str] = None + client_secret: str """ API Key that you generated in your Enterprise Account when configuring the integration options. """ - profile_name: Optional[str] = None + profile_name: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -939,8 +1457,8 @@ class ElectronicSealRecipient: Definition: ElectronicSealRecipient """ - name: Optional[str] = None - level_of_assurance: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + level_of_assurance: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -949,14 +1467,24 @@ class PermissionLegalNoticeResponse: Definition: PermissionLegalNoticeResponse """ - enabled: Optional[bool] = None + enabled: bool """True, if legal notice is enabled and configured for the recipient.""" - allowed_notices: Optional[List[LegalNoticeResponse]] = None + allowed_notices: Optional[ + List[LegalNoticeResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """ List of legal notices allowed to the document owner from which he can select one for the recipient. """ - default_notice: Optional[List[LegalNoticeResponse]] = None + default_notice: Optional[ + List[LegalNoticeResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Default or selected legal notice for the recipient.""" @@ -966,10 +1494,10 @@ class LegalNoticeResponse: Definition: LegalNoticeResponse """ - legal_notice_id: Optional[int] = None - legal_notice_name: Optional[str] = None + legal_notice_id: int + legal_notice_name: Optional[str] = dataclass_field(default=None, kw_only=True) """LegalNoticeResponse""" - legal_notice_html: Optional[str] = None + legal_notice_html: Optional[str] = dataclass_field(default=None, kw_only=True) """HTML content of the legal notice.""" @@ -979,9 +1507,24 @@ class AccessResponse: Definition: AccessResponse """ - authentication: Optional[AuthenticationResponse] = None - authentication_signing: Optional[AuthenticationSigningResponse] = None - access_duration: Optional[PermissionAccessDurationResponse] = None + authentication: Optional[ + AuthenticationResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + authentication_signing: Optional[ + AuthenticationSigningResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + access_duration: Optional[ + PermissionAccessDurationResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -990,11 +1533,26 @@ class AuthenticationResponse: Definition: AuthenticationResponse """ - enabled: Optional[bool] = None + enabled: bool """True, if authentication is enabled for the package.""" - password: Optional[AccessSecurityPasswordResponse] = None - sms_otp: Optional[AccessSecuritySmsOtpResponse] = None - totp: Optional[TotpPermissionResponse] = None + password: Optional[ + AccessSecurityPasswordResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + sms_otp: Optional[ + AccessSecuritySmsOtpResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + totp: Optional[ + TotpPermissionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1003,9 +1561,9 @@ class AccessSecurityPasswordResponse: Definition: AccessSecurityPasswordResponse """ - enabled: Optional[bool] = None + enabled: bool """True, if password authentication is enabled for the package.""" - user_password: Optional[str] = None + user_password: Optional[str] = dataclass_field(default=None, kw_only=True) """Authentication password for document access.""" @@ -1015,16 +1573,16 @@ class AccessSecuritySmsOtpResponse: Definition: AccessSecuritySmsOtpResponse """ - enabled: Optional[bool] = None + enabled: bool """True, if SMS OTP authentication is enabled for the package.""" - otp_length: Optional[int] = None - retry_duration: Optional[int] = None - mobile_number: Optional[str] = None + otp_length: int + retry_duration: int + mobile_number: Optional[str] = dataclass_field(default=None, kw_only=True) """ Mobile number of the recipient. Mobile number is needed to send the SMS to the recipient for the authentication. """ - methods: Optional[List[str]] = None + methods: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Allowed OTP Methods""" @@ -1034,7 +1592,7 @@ class TotpPermissionResponse: Definition: TotpPermissionResponse """ - enabled: Optional[bool] = None + enabled: bool """Enabled""" @@ -1044,10 +1602,20 @@ class AuthenticationSigningResponse: Definition: AuthenticationSigningResponse """ - enabled: Optional[bool] = None + enabled: bool """True, if authentication is enabled for the package.""" - sms_otp: Optional[AuthenticationSigningSmsOtpResponse] = None - totp: Optional[TotpPermissionResponse] = None + sms_otp: Optional[ + AuthenticationSigningSmsOtpResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + totp: Optional[ + TotpPermissionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1056,14 +1624,14 @@ class AuthenticationSigningSmsOtpResponse: Definition: AuthenticationSigningSmsOtpResponse """ - otp_length: Optional[int] = None - retry_duration: Optional[int] = None - mobile_number: Optional[str] = None + otp_length: int + retry_duration: int + mobile_number: Optional[str] = dataclass_field(default=None, kw_only=True) """ Mobile number of the recipient. Mobile number is needed to send the SMS to the recipient for the authentication. """ - methods: Optional[List[str]] = None + methods: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Allowed OTP Methods""" @@ -1073,10 +1641,20 @@ class PermissionAccessDurationResponse: Definition: PermissionAccessDurationResponse """ - enabled: Optional[bool] = None + enabled: bool """True, if access duration security is enabled for the package.""" - duration_by_date: Optional[AccessDurationByDateResponse] = None - duration_by_days: Optional[AccessDurationByDaysResponse] = None + duration_by_date: Optional[ + AccessDurationByDateResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + duration_by_days: Optional[ + AccessDurationByDaysResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1085,10 +1663,15 @@ class AccessDurationByDateResponse: Definition: AccessDurationByDateResponse """ - enabled: Optional[bool] = None + enabled: bool """True if access security is enabled for a duration by date and time.""" - accessible: Optional[bool] = None - duration: Optional[DurationByDateResponse] = None + accessible: bool + duration: Optional[ + DurationByDateResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1097,11 +1680,11 @@ class DurationByDateResponse: Definition: DurationByDateResponse """ - start_date_time: Optional[str] = None + start_date_time: Optional[str] = dataclass_field(default=None, kw_only=True) """ Date and time from where the package will be accessible to the recipient. """ - end_date_time: Optional[str] = None + end_date_time: Optional[str] = dataclass_field(default=None, kw_only=True) """ Date and time after which the package will not be accessible to the recipient. @@ -1114,10 +1697,15 @@ class AccessDurationByDaysResponse: Definition: AccessDurationByDaysResponse """ - enabled: Optional[bool] = None + enabled: bool """True, if access security is enabled for a duration by number of days.""" - accessible: Optional[bool] = None - duration: Optional[DurationByDaysResponse] = None + accessible: bool + duration: Optional[ + DurationByDaysResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1126,7 +1714,7 @@ class DurationByDaysResponse: Definition: DurationByDaysResponse """ - total_days: Optional[int] = None + total_days: int """ Total number of days for which the package will be accessible to the recipient after receiving the package. @@ -1139,16 +1727,16 @@ class ReminderRepeat: Definition: ReminderRepeat """ - enabled: Optional[bool] = None + enabled: bool """True, if subsequent reminders are enabled.""" - frequency: Optional[str] = None + frequency: Optional[str] = dataclass_field(default=None, kw_only=True) """Repeat Reminder Frequency. Possible Values are DAYS | HOURS. """ - keep_reminding_after: Optional[int] = None + keep_reminding_after: int """ The number of days after which the subsequent reminders would be sent to workflow recipient. """ - total_reminders: Optional[int] = None + total_reminders: int """The number of subsequent reminders to be sent to workflow user.""" @@ -1158,14 +1746,19 @@ class AccessUpdateRequest: Definition: AccessUpdateRequest """ - apply_to_all: Optional[bool] = None + apply_to_all: bool """ True, if the access security or authentications are to be applied on all the recipients in the workflow. """ - authentication: Optional[AccessAuthentication] = None - authentication_signing: Optional[SigningAuthentication] = None - access_duration: Optional[PermissionAccessDuration] = None + authentication: AccessAuthentication | Mapping[str, Any] + authentication_signing: Optional[ + SigningAuthentication | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + access_duration: PermissionAccessDuration | Mapping[str, Any] @dataclass @@ -1174,11 +1767,26 @@ class AccessAuthentication: Definition: AccessAuthentication """ - enabled: Optional[bool] = None + enabled: bool """True, if authentication is enabled for the package.""" - password: Optional[AuthenticationPassword] = None - sms_otp: Optional[AuthenticationSmsOtp] = None - totp: Optional[TotpPermissionResponse] = None + password: Optional[ + AuthenticationPassword | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + sms_otp: Optional[ + AuthenticationSmsOtp | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + totp: Optional[ + TotpPermissionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1187,9 +1795,9 @@ class AuthenticationPassword: Definition: AuthenticationPassword """ - enabled: Optional[bool] = None + enabled: bool """True, if password authentication is enabled for the package.""" - user_password: Optional[str] = None + user_password: Optional[str] = dataclass_field(default=None, kw_only=True) """ Password string if password field is enabled. If a password is already set and owner do not wish to change it, remove the field from the response, or @@ -1203,9 +1811,9 @@ class AuthenticationSmsOtp: Definition: AuthenticationSmsOtp """ - enabled: Optional[bool] = None + enabled: bool """True, if SMS OTP authentication is enabled for the package.""" - mobile_number: Optional[str] = None + mobile_number: Optional[str] = dataclass_field(default=None, kw_only=True) """ Mobile number of the recipient. Mobile number is needed to send the SMS to the recipient for the authentication. @@ -1218,10 +1826,20 @@ class SigningAuthentication: Definition: SigningAuthentication """ - enabled: Optional[bool] = None + enabled: bool """True, if authentication is enabled for the package.""" - sms_otp: Optional[AuthenticationSigningSmsOtp] = None - totp: Optional[TotpPermissionResponse] = None + sms_otp: Optional[ + AuthenticationSigningSmsOtp | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + totp: Optional[ + TotpPermissionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1230,7 +1848,7 @@ class AuthenticationSigningSmsOtp: Definition: AuthenticationSigningSmsOtp """ - mobile_number: Optional[str] = None + mobile_number: Optional[str] = dataclass_field(default=None, kw_only=True) """ Mobile number of the recipient. Mobile number is needed to send the SMS to the recipient for the authentication. @@ -1243,10 +1861,20 @@ class PermissionAccessDuration: Definition: PermissionAccessDuration """ - enabled: Optional[bool] = None + enabled: bool """True, if access duration security is enabled for the package.""" - duration_by_date: Optional[AccessDurationByDate] = None - duration_by_days: Optional[AccessDurationByDays] = None + duration_by_date: Optional[ + AccessDurationByDate | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + duration_by_days: Optional[ + AccessDurationByDays | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1255,9 +1883,14 @@ class AccessDurationByDate: Definition: AccessDurationByDate """ - enabled: Optional[bool] = None + enabled: bool """True if access security is enabled for a duration by date and time.""" - duration: Optional[DurationByDate] = None + duration: Optional[ + DurationByDate | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1266,11 +1899,11 @@ class DurationByDate: Definition: DurationByDate """ - start_date_time: Optional[str] = None + start_date_time: Optional[str] = dataclass_field(default=None, kw_only=True) """ Date and time from where the package will be accessible to the recipient. """ - end_date_time: Optional[str] = None + end_date_time: Optional[str] = dataclass_field(default=None, kw_only=True) """ Date and time after which the package will not be accessible to the recipient. @@ -1283,9 +1916,14 @@ class AccessDurationByDays: Definition: AccessDurationByDays """ - enabled: Optional[bool] = None + enabled: bool """True, if access security is enabled for a duration by number of days.""" - duration: Optional[DurationByDays] = None + duration: Optional[ + DurationByDays | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1294,7 +1932,7 @@ class DurationByDays: Definition: DurationByDays """ - total_days: Optional[int] = None + total_days: int """ Total number of days for which the package will be accessible to the recipient after receiving the package. @@ -1307,23 +1945,28 @@ class QrCodeRequest: Definition: QrCodeRequest """ - page_no: Optional[int] = None + page_no: int """Page number on which the field is to be created.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the provided field that is to be added. If not provided, system will assign an unique auto generated name to the field. """ - dimensions: Optional[FieldDimension] = None - data: Optional[str] = None + dimensions: FieldDimension | Mapping[str, Any] + data: Optional[str] = dataclass_field(default=None, kw_only=True) """ The plain text data to be encoded in the QR code. Default is URL generated to access the related document. e.g. {base_url}/document/{document_unique_id} """ - options: Optional[QrCodeOptions] = None - color: Optional[QrCodeColor] = None - logo: Optional[QrCodeLogo] = None + options: Optional[ + QrCodeOptions | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + color: Optional[QrCodeColor | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + logo: Optional[QrCodeLogo | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1332,13 +1975,13 @@ class FieldDimension: Definition: FieldDimension """ - x: Optional[float] = None + x: float """Left location of the field in pixel.""" - y: Optional[float] = None + y: float """Top location of the field in pixel.""" - width: Optional[float] = None + width: float """Width of the field in pixel.""" - height: Optional[float] = None + height: float """Height of the field in pixel.""" @@ -1348,15 +1991,15 @@ class QrCodeOptions: Definition: QrCodeOptions """ - error_correction_level: Optional[ECCLevelAPI] = None - encoding: Optional[EciModeAPI] = None - pixels_per_module: Optional[int] = None + error_correction_level: ECCLevelAPI + encoding: EciModeAPI + pixels_per_module: int """ Specifies the number of pixels per module in the QR code. A higher number results in a larger and more detailed QR code. Default is \"20\" Possible Values are : 20 | 30 | 40 | 50 """ - add_margins: Optional[bool] = None + add_margins: bool """ Indicates whether quiet zones (margins) should be drawn around the QR code. Quiet zones help scanners to detect and decode the QR code more accurately. @@ -1376,12 +2019,12 @@ class QrCodeColor: Definition: QrCodeColor """ - dots: Optional[str] = None + dots: Optional[str] = dataclass_field(default=None, kw_only=True) """ Represents the dark color used for the dots in the QR code. Default is \"black\". e.g. \"#000000\" """ - background: Optional[str] = None + background: Optional[str] = dataclass_field(default=None, kw_only=True) """ Represents the light color used for the background of the QR code. Default is \"white\". e.g. \"#ffffff\" @@ -1394,14 +2037,14 @@ class QrCodeLogo: Definition: QrCodeLogo """ - base64: Optional[str] = None + base64: Optional[str] = dataclass_field(default=None, kw_only=True) """An optional icon (base64) to place in the center of the QR code.""" - hide_background_dots: Optional[bool] = None + hide_background_dots: bool """ The background color behind the icon, if an icon is provided. If color is not provided transparent background is implemented. """ - size: Optional[int] = None + size: int """ The size of the icon as a percentage of the QR code's size, if an icon is provided. Default is \"15\". Possible Values are : 10 | 15 | 20 | 25 | 30 | @@ -1424,10 +2067,20 @@ class SignatureFieldAuthentication: Definition: SignatureFieldAuthentication """ - enabled: Optional[bool] = None + enabled: bool """True, if authentication is enabled for the field. False otherwise.""" - otp: Optional[SignatureFieldAuthenticationOtp] = None - totp: Optional[SignatureFieldAuthenticationTotp] = None + otp: Optional[ + SignatureFieldAuthenticationOtp | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + totp: Optional[ + SignatureFieldAuthenticationTotp | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1436,12 +2089,12 @@ class SignatureFieldAuthenticationOtp: Definition: SignatureFieldAuthenticationOtp """ - enabled: Optional[bool] = None + enabled: bool """ True, if SMS/Email OTP authentication is enabled for the field. False otherwise. """ - mobile_number: Optional[str] = None + mobile_number: Optional[str] = dataclass_field(default=None, kw_only=True) """Mobile number of the recipient to which the field is assigned.""" @@ -1451,7 +2104,7 @@ class SignatureFieldAuthenticationTotp: Definition: SignatureFieldAuthenticationTotp """ - enabled: Optional[bool] = None + enabled: bool """ True, if TOTP authentication is enabled for the field. False otherwise. """ @@ -1463,22 +2116,27 @@ class UpdateQrCodeRequest: Definition: UpdateQrCodeRequest """ - field_name: Optional[str] = None + field_name: str """Current name of the field, that is to be updated.""" - renamed_as: Optional[str] = None + renamed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """Updated name of the field if renaming is intended.""" - page_no: Optional[int] = None + page_no: int """Page number for which field is need to be updated""" - dimensions: Optional[FieldDimension] = None - data: Optional[str] = None + dimensions: FieldDimension | Mapping[str, Any] + data: Optional[str] = dataclass_field(default=None, kw_only=True) """ The plain text data to be encoded in the QR code. Default is URL generated to access the related document. e.g. {base_url}/document/{document_unique_id} """ - options: Optional[QrCodeOptions] = None - color: Optional[QrCodeColor] = None - logo: Optional[QrCodeLogo] = None + options: Optional[ + QrCodeOptions | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + color: Optional[QrCodeColor | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + logo: Optional[QrCodeLogo | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1487,8 +2145,13 @@ class FieldValidationValue: Definition: FieldValidationValue """ - required: Optional[bool] = None - rules: Optional[List[FieldValidationValueRule]] = None + required: bool + rules: Optional[ + List[FieldValidationValueRule | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1497,12 +2160,16 @@ class FieldValidationValueRule: Definition: FieldValidationValueRule """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """ Specifies the type of validation rule, which is currently always set to EQUALS for text field. """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Represents the value used for validation.""" @@ -1512,44 +2179,49 @@ class PostProcessResponse: Definition: PostProcessResponse """ - enabled: Optional[bool] = None + enabled: bool """True, if post processing is enabled for the package.""" - contacts: Optional[List[str]] = None + contacts: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ List of email addresses to which the email will be sent when the workflow is completed. """ - recipients: Optional[List[PostProcessRecipientResponse]] = None + recipients: Optional[ + List[PostProcessRecipientResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """ List of the name and email addresses to whom the emails are sent when the post processing is executed after the workflow completion. """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """ Any custom string message that is to be sent to the contacts when the workflow is completed. """ - google_drive: Optional[bool] = None + google_drive: bool """ True, if google drive uploading is turned on for the package. Documents will be uploaded to google drive when the workflow is completed. """ - one_drive: Optional[bool] = None + one_drive: bool """ True, if one drive uploading is turned on for the package. Documents will be uploaded to one drive when the workflow is completed. """ - dropbox: Optional[bool] = None + dropbox: bool """ True, if dropbox uploading is turned on for the package. Documents will be uploaded to google drive when the workflow is completed. """ - workflow_recipients: Optional[bool] = None + workflow_recipients: bool """ True, if workflow completion report is to be sent to all recipients of the workflow when post processing is executed. Default value is false. """ - document_processing_report: Optional[bool] = None + document_processing_report: bool """ True, if Send the document processing report (XML) is to be enabled to for the workflow @@ -1562,8 +2234,8 @@ class PostProcessRecipientResponse: Definition: PostProcessRecipientResponse """ - name: Optional[str] = None - email: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + email: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1572,14 +2244,14 @@ class CertifyResponse: Definition: CertifyResponse """ - enabled: Optional[bool] = None + enabled: bool """True, if certify signature settings are enabled for the document.""" - allowed_permissions: Optional[List[str]] = None + allowed_permissions: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ Certify permission level set for the document with certify signature settings. """ - default_permission: Optional[str] = None + default_permission: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1588,9 +2260,9 @@ class GroupMemberResponse: Definition: GroupMemberResponse """ - user_email: Optional[str] = None + user_email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the group member""" - user_name: Optional[str] = None + user_name: Optional[str] = dataclass_field(default=None, kw_only=True) """User name of the group member""" @@ -1600,7 +2272,7 @@ class AttachmentPermissionResponse: Definition: AttachmentPermissionResponse """ - enabled: Optional[bool] = None + enabled: bool """Enabled""" @@ -1616,8 +2288,8 @@ class PostProcessRecipientRequest: Definition: PostProcessRecipientRequest """ - name: Optional[str] = None - email: Optional[str] = None + name: str + email: str @dataclass @@ -1626,8 +2298,13 @@ class UpdateCertifyPolicyRequest: Definition: UpdateCertifyPolicyRequest """ - certify: Optional[CertifyPolicyRequest] = None - lock_form_fields: Optional[bool] = None + certify: Optional[ + CertifyPolicyRequest | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + lock_form_fields: bool """ True if form fields are to be locked after the last signature on the current document. @@ -1640,9 +2317,9 @@ class CertifyPolicyRequest: Definition: CertifyPolicyRequest """ - enabled: Optional[bool] = None + enabled: bool """True if certify settings are to be enabled for the document.""" - permission: Optional[CertifyPermission] = None + permission: CertifyPermission CertifyPermission = Literal[ @@ -1658,7 +2335,7 @@ class DeleteDocumentFieldRequest: Definition: DeleteDocumentFieldRequest """ - field_name: Optional[str] = None + field_name: str """Name of the field to be deleted.""" @@ -1688,9 +2365,9 @@ class EnterpriseTemplateRole: Definition: EnterpriseTemplateRole """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the enterprise role assigned to the user.""" - id: Optional[int] = None + id: int """Id of the enterprise role assigned to the user.""" @@ -1700,9 +2377,9 @@ class TemplateDocumentResponse: Definition: TemplateDocumentResponse """ - id: Optional[int] = None + id: int """Id of the template document """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the template document.""" @@ -1721,9 +2398,9 @@ class NextSignerEmail: Definition: Next_signer_email """ - user_email: Optional[str] = None + user_email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the next signer.""" - user_name: Optional[str] = None + user_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the next signer.""" @@ -1733,7 +2410,12 @@ class WorkflowGatekeeperResponse: Definition: WorkflowGatekeeperResponse """ - emails: Optional[List[WorkflowGatekeeperUserResponse]] = None + emails: Optional[ + List[WorkflowGatekeeperUserResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Getekeepers""" @@ -1743,7 +2425,7 @@ class WorkflowGatekeeperUserResponse: Definition: WorkflowGatekeeperUserResponse """ - user_email: Optional[str] = None + user_email: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1752,11 +2434,26 @@ class EnterpriseAuthenticationResponse: Definition: EnterpriseAuthenticationResponse """ - enabled: Optional[bool] = None + enabled: bool """True, if authentication is enabled for the package.""" - password: Optional[AccessSecurityPasswordResponse] = None - sms_otp: Optional[EnterpriseAccessSecuritySmsOtpResponse] = None - totp: Optional[TotpPermissionResponse] = None + password: Optional[ + AccessSecurityPasswordResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + sms_otp: Optional[ + EnterpriseAccessSecuritySmsOtpResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + totp: Optional[ + TotpPermissionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1765,11 +2462,11 @@ class EnterpriseAccessSecuritySmsOtpResponse: Definition: EnterpriseAccessSecuritySmsOtpResponse """ - enabled: Optional[bool] = None + enabled: bool """True, if SMS OTP authentication is enabled for the package.""" - otp_length: Optional[int] = None - retry_duration: Optional[int] = None - mobile_number: Optional[str] = None + otp_length: int + retry_duration: int + mobile_number: Optional[str] = dataclass_field(default=None, kw_only=True) """ Mobile number of the recipient. Mobile number is needed to send the SMS to the recipient for the authentication. @@ -1782,10 +2479,20 @@ class EnterpriseAuthenticationSigningResponse: Definition: EnterpriseAuthenticationSigningResponse """ - enabled: Optional[bool] = None + enabled: bool """True, if authentication is enabled for the package.""" - sms_otp: Optional[EnterpriseAuthenticationSigningSmsOtpResponse] = None - totp: Optional[TotpPermissionResponse] = None + sms_otp: Optional[ + EnterpriseAuthenticationSigningSmsOtpResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + totp: Optional[ + TotpPermissionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1794,9 +2501,9 @@ class EnterpriseAuthenticationSigningSmsOtpResponse: Definition: EnterpriseAuthenticationSigningSmsOtpResponse """ - otp_length: Optional[int] = None - retry_duration: Optional[int] = None - mobile_number: Optional[str] = None + otp_length: int + retry_duration: int + mobile_number: Optional[str] = dataclass_field(default=None, kw_only=True) """ Mobile number of the recipient. Mobile number is needed to send the SMS to the recipient for the authentication. @@ -1809,9 +2516,9 @@ class DocumentOwner: Definition: DocumentOwner """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the document package owner.""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email of the document package owner.""" @@ -1821,19 +2528,23 @@ class DocumentDetails: Definition: DocumentDetails """ - id: Optional[int] = None + id: int """ID of the newly created document.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the document.""" - uploaded_on: Optional[str] = None + uploaded_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time when the document was uploaded.""" - modified_on: Optional[str] = None + modified_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time when the document was last modified.""" - size: Optional[int] = None + size: int """Size of the document in bytes.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type of the document e.g. \"PDF\".""" - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Identifies where the document was uploaded e.g. \"My App\".""" @@ -1843,9 +2554,9 @@ class ChangeServicePlanRequest: Definition: ChangeServicePlanRequest """ - user_email: Optional[str] = None + user_email: str """Email address of the account owner.""" - service_plan: Optional[str] = None + service_plan: str """New Service Plan name, which is to be assigned to the user.""" @@ -1855,9 +2566,9 @@ class TemplateSmartFormResponse: Definition: TemplateSmartFormResponse """ - active_count: Optional[int] = None + active_count: int """Active count """ - total_count: Optional[int] = None + total_count: int """Total""" @@ -1867,14 +2578,14 @@ class ServicePlanLevelOfAssurance: Definition: ServicePlanLevelOfAssurance """ - allowed: Optional[List[str]] = None + allowed: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ Allowed level of assurances, Possible values are: ADVANCED_ELECTRONIC_SIGNATURE, HIGH_TRUST_ADVANCED, QUALIFIED_ELECTRONIC_SIGNATURE, ELECTRONIC_SEAL, ADVANCED_ELECTRONIC_SEAL, QUALIFIED_ELECTRONIC_SEAL, ELECTRONIC_SIGNATURE """ - default: Optional[List[str]] = None + default: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ Default level of assurances, Possible values are: ADVANCED_ELECTRONIC_SIGNATURE, HIGH_TRUST_ADVANCED, @@ -1889,12 +2600,12 @@ class ServicePlanCertifyOption: Definition: ServicePlanCertifyOption """ - allowed: Optional[List[str]] = None + allowed: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ Allowed document certify options, Possible values are: NO_CHANGES_ALLOWED, FORM_FILLING_ALLOWED, FORM_FILLING_WITH_ANNOTATIONS_ALLOWED """ - default: Optional[str] = None + default: Optional[str] = dataclass_field(default=None, kw_only=True) """ Default document certify options, Possible values are: NO_CHANGES_ALLOWED, FORM_FILLING_ALLOWED, FORM_FILLING_WITH_ANNOTATIONS_ALLOWED @@ -1907,12 +2618,22 @@ class ServicePlanAutoDeleteDocument: Definition: ServicePlanAutoDeleteDocument """ - enabled: Optional[bool] = None + enabled: bool """True, If auto deletion of the unused documents is enabled.""" - duration: Optional[int] = None + duration: int """Total number of unused days. """ - notify: Optional[NotifyUnUsedDeleteDocument] = None - email_document: Optional[EmailDeletedDocument] = None + notify: Optional[ + NotifyUnUsedDeleteDocument | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + email_document: Optional[ + EmailDeletedDocument | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1921,9 +2642,9 @@ class NotifyUnUsedDeleteDocument: Definition: NotifyUnUsedDeleteDocument """ - enabled: Optional[bool] = None + enabled: bool """True, If notify the user before days to deleting unused documents.""" - duration: Optional[int] = None + duration: int """Total number of days before notifying the user. """ @@ -1933,9 +2654,9 @@ class EmailDeletedDocument: Definition: EmailDeletedDocument """ - enabled: Optional[bool] = None + enabled: bool """True, If deleted document as attachment is enabled""" - workflow_evidence_report: Optional[bool] = None + workflow_evidence_report: bool """ True, Email the workflow evidence report as an attachment of the completed document is enabled @@ -1948,19 +2669,64 @@ class ServicePlanSigningServer: Definition: ServicePlanSigningServer """ - key_location: Optional[str] = None + key_location: Optional[str] = dataclass_field(default=None, kw_only=True) """Key location of the signing server, possible values are SERVER, LOCAL""" - order: Optional[int] = None + order: Optional[int] = dataclass_field(default=None, kw_only=True) """Signing server order""" - signing_profile: Optional[ServicePlanProfile] = None - electronic_seal: Optional[SigningServerCapacity] = None - advanced_electronic_seal: Optional[SigningServerCapacity] = None - qualified_electronic_seal: Optional[SigningServerCapacity] = None - advanced_electronic_signature: Optional[SigningServerCapacity] = None - high_trust_advanced_signature: Optional[SigningServerCapacity] = None - qualified_electronic_signature: Optional[SigningServerCapacity] = None - signature_appearances: Optional[SigningServerSignatureAppearance] = None - csp: Optional[SigningServerCsp] = None + signing_profile: Optional[ + ServicePlanProfile | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + electronic_seal: Optional[ + SigningServerCapacity | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + advanced_electronic_seal: Optional[ + SigningServerCapacity | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + qualified_electronic_seal: Optional[ + SigningServerCapacity | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + advanced_electronic_signature: Optional[ + SigningServerCapacity | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + high_trust_advanced_signature: Optional[ + SigningServerCapacity | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + qualified_electronic_signature: Optional[ + SigningServerCapacity | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + signature_appearances: Optional[ + SigningServerSignatureAppearance | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + csp: Optional[ + SigningServerCsp | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1969,9 +2735,9 @@ class ServicePlanProfile: Definition: ServicePlanProfile """ - id: Optional[int] = None + id: int """ID of the profile""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the profile""" @@ -1981,9 +2747,14 @@ class SigningServerCapacity: Definition: SigningServerCapacity """ - enabled: Optional[bool] = None + enabled: bool """True, If to add the Signing Capacities.""" - capacities: Optional[List[ServicePlanCapacity]] = None + capacities: Optional[ + List[ServicePlanCapacity | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Total number of Signing Capacities added are signing server.""" @@ -1993,18 +2764,18 @@ class ServicePlanCapacity: Definition: ServicePlanCapacity """ - id: Optional[int] = None + id: int """Id of the Capacity""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the Capacity""" - level_of_assurance: Optional[str] = None + level_of_assurance: Optional[str] = dataclass_field(default=None, kw_only=True) """ Level of assurance of the capacity, possible values are ADVANCED_ELECTRONIC_SIGNATURE, HIGH_TRUST_ADVANCED, QUALIFIED_ELECTRONIC_SIGNATURE, ELECTRONIC_SEAL, ADVANCED_ELECTRONIC_SEAL, QUALIFIED_ELECTRONIC_SEAL. """ - key_protection: Optional[str] = None + key_protection: Optional[str] = dataclass_field(default=None, kw_only=True) """ Key protection option of the capacity, possible values are NO_PASSWORD, USER_PASSWORD, SYSTEM_PASSWORD, REMOTE_AUTHORISATION. @@ -2017,12 +2788,12 @@ class SigningServerSignatureAppearance: Definition: SigningServerSignatureAppearance """ - signature_appearance: Optional[str] = None + signature_appearance: Optional[str] = dataclass_field(default=None, kw_only=True) """ Appearances of the signature, possible values are COMPANY_LOGO, HAND_SIGNATURE, DETAILED_SIGNATURE """ - signature_appearance_logo: Optional[str] = None + signature_appearance_logo: Optional[str] = dataclass_field(default=None, kw_only=True) """Logo of the signature appearance""" @@ -2032,10 +2803,15 @@ class SigningServerCsp: Definition: SigningServerCsp """ - enabled: Optional[bool] = None + enabled: bool """True, If to add Push Certificates to CSP.""" - virtual_profile: Optional[ServicePlanProfile] = None - auto_delete_certificates: Optional[bool] = None + virtual_profile: Optional[ + ServicePlanProfile | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + auto_delete_certificates: bool """ True, If Automatically delete certificates and users from CSP when user is removed. @@ -2048,10 +2824,30 @@ class ServicePlanElectronicSealServer: Definition: ServicePlanElectronicSealServer """ - electronic_seal_profile: Optional[ServicePlanProfile] = None - electronic_seal: Optional[SigningServerCapacity] = None - advanced_electronic_seal: Optional[SigningServerCapacity] = None - qualified_electronic_seal: Optional[SigningServerCapacity] = None + electronic_seal_profile: Optional[ + ServicePlanProfile | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + electronic_seal: Optional[ + SigningServerCapacity | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + advanced_electronic_seal: Optional[ + SigningServerCapacity | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + qualified_electronic_seal: Optional[ + SigningServerCapacity | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -2060,9 +2856,19 @@ class ServicePlanAuthenticationProfile: Definition: ServicePlanAuthenticationProfile """ - allowed: Optional[List[ServicePlanProfile]] = None + allowed: Optional[ + List[ServicePlanProfile | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Allowed authentication profile in service plan""" - default: Optional[ServicePlanProfile] = None + default: Optional[ + ServicePlanProfile | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -2071,12 +2877,16 @@ class ServicePlanEvidenceReport: Definition: ServicePlanEvidenceReport """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """ Type of workflow evidence recording, Possible values are \"BASIC\", \"DETAILED\" """ - delete_document_logs: Optional[bool] = None + delete_document_logs: bool """ True, If enable to delete document logs on generation of Workflow Evidence Report. @@ -2089,13 +2899,23 @@ class ServicePlanOneTimePassword: Definition: ServicePlanOneTimePassword """ - email_otp: Optional[ServicePlanEmailOtp] = None - sms_otp: Optional[ServicePlanSmsOtp] = None - otp_length: Optional[int] = None + email_otp: Optional[ + ServicePlanEmailOtp | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + sms_otp: Optional[ + ServicePlanSmsOtp | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + otp_length: int """Character count of OTP to be generated for authentication.""" - otp_expiry: Optional[int] = None + otp_expiry: int """OTP expiry duration in seconds""" - otp_retry_interval: Optional[int] = None + otp_retry_interval: int """OTP retry interval duration in seconds""" @@ -2105,7 +2925,7 @@ class ServicePlanEmailOtp: Definition: ServicePlanEmailOtp """ - enabled: Optional[bool] = None + enabled: bool """True, if Email OTP are enabled for the service plan.""" @@ -2115,9 +2935,9 @@ class ServicePlanSmsOtp: Definition: ServicePlanSmsOtp """ - enabled: Optional[bool] = None + enabled: bool """True, if SMS OTP are enabled for the service plan.""" - server: Optional[str] = None + server: Optional[str] = dataclass_field(default=None, kw_only=True) """SMS OTP server""" @@ -2127,10 +2947,11 @@ class ServicePlanSmtpServer: Definition: ServicePlanSmtpServer """ - enabled: Optional[bool] = None + enabled: bool """True, if SMTP Server is enabled for the service plan.""" - server: Optional[str] = field( + server: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Server"}, ) """SMTP Server""" @@ -2142,10 +2963,11 @@ class ServicePlanSmsNotification: Definition: ServicePlanSmsNotification """ - enabled: Optional[bool] = None + enabled: bool """True, if SMS notification gateway is enabled for the service plan.""" - server: Optional[str] = field( + server: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Server"}, ) """SMS Gateway""" @@ -2157,11 +2979,16 @@ class ServicePlanAutoDeleteUser: Definition: ServicePlanAutoDeleteUser """ - enabled: Optional[bool] = None + enabled: bool """True, If auto deletion of the inactive users is enabled.""" - inactive_days: Optional[int] = None + inactive_days: int """Total number of inactive days. """ - notify: Optional[NotifyInactiveDeleteUser] = None + notify: Optional[ + NotifyInactiveDeleteUser | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -2170,9 +2997,9 @@ class NotifyInactiveDeleteUser: Definition: NotifyInactiveDeleteUser """ - enabled: Optional[bool] = None + enabled: bool """True, If notify the user before days to deleting inactive users.""" - duration: Optional[int] = None + duration: int """Total number of days before notifying the user. """ @@ -2182,7 +3009,7 @@ class ServicePlanCapacityRequest: Definition: ServicePlanCapacityRequest """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the Capacity""" @@ -2192,20 +3019,20 @@ class WorkflowDetailUpdateRequest: Definition: WorkflowDetailUpdateRequest """ - workflow_type: Optional[WorkflowType] = None - workflow_mode: Optional[WorkflowModes] = None - continue_on_decline: Optional[bool] = None + workflow_type: Optional[WorkflowType] = dataclass_field(default=None, kw_only=True) + workflow_mode: Optional[WorkflowModes] = dataclass_field(default=None, kw_only=True) + continue_on_decline: Optional[bool] = dataclass_field(default=None, kw_only=True) """ True, if workflow needs to continue even if any recipient declines the document. If no value is provided, old value will be retained. """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """ A custom string message from the document owner to every recipient, this message appears in the sharing email as well as on the screen. If no value is provided, old value will be retained. """ - comments: Optional[bool] = None + comments: Optional[bool] = dataclass_field(default=None, kw_only=True) """Allow comments""" @@ -2218,40 +3045,45 @@ class PostProcessUpdateRequest: Definition: PostProcessUpdateRequest """ - enabled: Optional[bool] = None + enabled: bool """True, if post processing is turned on for the package.""" - contacts: Optional[List[str]] = None - recipients: Optional[List[PostProcessRecipientRequest]] = None + contacts: Optional[List[str]] = dataclass_field(default=None, kw_only=True) + recipients: Optional[ + List[PostProcessRecipientRequest | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """ List of the name and email addresses to whom the emails are sent when the post processing is executed after the workflow completion. """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """ A custom string message for all the contacts. Message becomes part of the email sent to the contacts. """ - google_drive: Optional[bool] = None + google_drive: Optional[bool] = dataclass_field(default=None, kw_only=True) """ True, if document is to be uploaded to the provided google account after the workflow completion. """ - dropbox: Optional[bool] = None + dropbox: Optional[bool] = dataclass_field(default=None, kw_only=True) """ True, if document is to be uploaded to the provided dropbox account after the workflow completion. """ - onedrive: Optional[bool] = None + onedrive: Optional[bool] = dataclass_field(default=None, kw_only=True) """ True, if document is to be uploaded to the provided oneDrive account after the workflow completion. """ - workflow_recipients: Optional[bool] = None + workflow_recipients: bool """ True, if workflow completion report is to be sent to all recipients of the workflow when post processing is executed. Default value is false. """ - document_processing_report: Optional[bool] = None + document_processing_report: bool """ True, if Send the document processing report (XML) is to be enabled to for the workflow @@ -2264,26 +3096,26 @@ class WorflowUserRequest: Definition: WorflowUserRequest """ - user_email: Optional[str] = None + user_email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the user to be added in the workflow.""" - user_name: Optional[str] = None + user_name: str """Name of the recipient to be added in the workflow.""" - user_national_id: Optional[str] = None + user_national_id: Optional[str] = dataclass_field(default=None, kw_only=True) """User national id of the recipient""" - email_notification: Optional[bool] = None + email_notification: bool """ If set as true, SigningHub will send notifications to the user via email as per the document owner and user notification settings. A value of false means no notifications will be sent to user throughout the workflow. """ - role: Optional[CollaboratorRole] = None - signing_order: Optional[int] = None + role: CollaboratorRole + signing_order: Optional[int] = dataclass_field(default=None, kw_only=True) """ Order of the recipient in the workflow. This signing order is mandatory when workflow type is \"CUSTOM\". """ - delivery_method: Optional[DeliveryMethod] = None - mobile_number: Optional[str] = None + delivery_method: DeliveryMethod + mobile_number: Optional[str] = dataclass_field(default=None, kw_only=True) """Mobile Number""" @@ -2303,42 +3135,47 @@ class WorkflowResponse: Definition: WorkflowResponse """ - workflow_type: Optional[str] = None + workflow_type: Optional[str] = dataclass_field(default=None, kw_only=True) """ Type of the workflow, there are four types of workflows supported in the application. Possible values are \"SERIAL\", \"PARALLEL\", \"INDIVIDUAL\" and \"CUSTOM\". """ - continue_on_decline: Optional[bool] = None + continue_on_decline: bool """ True, if workflow needs to be continued even after a recipient declines at his turn. """ - workflow_status: Optional[str] = None + workflow_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Processing status of the workflow, possible values are \"DRAFT\", \"IN_PRGORESS\" and \"COMPLETED\". """ - workflow_mode: Optional[str] = None + workflow_mode: Optional[str] = dataclass_field(default=None, kw_only=True) """ Mode of the workflow, there are three types of workflow modes supported in application. Possible values are \"ONLY_ME\", \"ME_AND_OTHERS\" and \"ONLY_OTHERS\" """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """ Any custom string message that is to be sent to all the recipient of the workflow by the document owner. """ - read_only: Optional[bool] = None + read_only: bool """ If any template applied on the documents in this workflow is read only or locked template then the workflow is read only. SigningHub will not allow the end users to make any changes to this workflow in draft state and this workflow is to be shared as it is. """ - post_process: Optional[PostProcessResponse] = None - comments: Optional[bool] = None + post_process: Optional[ + PostProcessResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + comments: bool """Comments""" @@ -2348,52 +3185,62 @@ class WorkflowDocumentsResponse: Definition: WorkflowDocumentsResponse """ - document_id: Optional[int] = None + document_id: int """ID of the document.""" - document_name: Optional[str] = None + document_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the document.""" - document_type: Optional[str] = None + document_type: Optional[str] = dataclass_field(default=None, kw_only=True) """ Original document extension when the document was uploaded before conversion to the PDF. """ - document_order: Optional[int] = None + document_order: int """Order of the document in the document package.""" - document_source: Optional[str] = None + document_source: Optional[str] = dataclass_field(default=None, kw_only=True) """Source of the document from where the document was uploaded.""" - update_required: Optional[bool] = None + update_required: bool """True if document is required to update """ - document_height: Optional[int] = None + document_height: int """Height of the PDF document.""" - document_width: Optional[int] = None + document_width: int """Width of the PDF document.""" - document_pages: Optional[int] = None + document_pages: int """Total number of pages in the document.""" - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time on which the document was uploaded.""" - modified_on: Optional[str] = None + modified_on: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time on which the document was last modified.""" - form_fields: Optional[bool] = None + form_fields: bool """True, if document has form fields.""" - template: Optional[DocumentsTemplateResponse] = None - certify: Optional[CertifyResponse] = None - lock_form_fields: Optional[bool] = None + template: Optional[ + DocumentsTemplateResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + certify: Optional[ + CertifyResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + lock_form_fields: bool """ True, if document is set to lock the form fields with the last digital signature on the document. """ - locked: Optional[bool] = None - has_signed_signature_fields: Optional[bool] = None + locked: bool + has_signed_signature_fields: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Pdf document meta info: true if pdf document have signed signature fields """ - attachments: Optional[bool] = None + attachments: bool """True, if document has attachments.""" - conformance_level: Optional[str] = None + conformance_level: Optional[str] = dataclass_field(default=None, kw_only=True) """Document conformance level""" - document_size: Optional[int] = None + document_size: int """Size of document.""" - formatted: Optional[bool] = None + formatted: bool """This property is for XML document, that either its formatted or not""" @@ -2403,11 +3250,11 @@ class DocumentsTemplateResponse: Definition: DocumentsTemplateResponse """ - template_id: Optional[int] = None + template_id: int """ID of the template applied to the document.""" - template_name: Optional[str] = None + template_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the template applied to the document.""" - read_only: Optional[bool] = None + read_only: bool """ True, if template is configured as read only. No changes to the workflow should be made after a read only template is applied. @@ -2420,84 +3267,109 @@ class WorkflowUserResponse: Definition: WorkflowUserResponse """ - order: Optional[int] = None + order: int """Order of the recipient in the workflow.""" - user_name: Optional[str] = None + user_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the recipient if recipient is not a group. If recipient is a placeholder it will contain the name of the placeholder. """ - user_email: Optional[str] = None + user_email: Optional[str] = dataclass_field(default=None, kw_only=True) """ Email address of the recipient if recipient is not a group or placeholder. """ - mobile_number: Optional[str] = None + mobile_number: Optional[str] = dataclass_field(default=None, kw_only=True) """Mobile number""" - delivery_method: Optional[str] = None + delivery_method: Optional[str] = dataclass_field(default=None, kw_only=True) """ Delivery method of recipient Possible values: EMAIL, SMS, or EMAIL_AND_SMS """ - user_photo_url: Optional[str] = None + user_photo_url: Optional[str] = dataclass_field(default=None, kw_only=True) """ API endpoint to access the resource, This will be provided only for main signers. e.g it will be null for group/delegator/gatekeeper etc. This URL does not make sure that signer image is exist. If image exist it will be provided by hitting the defined url otherwise it will be an empty string. """ - group_name: Optional[str] = None + group_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the group if recipient is a group.""" - group_members: Optional[List[str]] = None + group_members: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """List of all the email addresses and names of the users.""" - delegator: Optional[str] = None + delegator: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the user who is delegator to this recipient.""" - gatekeeper: Optional[str] = None + gatekeeper: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the user who is gatekeeper to this recipient.""" - gatekeepers: Optional[WorkflowGatekeeperResponse] = None - role: Optional[str] = None + gatekeepers: Optional[ + WorkflowGatekeeperResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + role: Optional[str] = dataclass_field(default=None, kw_only=True) """ Role of the recipient i.e., \"SIGNER\", \"REVIEWER\", \"EDITOR\",\"CARBON_COPY\" or \"INPERSON_HOST\". """ - process_status: Optional[str] = None + process_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Document processing status for the recipient. Possible values are \"UN_PROCESSED\", \"IN_PROGRESS\", \"SIGNED\", \"REVIEWED\", \"DECLINED\", \"EDITED\" or \"INVALID\". """ - processed_on: Optional[str] = None + processed_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time on which the document was processed.""" - processed_as: Optional[str] = None + processed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """ User may processed the field as COLLABORATOR, DELEGATOR, GROUP_MEMBER or OWNER. """ - processed_by: Optional[str] = None + processed_by: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the user who processed the document.""" - reason: Optional[str] = None + reason: Optional[str] = dataclass_field(default=None, kw_only=True) """ Reason provided by the user when declining, approving or submitting a document. """ - placeholder: Optional[str] = None + placeholder: Optional[str] = dataclass_field(default=None, kw_only=True) """Placeholder text if the recipient is a placeholder.""" - permission: Optional[WorkflowPermissionResponse] = None - authentications: Optional[AccessResponse] = None - reminder: Optional[ReminderResponse] = None - signing_order: Optional[int] = None + permission: Optional[ + WorkflowPermissionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + authentications: Optional[ + AccessResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + reminder: Optional[ + ReminderResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + signing_order: int """ Order in which the workflow will be signed by the recipients. This signing order is important when workflow type is set to \"CUSTOM\". """ - user_national_id: Optional[str] = None + user_national_id: Optional[str] = dataclass_field(default=None, kw_only=True) """ National identity number of the user. This helps to identify user in the workflow """ - guest_user: Optional[bool] = None + guest_user: bool """Gest user""" - email_language_code: Optional[str] = None + email_language_code: Optional[str] = dataclass_field(default=None, kw_only=True) """Email language code""" - electronic_seal: Optional[ElectronicSealRecipient] = None + electronic_seal: Optional[ + ElectronicSealRecipient | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -2506,9 +3378,9 @@ class DocumentCertifyResponse: Definition: DocumentCertifyResponse """ - enabled: Optional[bool] = None + enabled: bool """True if certify signature is enabled for the document.""" - permission: Optional[str] = None + permission: Optional[str] = dataclass_field(default=None, kw_only=True) """ It is the certify permissions to be applied on the PDF document when the first signature is created. The possible values are \"NO_CHANGES_ALLOWED\", @@ -2522,9 +3394,9 @@ class DocumentTemplateResponse: Definition: DocumentTemplateResponse """ - template_name: Optional[str] = None + template_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the template applied on the document.""" - read_only: Optional[bool] = None + read_only: bool """ True if the applied template is read only. User will not be able to make any changes if a read only template is applied. @@ -2537,9 +3409,9 @@ class ApplyTemplateRequest: Definition: ApplyTemplateRequest """ - template_name: Optional[str] = None + template_name: str """Name of template to be applied on the document.""" - apply_to_all: Optional[bool] = None + apply_to_all: bool """ True, if template is to be applied on all the documents in the package. """ @@ -2551,13 +3423,13 @@ class AddDocumentPackageRequest: Definition: AddDocumentPackageRequest """ - package_name: Optional[str] = None + package_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ The name of the package. Default package name is always \"Untitled\" if the package_name is not provided. """ - workflow_mode: Optional[WorkflowMode] = None - folder_name: Optional[str] = None + workflow_mode: WorkflowMode + folder_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ The name of the folder. It will be used to upload package in any folder of the user, either it is a custom folder or a shared folder. @@ -2573,7 +3445,7 @@ class ApproveRequest: Definition: ApproveRequest """ - reason: Optional[str] = None + reason: Optional[str] = dataclass_field(default=None, kw_only=True) """The reason for approving a package.""" @@ -2583,7 +3455,7 @@ class DeclineRequest: Definition: DeclineRequest """ - reason: Optional[str] = None + reason: Optional[str] = dataclass_field(default=None, kw_only=True) """Reason provided by the user for declining.""" @@ -2593,7 +3465,7 @@ class RenameDocumentPackageRequest: Definition: RenameDocumentPackageRequest """ - package_name: Optional[str] = None + package_name: str """New name of the document package. """ @@ -2603,9 +3475,9 @@ class RecipientAccessDurationDetails: Definition: RecipientAccessDurationDetails """ - date_from: Optional[str] = None + date_from: Optional[str] = dataclass_field(default=None, kw_only=True) """Start date/time for a recipient to access the document """ - date_to: Optional[str] = None + date_to: Optional[str] = dataclass_field(default=None, kw_only=True) """End date/time for a recipient to access the document """ @@ -2615,11 +3487,16 @@ class RecipientDeclineDetails: Definition: RecipientDeclineDetails """ - reason: Optional[str] = None + reason: Optional[str] = dataclass_field(default=None, kw_only=True) """Define reason of document decline""" - auto_decline: Optional[bool] = None + auto_decline: bool """Indication of document is manually/auto declined """ - declined_by: Optional[DeclineByDetails] = None + declined_by: Optional[ + DeclineByDetails | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -2628,9 +3505,9 @@ class DeclineByDetails: Definition: DeclineByDetails """ - user_name: Optional[str] = None + user_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of user who have declined the workflow """ - user_email: Optional[str] = None + user_email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email of user who have declined the workflow """ @@ -2651,11 +3528,11 @@ class CertifyPermissionResponse: Definition: CertifyPermissionResponse """ - enabled: Optional[bool] = None + enabled: bool """True if certify signature is enabled for the document.""" - allowed_permissions: Optional[List[str]] = None + allowed_permissions: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Set of allowed certify permission levels for the document.""" - default_permission: Optional[str] = None + default_permission: Optional[str] = dataclass_field(default=None, kw_only=True) """Selected permission level for the certify signature settings.""" @@ -2665,27 +3542,27 @@ class UploadDocumentMetaInfoDetail: Definition: UploadDocumentMetaInfoDetail """ - attachments: Optional[bool] = None + attachments: bool """true if pdf document has any attachment""" - form_fields: Optional[bool] = None + form_fields: bool """true if pdf document has any form field""" - blank_signatures: Optional[bool] = None + blank_signatures: bool """true if pdf document has any blank signature field""" - signed_signatures: Optional[bool] = None + signed_signatures: bool """true if pdf document has any signed signature field""" - conformance: Optional[str] = None + conformance: Optional[str] = dataclass_field(default=None, kw_only=True) """ null/empty if document does not contains any conformance level otherwise contains formation like 1A, 1B etc """ - locked: Optional[bool] = None + locked: bool """true if pdf document is locked""" - certify: Optional[str] = None + certify: Optional[str] = dataclass_field(default=None, kw_only=True) """ CertifyLevel of pdf document. Possible values NotCertified, NoChangesAllowed, FormFilling, FormFillingAndAnnotations """ - qr_code: Optional[bool] = None + qr_code: bool """true if pdf document has any Qr Code, otherwise its false""" @@ -2695,7 +3572,7 @@ class RenameDocumentRequest: Definition: RenameDocumentRequest """ - document_name: Optional[str] = None + document_name: str """New name of the document.""" @@ -2708,74 +3585,74 @@ class VerificationResponse: Definition: VerificationResponse """ - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the field for which the verification was requested.""" - signer_name: Optional[str] = None + signer_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the signer.""" - signature_status: Optional[str] = None + signature_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ If the overall status of the signature is valid or not. Possible values are \"VALID\" or \"INVALID\". """ - signing_reason: Optional[str] = None + signing_reason: Optional[str] = dataclass_field(default=None, kw_only=True) """ Reason provided by the user while signing the field. In case of witness signing, custom signing reason would be set """ - signing_location: Optional[str] = None + signing_location: Optional[str] = dataclass_field(default=None, kw_only=True) """Location entered by the user while signing the field.""" - contact_information: Optional[str] = None + contact_information: Optional[str] = dataclass_field(default=None, kw_only=True) """Contact information entered by the user while signing the field.""" - signing_time: Optional[str] = None + signing_time: Optional[str] = dataclass_field(default=None, kw_only=True) """ Date and time of signing in 8601 format. Default timezone from SH Admin is followed the the time. """ - ltv: Optional[bool] = None + ltv: bool """True, if signature is LTV.""" - qualified: Optional[bool] = None + qualified: bool """True, if signatures are qualified.""" - certified: Optional[bool] = None + certified: bool """True, if signatures are certified.""" - certify_permission: Optional[str] = None + certify_permission: Optional[str] = dataclass_field(default=None, kw_only=True) """Permission level for certified digital signature.""" - timestamp_at: Optional[str] = None + timestamp_at: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time when signature was time-stamped.""" - timestamp_authority: Optional[str] = None + timestamp_authority: Optional[str] = dataclass_field(default=None, kw_only=True) """Authority by which the signature was time-stamped.""" - subject_dn: Optional[str] = None + subject_dn: Optional[str] = dataclass_field(default=None, kw_only=True) """Subject DN from the certificate used while signing the field.""" - issuer_dn: Optional[str] = None + issuer_dn: Optional[str] = dataclass_field(default=None, kw_only=True) """Issuers DN from the certificate used while signing the field.""" - cert_valid_from: Optional[str] = None + cert_valid_from: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time from which the certificate is valid.""" - cert_valid_to: Optional[str] = None + cert_valid_to: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time to which the certificate is valid.""" - signature_type: Optional[str] = None + signature_type: Optional[str] = dataclass_field(default=None, kw_only=True) """ Type of signatures, possible values are \"PADES_PART2\" or \"PADES_PART4\". """ - signature_algorithm: Optional[str] = None + signature_algorithm: Optional[str] = dataclass_field(default=None, kw_only=True) """Signature algorithm used while signing the field.""" - signature_application: Optional[str] = None + signature_application: Optional[str] = dataclass_field(default=None, kw_only=True) """Application name from where the field was signed.""" - signature_policy_id: Optional[int] = None + signature_policy_id: int """Signature policy ID.""" - signature_policy_uri: Optional[str] = None + signature_policy_uri: Optional[str] = dataclass_field(default=None, kw_only=True) """Signature policy URI.""" - signer_photo: Optional[str] = None + signer_photo: Optional[str] = dataclass_field(default=None, kw_only=True) """Base64 image of the signer's avatar.""" - signer_photo_url: Optional[str] = None - signed_hash: Optional[str] = None + signer_photo_url: Optional[str] = dataclass_field(default=None, kw_only=True) + signed_hash: Optional[str] = dataclass_field(default=None, kw_only=True) """Hash of the document that was signed in respective signature.""" - display: Optional[str] = None - page_number: Optional[int] = None + display: Optional[str] = dataclass_field(default=None, kw_only=True) + page_number: int """Page number of the signature field""" - lei_number: Optional[str] = None + lei_number: Optional[str] = dataclass_field(default=None, kw_only=True) """LEI number if availbale in certificate""" - lei_role: Optional[str] = None + lei_role: Optional[str] = dataclass_field(default=None, kw_only=True) """LEI role if available in certificate""" - error_message: Optional[str] = None + error_message: Optional[str] = dataclass_field(default=None, kw_only=True) """ An error message returns in case the application unable to get verification results. @@ -2788,38 +3665,48 @@ class BulkSignRequest: Definition: BulkSignRequest """ - ids: Optional[List[int]] = None + ids: Optional[List[int]] = dataclass_field(default=None, kw_only=True) """ An array of the document package ids that are selected for bulk signing. """ - hand_signature_initials_image: Optional[str] = None + hand_signature_initials_image: Optional[str] = dataclass_field(default=None, kw_only=True) """Base64 image used for the filling of the initials""" - hand_signature_initials_method: Optional[HandSignature] = None - hand_signature_image: Optional[str] = None + hand_signature_initials_method: Optional[ + HandSignature + ] = dataclass_field( + default=None, + kw_only=True, + ) + hand_signature_image: Optional[str] = dataclass_field(default=None, kw_only=True) """Base64 encoded string image of the visible signature appearance""" - hand_signature_method: Optional[HandSignature] = None - signing_reason: Optional[str] = None + hand_signature_method: Optional[HandSignature] = dataclass_field(default=None, kw_only=True) + signing_reason: Optional[str] = dataclass_field(default=None, kw_only=True) """Reason of signing provided by the recipient.""" - signing_location: Optional[str] = None + signing_location: Optional[str] = dataclass_field(default=None, kw_only=True) """Locale of the signer provided by the recipient""" - contact_information: Optional[str] = None + contact_information: Optional[str] = dataclass_field(default=None, kw_only=True) """Contact information of the signer provided by the recipient""" - appearance_design: Optional[str] = None + appearance_design: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the signature appearance provided by user for signing. In case no appearance name is provided then default selected appearance would be used. Possible values are \"COMPANY_LOGO\", \"DETAILED_SIGNATURE\", \"HAND_SIGNATURE\" """ - signing_server: Optional[str] = None + signing_server: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of signing server using which the document is to be signed""" - signing_capacity: Optional[str] = None + signing_capacity: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of certification profile/signing capacity using which the document is to be signed """ - authentication: Optional[BulkSignAuthentication] = None - transaction_id: Optional[str] = None + authentication: Optional[ + BulkSignAuthentication | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + transaction_id: Optional[str] = dataclass_field(default=None, kw_only=True) """re-initiated signing process transaction id""" @@ -2829,19 +3716,19 @@ class BulkSignAuthentication: Definition: BulkSignAuthentication """ - mechanism: Optional[str] = None + mechanism: Optional[str] = dataclass_field(default=None, kw_only=True) """ Mechanism of the authentication. Possible values for mechanism are: AUTHENTICATION_PASSWORD, AUTHENTICATION_ACTIVE_DIRECTORY, AUTHENTICATION_AZURE_ACTIVE_DIRECTORY, AUTHENTICATION_OFFICE_365, AUTHENTICATION_OAUTH2, AUTHENTICATION_OIDC """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """ It is an optional parameter, but it's only required when using 'AUTHENTICATION_PASSWORD' as a parameter value under 'mechanism' """ - token: Optional[str] = None + token: Optional[str] = dataclass_field(default=None, kw_only=True) """ It is an optional parameter that will be received from third party server, but it's only required when using either @@ -2850,21 +3737,21 @@ class BulkSignAuthentication: 'AUTHENTICATION_LINKED_IN' 'AUTHENTICATION_SALES_FORCE' as a parameter value under 'mechanism' """ - user_identifier: Optional[str] = None + user_identifier: Optional[str] = dataclass_field(default=None, kw_only=True) """ It is an optional parameter, but it's only required when using 'AUTHENTICATION_ACTIVE_DIRECTORY' or 'AUTHENTICATION_SAML' as a parameter value under 'mechanism' """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ It is an optional parameter, but it's only required when using 'AUTHENTICATION_SALES_FORCE' or 'AUTHENTICATION_IDFY' as a parameter value under 'mechanism'. For 'AUTHENTICATION_IDFY' it's requestId """ - code_verifier: Optional[str] = None + code_verifier: Optional[str] = dataclass_field(default=None, kw_only=True) """Code Verifier if PKCE is enabled for the client.""" - nonce: Optional[str] = None + nonce: Optional[str] = dataclass_field(default=None, kw_only=True) """Nonce value if it is enabled for the client.""" @@ -2877,14 +3764,19 @@ class BulkSignPackagesStatus: Definition: BulkSignPackagesStatus """ - id: Optional[int] = None - name: Optional[str] = None - status: Optional[str] = None - action: Optional[str] = None + id: int + name: Optional[str] = dataclass_field(default=None, kw_only=True) + status: Optional[str] = dataclass_field(default=None, kw_only=True) + action: Optional[str] = dataclass_field(default=None, kw_only=True) """Required action key if any""" - error: Optional[str] = None - percentage: Optional[int] = None - documents: Optional[List[BulkSignActionDocumentModel]] = None + error: Optional[str] = dataclass_field(default=None, kw_only=True) + percentage: int + documents: Optional[ + List[BulkSignActionDocumentModel | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Documents in the current package""" @@ -2894,8 +3786,13 @@ class BulkSignActionDocumentModel: Definition: BulkSignActionDocumentModel """ - id: Optional[int] = None - fields: Optional[List[BulkSignActionFieldModel]] = None + id: int + fields: Optional[ + List[BulkSignActionFieldModel | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -2904,9 +3801,9 @@ class BulkSignActionFieldModel: Definition: BulkSignActionFieldModel """ - name: Optional[str] = None - hash: Optional[str] = None - hashing_algo: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + hash: Optional[str] = dataclass_field(default=None, kw_only=True) + hashing_algo: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -2915,7 +3812,7 @@ class BulkSignStatusRequest: Definition: BulkSignStatusRequest """ - transaction_id: Optional[str] = None + transaction_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identification number of the bulk signing transaction""" @@ -2925,9 +3822,9 @@ class SignDocumentRequest: Definition: SignDocumentRequest """ - field_name: Optional[str] = None + field_name: str """Unique identifier of the signature field in the document.""" - hand_signature_image: Optional[str] = None + hand_signature_image: Optional[str] = dataclass_field(default=None, kw_only=True) """ Base64 encoded string image of the visible signature appearance, which is placed onto the document. Note this can be retrieved from the user's @@ -2936,45 +3833,50 @@ class SignDocumentRequest: is binary, so the business application must then Base64 encode it before submitting in this API call.) """ - hand_signature_method: Optional[HandSignature] = None - signing_reason: Optional[str] = None + hand_signature_method: Optional[HandSignature] = dataclass_field(default=None, kw_only=True) + signing_reason: Optional[str] = dataclass_field(default=None, kw_only=True) """ Reason of signing provided by the recipient. Note: Commitment type indication for XML documents """ - signing_location: Optional[str] = None + signing_location: Optional[str] = dataclass_field(default=None, kw_only=True) """Locale of the signer provided by the recipient.""" - contact_information: Optional[str] = None + contact_information: Optional[str] = dataclass_field(default=None, kw_only=True) """Contact information of the signer provided by the recipient.""" - user_name: Optional[str] = None + user_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the signer provided by the recipient. Note this applies to in-person signing operations only. """ - user_password: Optional[str] = None + user_password: Optional[str] = dataclass_field(default=None, kw_only=True) """Password provided by the user subject to user's signature settings.""" - appearance_design: Optional[str] = None + appearance_design: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the signature appearance provided by user for signing. In case no appearance name is provided then default selected appearance would be used. Possible values are \"COMPANY_LOGO\",\"DETAILED_SIGNATURE\",\"HAND_SIGNATURE\" """ - signing_capacity: Optional[str] = None + signing_capacity: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of certification profile/signing capacity using which the document is to be signed. If not provided the default capacity will be used to sign. Provided name must be exactly same as of the actual profile due to case sensitivity. """ - skip_verification: Optional[bool] = None + skip_verification: bool """ No signature verification returns in response body when it is set as true. Default value for this parameter set to false. """ - signing_server: Optional[str] = None + signing_server: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of signing server using which the document is to be signed.""" - authentication: Optional[Authentication] = None + authentication: Optional[ + Authentication | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -2983,19 +3885,19 @@ class Authentication: Definition: Authentication """ - mechanism: Optional[str] = None + mechanism: Optional[str] = dataclass_field(default=None, kw_only=True) """ Mechanism of the authentication. Possible values for mechanism are: AUTHENTICATION_PASSWORD, AUTHENTICATION_ACTIVE_DIRECTORY, AUTHENTICATION_AZURE_ACTIVE_DIRECTORY, AUTHENTICATION_OFFICE_365, AUTHENTICATION_OAUTH2, AUTHENTICATION_OIDC """ - password: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) """ It is an optional parameter, but it's only required when using 'AUTHENTICATION_PASSWORD' as a parameter value under 'mechanism' """ - token: Optional[str] = None + token: Optional[str] = dataclass_field(default=None, kw_only=True) """ It is an optional parameter that will be received from third party server, but it's only required when using either @@ -3004,21 +3906,21 @@ class Authentication: 'AUTHENTICATION_LINKED_IN' 'AUTHENTICATION_SALES_FORCE' as a parameter value under 'mechanism' """ - user_identifier: Optional[str] = None + user_identifier: Optional[str] = dataclass_field(default=None, kw_only=True) """ It is an optional parameter, but it's only required when using 'AUTHENTICATION_ACTIVE_DIRECTORY' or 'AUTHENTICATION_SAML' as a parameter value under 'mechanism' """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ It is an optional parameter, but it's only required when using 'AUTHENTICATION_SALES_FORCE' or 'AUTHENTICATION_IDFY' as a parameter value under 'mechanism'. For 'AUTHENTICATION_IDFY' it's requestId """ - code_verifier: Optional[str] = None + code_verifier: Optional[str] = dataclass_field(default=None, kw_only=True) """Code Verifier if PKCE is enabled for the client.""" - nonce: Optional[str] = None + nonce: Optional[str] = dataclass_field(default=None, kw_only=True) """Nonce value if it is enabled for the client.""" @@ -3028,29 +3930,29 @@ class AutoPlaceFieldRequest: Definition: AutoPlaceFieldRequest """ - search_text: Optional[str] = None + search_text: Optional[str] = dataclass_field(default=None, kw_only=True) """Word that needs to be searched in the document.""" - order: Optional[int] = None + order: int """ Order of the user to which the fields will be assigned automatically. Workflow in SigningHub orders recipients. This list begins with \"1\" for the first designated signer. """ - placement: Optional[str] = None + placement: Optional[str] = dataclass_field(default=None, kw_only=True) """ If the text is found, fields are to be placed in the document. Placement of the field can be mentioned in this attribute. Possible values of placement of a field are LEFT, RIGHT, TOP, BOTTOM. If no value is provided the default value will be LEFT. """ - field_type: Optional[str] = None + field_type: Optional[str] = dataclass_field(default=None, kw_only=True) """ Type of field to be created in the document. Possible values are \"SIGNATURE\", \"IN_PERSON_SIGNATURE\", \"INITIALS\", \"TEXT\", \"NUMBER\" ,\"NAME\", \"EMAIL\", \"COMPANY\", \"JOBTITLE\", \"RADIOBOX\", \"CHECKBOX\", \"DATE\", \"ATTACHMENT\" """ - level_of_assurance: Optional[List[str]] = None + level_of_assurance: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ Level Of Assurance to be updated. Possible Values are \"ELECTRONIC_SIGNATURE\", \"ELECTRONIC_SEAL\", @@ -3058,15 +3960,20 @@ class AutoPlaceFieldRequest: \"ADVANCED_ELECTRONIC_SIGNATURE\", \"HIGH_TRUST_ADVANCED\", \"QUALIFIED_ELECTRONIC_SIGNATURE\" """ - dimensions: Optional[FieldDimension] = None - placeholder: Optional[str] = None + dimensions: Optional[ + FieldDimension | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + placeholder: Optional[str] = dataclass_field(default=None, kw_only=True) """Provide note in the case of Mandatory Attachment""" - radio_group_name: Optional[str] = None + radio_group_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ The group name required only when adding a Radio Box type field to group multiple Radio boxes together. """ - format: Optional[str] = None + format: Optional[str] = dataclass_field(default=None, kw_only=True) """

Text format of the field. Used for the date type field only. Possible values are

  • m/d
  • m/d/yy
  • m/d/yyyy
  • @@ -3076,20 +3983,25 @@ class AutoPlaceFieldRequest:
  • mmm-yyyy
  • mmmm-yy
  • mmmm-yyyy
  • mmmm d, yyyy
  • dd/mm/yy
  • ddmmmyyyy
""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Value that user want to show in the field.""" - max_length: Optional[int] = None + max_length: int """ Maximum length of the value allowed in the field. Must between 1 - 9999 """ - validation_rule: Optional[str] = None + validation_rule: Optional[str] = dataclass_field(default=None, kw_only=True) """ One or more rules for validation of the fields possible values are \"MANDATORY\" or \"OPTIONAL\". """ - validation: Optional[FieldValidationValue] = None - font: Optional[Font] = None - multiline: Optional[bool] = None + validation: Optional[ + FieldValidationValue | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + font: Optional[Font | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + multiline: bool """ This belongs to Text Area field type and If set to true, text area field would be created with multi line option. @@ -3102,17 +4014,17 @@ class Font: Definition: Font """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the font selected for the text field. Possible values are \"COURIER\", \"HELVETICA\". """ - size: Optional[str] = None + size: Optional[str] = dataclass_field(default=None, kw_only=True) """ Size of the font selected for the text field. Possible values are 8, 10, 12, 14, 16, 18, 20 """ - embedded_size: Optional[str] = None + embedded_size: Optional[str] = dataclass_field(default=None, kw_only=True) """Size of the font in the original PDF document.""" @@ -3122,22 +4034,47 @@ class FormFillingRequest: Definition: FormFillingRequest """ - auto_save: Optional[bool] = None + auto_save: bool """ Default value is false. True, if the form fields are being saved without user intervention e.g., while closing the document or pressing back. For Signing, Initials, In-persons, Reviewing, Submit actions the value is false. """ - text: Optional[List[TextFormFillingRequest]] = None + text: Optional[ + List[TextFormFillingRequest | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """It has the list of textboxes data to save""" - radio: Optional[List[RadioFormFillingRequest]] = None + radio: Optional[ + List[RadioFormFillingRequest | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """It has the list of radios value to save""" - checkbox: Optional[List[CheckBoxFormFillingRequest]] = None + checkbox: Optional[ + List[CheckBoxFormFillingRequest | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """It has the list of checkboxes value to save""" - dropdown: Optional[List[DropDownFormFillingRequest]] = None + dropdown: Optional[ + List[DropDownFormFillingRequest | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """It has the list of dropdowns value to save""" - listbox: Optional[List[ListBoxFormFillingRequest]] = None + listbox: Optional[ + List[ListBoxFormFillingRequest | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """It has the list of listboxes value to save""" @@ -3147,9 +4084,9 @@ class TextFormFillingRequest: Definition: TextFormFillingRequest """ - field_name: Optional[str] = None + field_name: str """Unique identifier of the field in the document.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Value of the field to be saved in the document.""" @@ -3159,11 +4096,11 @@ class RadioFormFillingRequest: Definition: RadioFormFillingRequest """ - field_name: Optional[str] = None + field_name: str """Unique identifier of the field in the document.""" - radio_group_name: Optional[str] = None + radio_group_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Group name to which the radio button belongs.""" - value: Optional[bool] = None + value: bool """Value of the field to be saved in the document.""" @@ -3173,9 +4110,9 @@ class CheckBoxFormFillingRequest: Definition: CheckBoxFormFillingRequest """ - field_name: Optional[str] = None + field_name: str """Unique identifier of the field in the document.""" - value: Optional[bool] = None + value: bool """Value of the field to be saved in the document.""" @@ -3185,9 +4122,9 @@ class DropDownFormFillingRequest: Definition: DropDownFormFillingRequest """ - field_name: Optional[str] = None + field_name: str """Unique identifier of the field in the document.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Value of the field to be saved in the document.""" @@ -3197,9 +4134,9 @@ class ListBoxFormFillingRequest: Definition: ListBoxFormFillingRequest """ - field_name: Optional[str] = None + field_name: str """Unique identifier of the field in the document.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Value of the field to be saved in the document.""" @@ -3209,16 +4146,16 @@ class InitialFieldRequest: Definition: InitialFieldRequest """ - order: Optional[int] = None + order: int """The order of the user in workflow for which the field is being added.""" - page_no: Optional[int] = None + page_no: int """Page number on which the field is to be created.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the field that is to be added. If not provided, system will assign an unique auto generated name to the field. """ - dimensions: Optional[FieldDimension] = None + dimensions: FieldDimension | Mapping[str, Any] @dataclass @@ -3227,12 +4164,12 @@ class InitialFillingRequest: Definition: InitialFillingRequest """ - field_name: Optional[str] = None + field_name: str """Unique identifier of the field in the document.""" - image: Optional[str] = None + image: str """Base64 image used for the filling of the initials.""" - method: Optional[HandSignature] = None - apply_to_all: Optional[bool] = None + method: Optional[HandSignature] = dataclass_field(default=None, kw_only=True) + apply_to_all: bool """True if all initials are to be filled.""" @@ -3242,13 +4179,13 @@ class UpdateInitialFieldRequest: Definition: UpdateInitialFieldRequest """ - field_name: Optional[str] = None + field_name: str """Current name of the field, that is to be updated.""" - renamed_as: Optional[str] = None + renamed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """Updated name of the field if renaming is intended.""" - page_no: Optional[int] = None + page_no: int """Page number on which the field is to be created.""" - dimensions: Optional[FieldDimension] = None + dimensions: FieldDimension | Mapping[str, Any] @dataclass @@ -3257,33 +4194,38 @@ class InPersonFieldRequest: Definition: InPersonFieldRequest """ - order: Optional[int] = None + order: int """The order of the user in workflow for which the field is being added.""" - page_no: Optional[int] = None + page_no: int """Page number on which the field is to be created.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the field that is to be added. If not provided, system will assign an unique auto generated name to the field. """ - placeholder: Optional[str] = None + placeholder: str """ String identifier for the inperson field, it can be Customer, Jack, CEO etc. """ - dimensions: Optional[FieldDimension] = None - display: Optional[str] = None + dimensions: FieldDimension | Mapping[str, Any] + display: Optional[str] = dataclass_field(default=None, kw_only=True) """ Visibility of the field that is to be added, possible values are \"VISIBLE\" and \"INVISIBLE\" """ - level_of_assurance: Optional[List[str]] = None + level_of_assurance: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ Level Of Assurance to be updated. Possible Values are \"ELECTRONIC_SEAL\", \"ADVANCED_ELECTRONIC_SEAL\", \"QUALIFIED_ELECTRONIC_SEAL\", \"ELECTRONIC_SIGNATURE\" """ - authentication_signing: Optional[SignatureFieldAuthentication] = None + authentication_signing: Optional[ + SignatureFieldAuthentication | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -3292,30 +4234,40 @@ class UpdateInPersonFieldRequest: Definition: UpdateInPersonFieldRequest """ - field_name: Optional[str] = None + field_name: str """Current name of the field, that is to be updated.""" - renamed_as: Optional[str] = None + renamed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """updated name of the field, if renaming is intended.""" - page_no: Optional[int] = None + page_no: int """Page number on which the field is to be created.""" - placeholder: Optional[str] = None + placeholder: Optional[str] = dataclass_field(default=None, kw_only=True) """ String identifier for the in-person field, it can be Customer, Jack, CEO etc. """ - dimensions: Optional[FieldDimension] = None - display: Optional[str] = None + dimensions: Optional[ + FieldDimension | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + display: Optional[str] = dataclass_field(default=None, kw_only=True) """ Visibility of the field that is to be updated, possible values are \"VISIBLE\" and \"INVISIBLE\" """ - level_of_assurance: Optional[List[str]] = None + level_of_assurance: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ Level Of Assurance to be updated. Possible Values are \"ELECTRONIC_SEAL\", \"ADVANCED_ELECTRONIC_SEAL\", \"QUALIFIED_ELECTRONIC_SEAL\", \"ELECTRONIC_SIGNATURE\" """ - authentication_signing: Optional[SignatureFieldAuthentication] = None + authentication_signing: Optional[ + SignatureFieldAuthentication | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -3324,16 +4276,16 @@ class DigitalSignatureFieldRequest: Definition: DigitalSignatureFieldRequest """ - order: Optional[int] = None + order: int """Order of the recipient for which the field is being created.""" - page_no: Optional[int] = None + page_no: int """Page number at which the field is about to be created.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the field that is to be added. If not provided, system will assign an unique auto generated name to the field. """ - level_of_assurance: Optional[List[str]] = None + level_of_assurance: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ Level Of Assurance to be added. Possible Values are \"ELECTRONIC_SIGNATURE\", \"ELECTRONIC_SEAL\", @@ -3341,13 +4293,23 @@ class DigitalSignatureFieldRequest: \"ADVANCED_ELECTRONIC_SIGNATURE\", \"HIGH_TRUST_ADVANCED\", \"QUALIFIED_ELECTRONIC_SIGNATURE\" """ - dimensions: Optional[FieldDimension] = None - display: Optional[str] = None + dimensions: Optional[ + FieldDimension | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + display: Optional[str] = dataclass_field(default=None, kw_only=True) """ Visibility of the field that is to be added, possible values are \"VISIBLE\" and \"INVISIBLE\" """ - authentication_signing: Optional[SignatureFieldAuthentication] = None + authentication_signing: Optional[ + SignatureFieldAuthentication | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -3356,9 +4318,9 @@ class UpdateDigitalSignatureFieldRequest: Definition: UpdateDigitalSignatureFieldRequest """ - field_name: Optional[str] = None + field_name: str """Current name of the field, which is to be updated.""" - level_of_assurance: Optional[List[str]] = None + level_of_assurance: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ Level Of Assurance to be updated. Possible Values are \"ELECTRONIC_SIGNATURE\", \"ELECTRONIC_SEAL\", @@ -3366,17 +4328,27 @@ class UpdateDigitalSignatureFieldRequest: \"ADVANCED_ELECTRONIC_SIGNATURE\", \"HIGH_TRUST_ADVANCED\", \"QUALIFIED_ELECTRONIC_SIGNATURE\" """ - renamed_as: Optional[str] = None + renamed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """Updated name of the field if renaming of the field is intended.""" - page_no: Optional[int] = None + page_no: int """Page number on which the field is to be created.""" - dimensions: Optional[FieldDimension] = None - display: Optional[str] = None + dimensions: Optional[ + FieldDimension | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + display: Optional[str] = dataclass_field(default=None, kw_only=True) """ Visibility of the field that is to be updated, possible values are \"VISIBLE\" and \"INVISIBLE\" """ - authentication_signing: Optional[SignatureFieldAuthentication] = None + authentication_signing: Optional[ + SignatureFieldAuthentication | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -3385,19 +4357,19 @@ class CheckBoxFieldRequest: Definition: CheckBoxFieldRequest """ - order: Optional[int] = None + order: int """The order of the user in workflow for which the field is being added.""" - page_no: Optional[int] = None + page_no: int """Page number on which the field is to be created.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the provided field that is to be added. If not provided, system will assign an unique auto generated name to the field. """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Value of the field. Possible values are \"true\" or \"false\"""" - dimensions: Optional[FieldDimension] = None - validation_rule: Optional[str] = None + dimensions: FieldDimension | Mapping[str, Any] + validation_rule: Optional[str] = dataclass_field(default=None, kw_only=True) """ One or more rules for validation of the fields possible values are \"MANDATORY\" or \"OPTIONAL\". @@ -3410,16 +4382,16 @@ class UpdateCheckBoxFieldRequest: Definition: UpdateCheckBoxFieldRequest """ - field_name: Optional[str] = None + field_name: str """Current name of the field, that is to be updated.""" - renamed_as: Optional[str] = None + renamed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """Updated name of the field if renaming is intended.""" - page_no: Optional[int] = None + page_no: int """Page number on which the field is to be created.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Value of the field. Possible values are \"true\" or \"false\"""" - dimensions: Optional[FieldDimension] = None - validation_rule: Optional[str] = None + dimensions: FieldDimension | Mapping[str, Any] + validation_rule: Optional[str] = dataclass_field(default=None, kw_only=True) """ One or more rules for validation of the fields possible values are \"MANDATORY\" or \"OPTIONAL\". @@ -3432,22 +4404,19 @@ class TextBoxFieldRequest: Definition: TextBoxFieldRequest """ - order: Optional[int] = None + order: int """The order of the user in workflow for which the field is being added.""" - page_no: Optional[int] = None + page_no: int """Page number on which the field is to be created.""" - type_: Optional[TextboxType] = field( - default=None, - metadata={"wire_name": "type"}, - ) - value: Optional[str] = None + type_: TextboxType = dataclass_field(metadata={"wire_name": "type"}) + value: Optional[str] = dataclass_field(default=None, kw_only=True) """ Value of the field. For type = DATE, the value is expected to follow ISO 8601 format.Following the format YYYY-MM-DD hh:mm:ss +00. As the values are for date fields client applications can send YYYY-MM-DD and ignore hh:mm:ss +00. If value is not in proper format an error will be returned. """ - placeholder: Optional[str] = None + placeholder: Optional[str] = dataclass_field(default=None, kw_only=True) """ Placeholder text for the text field. For name, email, company, job title and date, placeholder value can be \"NAME\", \"EMAIL\", \"COMPANY\", @@ -3456,11 +4425,11 @@ class TextBoxFieldRequest: own placeholder texts. These placeholders appear in the text fields while viewing the document in viewer. """ - max_length: Optional[int] = None + max_length: int """ Maximum length of the value allowed in the field. Must between 1 - 9999 """ - format: Optional[str] = None + format: Optional[str] = dataclass_field(default=None, kw_only=True) """

Text format of the field. Used for the date type field only. Possible values are

  • m/d
  • m/d/yy
  • m/d/yyyy
  • @@ -3470,17 +4439,22 @@ class TextBoxFieldRequest:
  • mmm-yyyy
  • mmmm-yy
  • mmmm-yyyy
  • mmmm d, yyyy
  • dd/mm/yy
  • ddmmmyyyy
""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the field that is to be added. If not provided, system will assign an unique auto generated name to the field. """ - field_type: Optional[FieldType] = None - validation_rule: Optional[ValidationRule] = None - validation: Optional[FieldValidationValue] = None - font: Optional[Font] = None - dimensions: Optional[FieldDimension] = None - multiline: Optional[bool] = None + field_type: FieldType + validation_rule: ValidationRule + validation: Optional[ + FieldValidationValue | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + font: Font | Mapping[str, Any] + dimensions: FieldDimension | Mapping[str, Any] + multiline: bool """If set to true, text area field would be created""" @@ -3490,33 +4464,38 @@ class UpdateTextBoxFieldRequest: Definition: UpdateTextBoxFieldRequest """ - field_name: Optional[str] = None + field_name: str """Current name of the field, that is to be updated.""" - renamed_as: Optional[str] = None + renamed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """Updated name of the field if renaming is intended.""" - page_no: Optional[int] = None + page_no: int """Page number on which the field is to be created.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """ Value of the field. For type = DATE, the value is expected to follow ISO 8601 format.Following the format YYYY-MM-DD hh:mm:ss +00. As the values are for date fields client applications can send YYYY-MM-DD and ignore hh:mm:ss +00. If value is not in proper format an error will be returned. """ - max_length: Optional[int] = None + max_length: int """ Maximum length of the value allowed in the field. Must between 1 - 9999 """ - field_type: Optional[FieldType] = None - validation_rule: Optional[ValidationRule] = None - font: Optional[Font] = None - dimensions: Optional[FieldDimension] = None - placeholder: Optional[str] = None + field_type: FieldType + validation_rule: ValidationRule + font: Optional[Font | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + dimensions: Optional[ + FieldDimension | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + placeholder: Optional[str] = dataclass_field(default=None, kw_only=True) """ Developers can provide a their own placeholder texts. These placeholders appear in the text fields while viewing the document in viewer. """ - format: Optional[str] = None + format: Optional[str] = dataclass_field(default=None, kw_only=True) """

Text format of the field. Used for the date type field only. Possible values are

  • m/d
  • m/d/yy
  • m/d/yyyy
  • @@ -3526,7 +4505,12 @@ class UpdateTextBoxFieldRequest:
  • mmm-yyyy
  • mmmm-yy
  • mmmm-yyyy
  • mmmm d, yyyy
  • dd/mm/yy
  • ddmmmyyyy
""" - validation: Optional[FieldValidationValue] = None + validation: Optional[ + FieldValidationValue | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -3535,20 +4519,20 @@ class RadioBoxFieldRequest: Definition: RadioBoxFieldRequest """ - order: Optional[int] = None + order: int """The order of the user in workflow for which the field is being added.""" - page_no: Optional[int] = None + page_no: int """Page number on which the field is to be created.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the provided field that is to be added. If not provided, system will assign an unique auto generated name to the field. """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Value of the field. Possible values are \"true\" or \"false\"""" - validation_rule: Optional[ValidationRule] = None - radio_group_name: Optional[str] = None - dimensions: Optional[FieldDimension] = None + validation_rule: ValidationRule + radio_group_name: str + dimensions: FieldDimension | Mapping[str, Any] @dataclass @@ -3557,18 +4541,18 @@ class UpdateRadioBoxFieldRequest: Definition: UpdateRadioBoxFieldRequest """ - field_name: Optional[str] = None + field_name: str """Current name of the field, that is to be updated.""" - renamed_as: Optional[str] = None + renamed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """Updated name of the field if renaming is intended.""" - page_no: Optional[int] = None + page_no: int """Page number on which the field is to be created.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Value of the field. Possible values are \"true\" or \"false\"""" - validation_rule: Optional[ValidationRule] = None - radio_group_name: Optional[str] = None + validation_rule: ValidationRule + radio_group_name: str """The group name to which the field belongs.""" - dimensions: Optional[FieldDimension] = None + dimensions: FieldDimension | Mapping[str, Any] ContactSortBy = Literal["CREATEDON", "NAME", "EMAIL"] @@ -3580,9 +4564,9 @@ class WorkSpaceMembers: Definition: WorkSpaceMembers """ - name: Optional[str] = None + name: str """Name of work space member""" - email: Optional[str] = None + email: str """Email Address of work space member""" @@ -3592,9 +4576,9 @@ class WorkSpaceOwner: Definition: WorkSpaceOwner """ - name: Optional[str] = None + name: str """Name of work space owner""" - email: Optional[str] = None + email: str """Email Address of work space owner""" @@ -3604,13 +4588,13 @@ class UploadDocumentLibraryCertifyResponse: Definition: UploadDocumentLibraryCertifyResponse """ - enabled: Optional[bool] = None + enabled: bool """True if certify signature is enabled for the document.""" - allowed_permissions: Optional[List[str]] = None + allowed_permissions: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Set of allowed certify permission levels for the document.""" - default_permission: Optional[str] = None + default_permission: Optional[str] = dataclass_field(default=None, kw_only=True) """Selected permission level for the certify signature settings.""" - permission: Optional[str] = None + permission: Optional[str] = dataclass_field(default=None, kw_only=True) """ It is the certify permissions to be applied on the PDF document when the first signature is created. The possible values are \"NO_CHANGES_ALLOWED\", @@ -3624,9 +4608,9 @@ class UploadDocumentLibraryTemplateResponse: Definition: UploadDocumentLibraryTemplateResponse """ - template_name: Optional[str] = None + template_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the template applied on the document.""" - read_only: Optional[bool] = None + read_only: bool """ True if the applied template is read only. User will not be able to make any changes if a read only template is applied. @@ -3639,12 +4623,12 @@ class WorkflowPermissionsUpdateRequest: Definition: WorkflowPermissionsUpdateRequest """ - apply_to_all: Optional[bool] = None + apply_to_all: bool """ True, if the permissions are to be applied on all the recipients in the workflow. """ - permissions: Optional[WorkflowPermission] = None + permissions: WorkflowPermission | Mapping[str, Any] @dataclass @@ -3653,23 +4637,33 @@ class WorkflowPermission: Definition: WorkflowPermission """ - print: Optional[bool] = None + print: Optional[bool] = dataclass_field(default=None, kw_only=True) """It defines whether recipient is allowed to print the document.""" - download: Optional[bool] = None + download: Optional[bool] = dataclass_field(default=None, kw_only=True) """It defines whether recipient is allowed to download the document.""" - add_text: Optional[bool] = None + add_text: Optional[bool] = dataclass_field(default=None, kw_only=True) """ It defines whether recipient is allowed to add text fields in the document. """ - change_recipients: Optional[bool] = None + change_recipients: Optional[bool] = dataclass_field(default=None, kw_only=True) """It allows the user to change any recipient who has not signed yet.""" - add_attachment: Optional[bool] = None + add_attachment: Optional[bool] = dataclass_field(default=None, kw_only=True) """ It defines whether recipient is allowed to add attachments in the PDF document. """ - legal_notice: Optional[PermissionLegalNotice] = None - attachment: Optional[AttachmentPermissionRequest] = None + legal_notice: Optional[ + PermissionLegalNotice | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + attachment: Optional[ + AttachmentPermissionRequest | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -3678,7 +4672,7 @@ class AttachmentPermissionRequest: Definition: AttachmentPermissionRequest """ - enabled: Optional[bool] = None + enabled: bool """Enabled""" @@ -3688,9 +4682,9 @@ class PermissionLegalNotice: Definition: PermissionLegalNotice """ - enabled: Optional[bool] = None + enabled: bool """True, if legal notice is enabled.""" - legal_notice_name: Optional[str] = None + legal_notice_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the legal notice selected for the recipient.""" @@ -3700,21 +4694,26 @@ class DocumentLogsActions: Definition: DocumentLogsActions """ - log_id: Optional[int] = None + log_id: int """ID of an action performed on the document.""" - date_time: Optional[str] = None + date_time: Optional[str] = dataclass_field(default=None, kw_only=True) """Date and time when the action was performed.""" - action_type: Optional[str] = None - user_email: Optional[str] = None + action_type: Optional[str] = dataclass_field(default=None, kw_only=True) + user_email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email of the user who performed the action.""" - user_name: Optional[str] = None + user_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the user who performed the action.""" - enterprise_name: Optional[str] = None + enterprise_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ The name of Enterprise to which the user belongs. If the user doesn't belong to an enterprise, then this element is not present. """ - information: Optional[DocumentLogsActionsInformation] = None + information: Optional[ + DocumentLogsActionsInformation | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -3723,12 +4722,16 @@ class DocumentLogsActionsInformation: Definition: DocumentLogsActionsInformation """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """ The type of extra information about the action e.g. \"SIGNING_METHOD\" which means what signing method user used to sign the document. """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """ The value of the extra information about the action e.g. \"LOCAL\" which means user signed the document using locally held credentials. @@ -3741,34 +4744,34 @@ class WorkflowUserUpdateRequest: Definition: WorkflowUserUpdateRequest """ - user_email: Optional[str] = None + user_email: Optional[str] = dataclass_field(default=None, kw_only=True) """ The email address of the new user to be updated in workflow. If no value is provided, old value will be retained. """ - user_name: Optional[str] = None + user_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the recipient to be updated. If no value is provided, old value will be retained. """ - email_notification: Optional[bool] = None + email_notification: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Setting its value to \"true\" sends an email notification to the user when its turn arrives in workflow. Setting its value to \"false\" does not send the email notification to the user on its turn. If no value is provided, old value will be retained. """ - mobile_number: Optional[str] = None + mobile_number: Optional[str] = dataclass_field(default=None, kw_only=True) """Mobile number. If no value is provided, old value will be retained.""" - role: Optional[WorkflowCollaboratorRole] = None - signing_order: Optional[int] = None + role: WorkflowCollaboratorRole + signing_order: Optional[int] = dataclass_field(default=None, kw_only=True) """ Order in which the workflow will be signed by the recipients. This signing order is important when workflow type is set to \"CUSTOM\". """ - email_language_code: Optional[str] = None + email_language_code: Optional[str] = dataclass_field(default=None, kw_only=True) """email language code""" - delivery_method: Optional[DeliveryMethod] = None + delivery_method: DeliveryMethod WorkflowCollaboratorRole = Literal[ @@ -3786,7 +4789,7 @@ class WorkflowUserReorderRequest: Definition: WorkflowUserReorderRequest """ - order: Optional[int] = None + order: int """The order of the recipient which is to be updated.""" @@ -3796,21 +4799,26 @@ class UpdateReminderRequest: Definition: UpdateReminderRequest """ - apply_to_all: Optional[bool] = None + apply_to_all: bool """ True, if reminder settings are to be applied on all the recipients in the workflow. """ - enabled: Optional[bool] = None + enabled: bool """True, if reminder settings are to be enabled.""" - frequency: Optional[str] = None + frequency: Optional[str] = dataclass_field(default=None, kw_only=True) """Reminder Frequency. Possible Values are DAYS | HOURS. """ - remind_after: Optional[int] = None + remind_after: int """ Required, in case of enabled property will true. The number of days after which the first reminder would be sent to workflow user. """ - repeat: Optional[RepeatRequest] = None + repeat: Optional[ + RepeatRequest | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -3819,16 +4827,16 @@ class RepeatRequest: Definition: RepeatRequest """ - enabled: Optional[bool] = None + enabled: bool """True, if subsequent reminders are enabled.""" - frequency: Optional[str] = None + frequency: Optional[str] = dataclass_field(default=None, kw_only=True) """Repeat Reminder Frequency. Possible Values are DAYS | HOURS. """ - keep_reminding_after: Optional[int] = None + keep_reminding_after: int """ Required, in case of enabled property will true. The number of days after which the subsequent reminders would be sent to workflow user. """ - total_reminders: Optional[int] = None + total_reminders: int """ Required, in case of enabled property will true. The number of subsequent reminders would be sent to workflow user. @@ -3841,17 +4849,17 @@ class WorflowGroupRequest: Definition: WorflowGroupRequest """ - group_name: Optional[str] = None + group_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the new group to be added in workflow.""" - email_notification: Optional[bool] = None + email_notification: bool """ Setting its value to \"true\" sends an email notification to the user when its turn arrives in workflow. Setting its value to \"false\" does not send the email notification to the user on its turn. If no value is provided, default value of \"true\" will be set. """ - role: Optional[CollaboratorRole] = None - signing_order: Optional[int] = None + role: CollaboratorRole + signing_order: Optional[int] = dataclass_field(default=None, kw_only=True) """ Order in which the workflow will be signed by the recipients. This signing order is important when workflow type is set to \"CUSTOM\". @@ -3864,16 +4872,16 @@ class PlaceholderRequest: Definition: PlaceholderRequest """ - placeholder: Optional[str] = None + placeholder: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the new placeholder to be added in workflow.""" - email_notification: Optional[bool] = None + email_notification: bool """ Setting its value to \"true\" sends an email notification to the user when its turn arrives in workflow. Setting its value to \"false\" does not send the email notification to the user on its turn. """ - role: Optional[CollaboratorRole] = None - signing_order: Optional[int] = None + role: CollaboratorRole + signing_order: Optional[int] = dataclass_field(default=None, kw_only=True) """ Order in which the workflow will be signed by the recipients. This signing order is important when workflow type is set to \"CUSTOM\". @@ -3886,20 +4894,20 @@ class WorkflowPlaceholderUpdateRequest: Definition: WorkflowPlaceholderUpdateRequest """ - placeholder: Optional[str] = None + placeholder: Optional[str] = dataclass_field(default=None, kw_only=True) """ The name of the new placeholder to be added in workflow. If no value is provided, old value will be retained. """ - email_notification: Optional[bool] = None + email_notification: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Setting its value to \"true\" sends an email notification to the user when its turn arrives in workflow. Setting its value to \"false\" does not send the email notification to the user on its turn. If no value is provided, old value will be retained. """ - role: Optional[WorkflowCollaboratorRole] = None - signing_order: Optional[int] = None + role: WorkflowCollaboratorRole + signing_order: Optional[int] = dataclass_field(default=None, kw_only=True) """ Order in which the workflow will be signed by the recipients. This signing order is important when workflow type is set to \"CUSTOM\". @@ -3912,9 +4920,14 @@ class UpdateWorkSpaceRequest: Definition: UpdateWorkSpaceRequest """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of shared space""" - members: Optional[List[WorkSpaceMembers]] = None + members: Optional[ + List[WorkSpaceMembers | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Members of shared space""" @@ -3924,7 +4937,7 @@ class MoveToRequest: Definition: MoveToRequest """ - folder_name: Optional[str] = None + folder_name: str """Target folder name in which package need to move""" @@ -3934,50 +4947,69 @@ class DigitalSignatureFieldResponse: Definition: DigitalSignatureFieldResponse """ - order: Optional[int] = None + order: int """ Order of the recipient to whom this field is assigned. If the field is not assigned to anyone, value will be null. """ - display_order: Optional[int] = None + display_order: int """Display order according to the SigningHub viewer.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the field.""" - page_no: Optional[int] = None + page_no: int """Page number of the document on which the field exists.""" - embedded: Optional[bool] = None + embedded: bool """True, if field is part of the PDF document.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """ If field is assigned or not, possible values are ASSIGNED, UN_ASSIGNED, SIGNED, LOGGED_IN_USER, HIDDEN and PLACEHOLDER. """ - process_status: Optional[str] = None + process_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Whether the field is processed or not. Possible values are UN_PROCESSED, PROCESSED. """ - processed_on: Optional[str] = None + processed_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date time on which the document is processed.""" - processed_as: Optional[str] = None + processed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """ User who processed the field as COLLABORATOR, DELEGATEE, GROUP_MEMBER or OWNER. """ - created_on: Optional[str] = None + created_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date time on which the field is added""" - processed_by: Optional[str] = None + processed_by: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the user who processed the field.""" - dimensions: Optional[FieldDimenssionResponse] = None - verification: Optional[VerificationResponse] = None - nid: Optional[str] = None - display: Optional[str] = None + dimensions: Optional[ + FieldDimenssionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + verification: Optional[ + VerificationResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + nid: Optional[str] = dataclass_field(default=None, kw_only=True) + display: Optional[str] = dataclass_field(default=None, kw_only=True) """ Returns the visibility value of the digital signature field, possible values are \"VISIBLE\" and \"INVISIBLE\". """ - level_of_assurance: Optional[List[str]] = None - authentication: Optional[FieldAuthentication] = None + level_of_assurance: Optional[List[str]] = dataclass_field(default=None, kw_only=True) + authentication: Optional[ + FieldAuthentication | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -3986,8 +5018,8 @@ class FieldDimenssionResponse: Definition: FieldDimenssionResponse """ - field: Optional[FieldResponse] = None - page: Optional[PageResponse] = None + field: Optional[FieldResponse | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + page: Optional[PageResponse | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -3996,13 +5028,13 @@ class FieldResponse: Definition: FieldResponse """ - x: Optional[float] = None + x: float """Left location of the field in pixel.""" - y: Optional[float] = None + y: float """Top location of the field in pixel.""" - width: Optional[float] = None + width: float """Width of the field in pixel.""" - height: Optional[float] = None + height: float """Height of the field in pixel.""" @@ -4012,9 +5044,9 @@ class PageResponse: Definition: PageResponse """ - width: Optional[float] = None + width: float """Width of the page where field is placed in the PDF.""" - height: Optional[float] = None + height: float """Height of the page where field is placed in the PDF.""" @@ -4024,12 +5056,22 @@ class FieldAuthentication: Definition: FieldAuthentication """ - enabled: Optional[bool] = None + enabled: bool """ True, if authentications are enabled for the electronic signature fields. """ - sms_otp: Optional[AccessSecuritySmsOtpResponse] = None - totp: Optional[AccessSecurityTOTPResponse] = None + sms_otp: Optional[ + AccessSecuritySmsOtpResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + totp: Optional[ + AccessSecurityTOTPResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -4038,7 +5080,7 @@ class AccessSecurityTOTPResponse: Definition: AccessSecurityTOTPResponse """ - enabled: Optional[bool] = None + enabled: bool """True, if TOTP authentication is enabled for the package.""" @@ -4048,40 +5090,49 @@ class HandSignatureFieldResponse: Definition: HandSignatureFieldResponse """ - order: Optional[int] = None + order: int """ Order of the recipient to whom this field is assigned. If the field is not assigned to anyone, value will be null. """ - display_order: Optional[int] = None + display_order: int """Display order according to the SigningHub viewer.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the field.""" - page_no: Optional[int] = None + page_no: int """Page number of the document on which the field exists.""" - embedded: Optional[bool] = None + embedded: bool """True, if field is part of the PDF document.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """ If field is assigned or not, possible values are ASSIGNED, UN_ASSIGNED, SIGNED, LOGGED_IN_USER, HIDDEN and PLACEHOLDER. """ - process_status: Optional[str] = None + process_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Whether the field is processed or not. Possible values are UN_PROCESSED, PROCESSED. """ - processed_on: Optional[str] = None + processed_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date time on which the document is processed.""" - processed_as: Optional[str] = None + processed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """ User who processed the field as COLLABORATOR,DELEGATEE,GROUP_MEMBER or OWNER. """ - processed_by: Optional[str] = None + processed_by: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the user who processed the field.""" - dimensions: Optional[FieldDimenssionResponse] = None - nid: Optional[str] = None + dimensions: Optional[ + FieldDimenssionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + nid: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -4090,47 +5141,66 @@ class ElectronicSignatureFieldResponse: Definition: ElectronicSignatureFieldResponse """ - order: Optional[int] = None + order: int """Email address of the user who processed the field.""" - display_order: Optional[int] = None + display_order: int """Display order according to the SigningHub viewer.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the field.""" - page_no: Optional[int] = None + page_no: int """Page number of the document on which the field exists.""" - embedded: Optional[bool] = None + embedded: bool """True, if field is part of the PDF document.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """ If field is assigned or not, possible values are ASSIGNED, UN_ASSIGNED, SIGNED, LOGGED_IN_USER, HIDDEN and PLACEHOLDER. """ - process_status: Optional[str] = None + process_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Whether the field is processed or not. Possible values are UN_PROCESSED, PROCESSED. """ - processed_on: Optional[str] = None + processed_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date time on which the document is processed.""" - processed_as: Optional[str] = None + processed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """ User who processed the field as COLLABORATOR,DELEGATEE,GROUP_MEMBER or OWNER. """ - processed_by: Optional[str] = None + processed_by: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the user who processed the field.""" - dimensions: Optional[FieldDimenssionResponse] = None - signature_sub_type: Optional[str] = None + dimensions: Optional[ + FieldDimenssionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + signature_sub_type: Optional[str] = dataclass_field(default=None, kw_only=True) """ The signature sub-type can be a WITNESS signature. If witness signatures are enabled in service plan, E-Signature fields are signed with a common certificate shared by all the users in the service plan. Possible values are WITNESS or NONE. """ - authentication: Optional[FieldAuthentication] = None - verification: Optional[VerificationResponse] = None - nid: Optional[str] = None - display: Optional[str] = None + authentication: Optional[ + FieldAuthentication | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + verification: Optional[ + VerificationResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + nid: Optional[str] = dataclass_field(default=None, kw_only=True) + display: Optional[str] = dataclass_field(default=None, kw_only=True) """ Returns the visibility value of the electronic signature field, possible values are \"VISIBLE\" and \"INVISIBLE\". @@ -4143,33 +5213,38 @@ class InitialFieldResponse: Definition: InitialFieldResponse """ - order: Optional[int] = None + order: int """ Order of the recipient to whom this field is assigned. If the field is not assigned to anyone, value will be null. """ - display_order: Optional[int] = None + display_order: int """Display order according to the SigningHub viewer.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the field.""" - page_no: Optional[int] = None + page_no: int """Page number of the document on which the field exists.""" - process_status: Optional[str] = None + process_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Whether the field is processed or not. Possible values are UN_PROCESSED, PROCESSED. """ - processed_on: Optional[str] = None + processed_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date time on which the document is processed.""" - processed_as: Optional[str] = None + processed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """ User who processed the field as COLLABORATOR,DELEGATEE,GROUP_MEMBER or OWNER. """ - processed_by: Optional[str] = None + processed_by: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the user who processed the field.""" - dimensions: Optional[FieldDimenssionResponse] = None - embedded: Optional[bool] = None + dimensions: Optional[ + FieldDimenssionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + embedded: bool """True, if field is part of the PDF document.""" @@ -4179,56 +5254,75 @@ class InPersonFieldResponse: Definition: InPersonFieldResponse """ - order: Optional[int] = None + order: int """ Order of the recipient to whom this field is assigned. If the field is not assigned to anyone, value will be null. """ - display_order: Optional[int] = None + display_order: int """Display order according to the SigningHub viewer.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the field.""" - page_no: Optional[int] = None + page_no: int """Page number of the document on which the field exists.""" - embedded: Optional[bool] = None + embedded: bool """True, if field is part of the PDF document.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) - process_status: Optional[str] = None + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) + process_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Whether the field is processed or not. Possible values are UN_PROCESSED, PROCESSED. """ - processed_on: Optional[str] = None + processed_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date time on which the document is processed.""" - processed_as: Optional[str] = None + processed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """ User who processed the field as COLLABORATOR,DELEGATEE,GROUP_MEMBER or OWNER. """ - processed_by: Optional[str] = None + processed_by: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the user who processed the field.""" - placeholder: Optional[str] = None + placeholder: Optional[str] = dataclass_field(default=None, kw_only=True) """ Name of the in-person signer or placeholder e.g., Customer, Sales Representative etc. """ - signature_sub_type: Optional[str] = None + signature_sub_type: Optional[str] = dataclass_field(default=None, kw_only=True) """ The signature sub-type for in-person signatures can be a WITNESS signature. If witness signatures are enabled in service plan, In-person fields are signed with a common certificate shared by all the users in the service plan. Possible values are WITNESS or NONE. """ - dimensions: Optional[FieldDimenssionResponse] = None - verification: Optional[VerificationResponse] = None - display: Optional[str] = None + dimensions: Optional[ + FieldDimenssionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + verification: Optional[ + VerificationResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + display: Optional[str] = dataclass_field(default=None, kw_only=True) """ Returns the visibility value of the inperson field, possible values are \"VISIBLE\" and \"INVISIBLE\". """ - level_of_assurance: Optional[List[str]] = None + level_of_assurance: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """In Person selected level of assurances""" - authentication: Optional[FieldAuthentication] = None + authentication: Optional[ + FieldAuthentication | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -4237,29 +5331,33 @@ class TextFieldResponse: Definition: TextFieldResponse """ - required: Optional[bool] = None + required: bool """True if field required in pdf""" - order: Optional[int] = None + order: int """ Order of the recipient to whom this field is assigned. If the field is not assigned to anyone, value will be null. """ - tab_order: Optional[int] = None + tab_order: int """Tab order in the PDF document""" - display_order: Optional[int] = None + display_order: int """Display order according to the SigningHub viewer.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the field.""" - page_no: Optional[int] = None + page_no: int """Page number of the document on which the field exists.""" - embedded: Optional[bool] = None + embedded: bool """True, if field is part of the PDF document.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """ Type of the text field, possible values are \"TEXT\", \"NAME\", \"COMPANY\", \"JOBTITLE\", \"EMAIL\", \"DATE\". """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """ Value of the field. For type = DATE or format_type = DATE, the value is expected to follow ISO 8601 format.Following the format YYYY-MM-DD hh:mm:ss @@ -4267,29 +5365,34 @@ class TextFieldResponse: YYYY-MM-DD and ignore hh:mm:ss +00. If value is not in proper format an error will be returned. """ - read_only: Optional[bool] = None + read_only: bool """True, if the field is marked read only in the PDF document.""" - validation_rule: Optional[str] = None + validation_rule: Optional[str] = dataclass_field(default=None, kw_only=True) """ One or more rules for validation of the fields, possible values are \"MANDATORY\" or \"OPTIONAL\". """ - validation: Optional[FieldValidationValue] = None - visible: Optional[bool] = None + validation: Optional[ + FieldValidationValue | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + visible: bool """True, if the field is not hidden in the PDF document.""" - multiline: Optional[bool] = None + multiline: bool """True, if the field is multi line in the PDF document.""" - font: Optional[FontResponse] = None - max_length: Optional[int] = None + font: Optional[FontResponse | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + max_length: int """Maximum content length allowed to be filled in the field.""" - format_type: Optional[str] = None + format_type: Optional[str] = dataclass_field(default=None, kw_only=True) """ If field is a textbox it can follow different input types. Possible values are ALPHANUMERIC, NUMBER, TEXT, EMAIL, TIME or DATE. """ - placeholder: Optional[str] = None + placeholder: Optional[str] = dataclass_field(default=None, kw_only=True) """Placeholder text for the textbox field.""" - format: Optional[str] = None + format: Optional[str] = dataclass_field(default=None, kw_only=True) """

Text format of the field. Used for the date type field only. Possible values are

  • m/d
  • m/d/yy
  • m/d/yyyy
  • @@ -4299,20 +5402,25 @@ class TextFieldResponse:
  • mmm-yyyy
  • mmmm-yy
  • mmmm-yyyy
  • mmmm d, yyyy
  • dd/mm/yy
  • ddmmmyyyy
""" - color: Optional[str] = None + color: Optional[str] = dataclass_field(default=None, kw_only=True) """Color of the text in the form fields.""" - border_color: Optional[str] = None + border_color: Optional[str] = dataclass_field(default=None, kw_only=True) """Border color of the form field.""" - tooltip: Optional[str] = None + tooltip: Optional[str] = dataclass_field(default=None, kw_only=True) """tooltip of the form field.""" - field_rotation: Optional[int] = None + field_rotation: int """Field Rotation""" - align: Optional[str] = None + align: Optional[str] = dataclass_field(default=None, kw_only=True) """ Text alignment for the form field. Possible values are \"RIGHT\", \"LEFT\", \"CENTER\" or \"JUSTIFY\" """ - dimensions: Optional[FieldDimenssionResponse] = None + dimensions: Optional[ + FieldDimenssionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -4321,47 +5429,56 @@ class RadioFieldResponse: Definition: RadioFieldResponse """ - required: Optional[bool] = None + required: bool """True if field required in pdf""" - order: Optional[int] = None + order: int """ Order of the recipient to whom this field is assigned. If the field is not assigned to anyone, value will be null. """ - tab_order: Optional[int] = None + tab_order: int """Tab order in the PDF document.""" - display_order: Optional[int] = None + display_order: int """Display order according to the SigningHub viewer.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the field.""" - page_no: Optional[int] = None + page_no: int """Page number of the document on which the field exists.""" - embedded: Optional[bool] = None + embedded: bool """True, if field is part of the PDF document.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) - value: Optional[bool] = None + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) + value: bool """Value of the field.""" - read_only: Optional[bool] = None + read_only: bool """True, if the field is marked readonly in the PDF document.""" - validation_rule: Optional[str] = None + validation_rule: Optional[str] = dataclass_field(default=None, kw_only=True) """ One or more rules for validation of the fields possible values are \"MANDATORY\" or \"OPTIONAL\". """ - radio_group_name: Optional[str] = None + radio_group_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The group name to which the field belongs.""" - checked: Optional[bool] = None + checked: bool """True, if the field is selected""" - visible: Optional[bool] = None + visible: bool """True if the field is not hidden in the PDF document.""" - dimensions: Optional[FieldDimenssionResponse] = None - color: Optional[str] = None + dimensions: Optional[ + FieldDimenssionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + color: Optional[str] = dataclass_field(default=None, kw_only=True) """Color of the text in the form fields.""" - border_color: Optional[str] = None + border_color: Optional[str] = dataclass_field(default=None, kw_only=True) """Border color of the form field.""" - tooltip: Optional[str] = None + tooltip: Optional[str] = dataclass_field(default=None, kw_only=True) """tooltip of the form field.""" - field_rotation: Optional[int] = None + field_rotation: int """Field Rotation""" @@ -4371,45 +5488,54 @@ class CheckboxFieldResponse: Definition: CheckboxFieldResponse """ - required: Optional[bool] = None + required: bool """True if field required in pdf""" - order: Optional[int] = None + order: int """ Order of the recipient to whom this field is assigned. If the field is not assigned to anyone, value will be null. """ - tab_order: Optional[int] = None + tab_order: int """Tab order in the PDF document""" - display_order: Optional[int] = None + display_order: int """Display order according to the SigningHub viewer.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the field.""" - page_no: Optional[int] = None + page_no: int """Page number of the document on which the field exists.""" - embedded: Optional[bool] = None + embedded: bool """True, if field is part of the PDF document.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) - value: Optional[bool] = None + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) + value: bool """Value of the field.""" - read_only: Optional[bool] = None + read_only: bool """True, if the field is marked read only in the PDF document.""" - checked: Optional[bool] = None + checked: bool """True if the field is selected.""" - visible: Optional[bool] = None + visible: bool """True if the field is not hidden in the PDF document.""" - validation_rule: Optional[str] = None + validation_rule: Optional[str] = dataclass_field(default=None, kw_only=True) """ One or more rules for validation of the fields possible values are \"MANDATORY\" or \"OPTIONAL\". """ - dimensions: Optional[FieldDimenssionResponse] = None - color: Optional[str] = None + dimensions: Optional[ + FieldDimenssionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + color: Optional[str] = dataclass_field(default=None, kw_only=True) """Color of the text in the form fields.""" - border_color: Optional[str] = None + border_color: Optional[str] = dataclass_field(default=None, kw_only=True) """Border color of the form field.""" - tooltip: Optional[str] = None + tooltip: Optional[str] = dataclass_field(default=None, kw_only=True) """tooltip of the form field.""" - field_rotation: Optional[int] = None + field_rotation: int """Field Rotation""" @@ -4419,45 +5545,50 @@ class DropdownFieldResponse: Definition: DropdownFieldResponse """ - required: Optional[bool] = None + required: bool """True if field required in pdf""" - order: Optional[int] = None + order: int """ Order of the recipient to whom this field is assigned. If the field is not assigned to anyone, value will be null. """ - tab_order: Optional[int] = None + tab_order: int """Tab order in the PDF document.""" - display_order: Optional[int] = None + display_order: int """Display order according to the SigningHub viewer.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the field.""" - page_no: Optional[int] = None + page_no: int """Page number of the document on which the field exists.""" - embedded: Optional[bool] = None + embedded: bool """True, if field is part of the PDF document.""" - validation_rule: Optional[str] = None + validation_rule: Optional[str] = dataclass_field(default=None, kw_only=True) """ One or more rules for validation of the fields possible values are \"MANDATORY\" or \"OPTIONAL\". """ - read_only: Optional[bool] = None + read_only: bool """True, if the field is marked read only in the PDF document.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Value of the field .""" - choices: Optional[List[str]] = None + choices: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Choices available for the dropdown to choose a value from.""" - visible: Optional[bool] = None + visible: bool """True, if the field is not hidden in the PDF document.""" - dimensions: Optional[FieldDimenssionResponse] = None - font: Optional[FontResponse] = None - color: Optional[str] = None + dimensions: Optional[ + FieldDimenssionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + font: Optional[FontResponse | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + color: Optional[str] = dataclass_field(default=None, kw_only=True) """Color of the text in the form fields.""" - border_color: Optional[str] = None + border_color: Optional[str] = dataclass_field(default=None, kw_only=True) """Border color of the form field.""" - tooltip: Optional[str] = None + tooltip: Optional[str] = dataclass_field(default=None, kw_only=True) """tooltip of the form field.""" - field_rotation: Optional[int] = None + field_rotation: int """Field Rotation""" @@ -4467,43 +5598,48 @@ class ListBoxFieldResponse: Definition: ListBoxFieldResponse """ - order: Optional[int] = None + order: int """ Order of the recipient to whom this field is assigned. If the field is not assigned to anyone, value will be null. """ - tab_order: Optional[int] = None + tab_order: int """Tab order in the PDF document.""" - display_order: Optional[int] = None + display_order: int """Display order according to the SigningHub viewer.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the field.""" - page_no: Optional[int] = None + page_no: int """Page number of the document on which the field exists.""" - embedded: Optional[bool] = None + embedded: bool """True, if field is part of the PDF document.""" - validation_rule: Optional[str] = None + validation_rule: Optional[str] = dataclass_field(default=None, kw_only=True) """ One or more rules for validation of the fields possible values are \"MANDATORY\" or \"OPTIONAL\". """ - read_only: Optional[bool] = None + read_only: bool """True, if the field is marked read only in the PDF document.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Value of the field.""" - choices: Optional[List[str]] = None + choices: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Choices available for the dropdown to choose a value from.""" - visible: Optional[bool] = None + visible: bool """True, if the field is not hidden in the PDF document.""" - dimensions: Optional[FieldDimenssionResponse] = None - font: Optional[FontResponse] = None - color: Optional[str] = None + dimensions: Optional[ + FieldDimenssionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + font: Optional[FontResponse | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + color: Optional[str] = dataclass_field(default=None, kw_only=True) """Color of the text in the form fields.""" - border_color: Optional[str] = None + border_color: Optional[str] = dataclass_field(default=None, kw_only=True) """Border color of the form field.""" - tooltip: Optional[str] = None + tooltip: Optional[str] = dataclass_field(default=None, kw_only=True) """tooltip of the form field.""" - field_rotation: Optional[int] = None + field_rotation: int """Field Rotation""" @@ -4513,15 +5649,15 @@ class FontResponse: Definition: FontResponse """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Font name for the text field. For user defined fields SigningHub only support \"COURIER\", \"HELVETICA\". In case of existing fields in a PDF file, font value can be anything that is set in the PDF. """ - size: Optional[int] = None + size: int """Font size for the text field.""" - embedded_size: Optional[float] = None + embedded_size: float """Size of the font in the original PDF document.""" @@ -4531,24 +5667,38 @@ class QrCodeResponse: Definition: QrCodeResponse """ - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the field.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Field Type PDF_FIELD_TYPE like QR""" - page_no: Optional[int] = None + page_no: int """Page number of the document on which the field exists.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """QrCode generated base64 will be provided inly in draft mode""" - dimensions: Optional[FieldDimenssionResponse] = None - data: Optional[str] = None + dimensions: Optional[ + FieldDimenssionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + data: Optional[str] = dataclass_field(default=None, kw_only=True) """ The plain text data to be encoded in the QR code. Default is URL generated to access the related document. e.g. {base_url}/document/{document_unique_id} """ - options: Optional[QrCodeOptions] = None - color: Optional[QrCodeColor] = None - logo: Optional[QrCodeLogo] = None + options: Optional[ + QrCodeOptions | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + color: Optional[QrCodeColor | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + logo: Optional[QrCodeLogo | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -4557,37 +5707,43 @@ class AttachmentFieldResponse: Definition: AttachmentFieldResponse """ - order: Optional[int] = None + order: int """Order of the recipient to whom this field is assigned.""" - display_order: Optional[int] = None + display_order: int """Display order according to the SigningHub viewer.""" - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the field.""" - page_no: Optional[int] = None + page_no: int """Page number of the document on which the field exists.""" - process_status: Optional[str] = None + process_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Whether the field is processed or not. Possible values are UN_PROCESSED, PROCESSED. """ - processed_on: Optional[str] = None + processed_on: Optional[str] = dataclass_field(default=None, kw_only=True) """Date time on which the document is processed.""" - processed_as: Optional[str] = None + processed_as: Optional[str] = dataclass_field(default=None, kw_only=True) """ User who processed the field as COLLABORATOR,DELEGATEE,GROUP_MEMBER or OWNER. """ - processed_by: Optional[str] = None + processed_by: Optional[str] = dataclass_field(default=None, kw_only=True) """Email address of the user who processed the field.""" - attachment_ref_id: Optional[int] = field( + attachment_ref_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "attachmentRefId"}, ) """Attachmet ref id""" - note: Optional[str] = None + note: Optional[str] = dataclass_field(default=None, kw_only=True) """Attachmet note Only in case of \"MANDATORY\" attachment rule""" - validation_rule: Optional[ValidationRule] = None - dimensions: Optional[FieldDimenssionResponse] = None + validation_rule: ValidationRule + dimensions: Optional[ + FieldDimenssionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -4596,17 +5752,27 @@ class CommentFieldResponse: Definition: CommentFieldResponse """ - id: Optional[int] = None + id: int """Comment field id""" - page_no: Optional[int] = None + page_no: int """Page number of the document on which the field exists.""" - unread_count: Optional[int] = None + unread_count: int """Unread comments""" - private: Optional[bool] = None + private: bool """Private""" - recipients: Optional[List[CommentFieldRecipientResponse]] = None + recipients: Optional[ + List[CommentFieldRecipientResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Recipients""" - dimensions: Optional[FieldDimenssionResponse] = None + dimensions: Optional[ + FieldDimenssionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -4615,14 +5781,19 @@ class UniqueIdentifierFieldResponse: Definition: UniqueIdentifierFieldResponse """ - field_name: Optional[str] = None + field_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the field.""" - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """Value of the field.""" - page_no: Optional[int] = None + page_no: int """Page number of the document on which the field exists.""" - font: Optional[FontResponse] = None - dimensions: Optional[FieldDimenssionResponse] = None + font: Optional[FontResponse | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + dimensions: Optional[ + FieldDimenssionResponse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -4631,9 +5802,9 @@ class CommentFieldRecipientResponse: Definition: CommentFieldRecipientResponse """ - user_name: Optional[str] = None + user_name: Optional[str] = dataclass_field(default=None, kw_only=True) """User name""" - user_email: Optional[str] = None + user_email: Optional[str] = dataclass_field(default=None, kw_only=True) """User email""" @@ -4643,15 +5814,15 @@ class AssignFieldRequest: Definition: AssignFieldRequest """ - field_name: Optional[str] = None + field_name: str """Name of the signature field that is to be assigned.""" - radio_group_name: Optional[str] = None + radio_group_name: Optional[str] = dataclass_field(default=None, kw_only=True) """provide group name for radio box""" - order: Optional[int] = None + order: int """ The order of the user in workflow, to which the field is being assigned. """ - level_of_assurance: Optional[List[str]] = None + level_of_assurance: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ Level Of Assurance to be added. Possible Values are \"ELECTRONIC_SIGNATURE\", \"ELECTRONIC_SEAL\", @@ -4669,16 +5840,16 @@ class SigninghubClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -4689,8 +5860,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -4698,8 +5869,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -4711,7 +5882,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -4726,7 +5897,46 @@ def __init__( def connector_name(self) -> str: return "signinghub" - async def attachment_delete_attachment_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def attachment_delete_attachment( self, package_id: int, document_id: int, @@ -4742,6 +5952,24 @@ async def attachment_delete_attachment_async( Business applications can use this service API to delete the attachment of a document. + + Swagger operation ID: `V4_Attachment_DeleteAttachment`. + + Args: + package_id: Package ID of the package to which the document is + added. + document_id: ID of the document to which the attachment is added. + attachment_id: ID of the attachment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4754,7 +5982,7 @@ async def attachment_delete_attachment_async( f"/{quote(str(attachment_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -4768,6 +5996,7 @@ async def attachment_delete_attachment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4775,7 +6004,7 @@ async def attachment_delete_attachment_async( return json.loads(response.text) - async def attachment_download_attachment_async( + def attachment_download_attachment( self, package_id: int, document_id: int, @@ -4791,6 +6020,24 @@ async def attachment_download_attachment_async( Business applications can use this service API to download the attachment of a document. + + Swagger operation ID: `V4_Attachment_DownloadAttachment`. + + Args: + package_id: Package ID of the package to which the document is + added. + document_id: ID of the document to which the attachment is added. + attachment_id: ID of the attachment. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4803,7 +6050,7 @@ async def attachment_download_attachment_async( f"/{quote(str(attachment_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4817,6 +6064,7 @@ async def attachment_download_attachment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4824,7 +6072,7 @@ async def attachment_download_attachment_async( return json.loads(response.text) - async def attachment_get_attachments_async( + def list_attachment_get_attachments( self, package_id: int, document_id: int, @@ -4833,12 +6081,33 @@ async def attachment_get_attachments_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Attachments Business applications can use this service API to get the attachments of a document. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `V4_Attachment_GetAttachments`. + + Args: + package_id: Package ID of the package to which the document is + added. + document_id: ID of the document to which the attachment is added. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4849,29 +6118,50 @@ async def attachment_get_attachments_async( f"/{quote(str(document_id), safe='')}" f"/attachments" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def attachment_upload_attachment_async( + return ItemPaged(get_next, extract_data) + + def attachment_upload_attachment( self, input: bytes, package_id: int, @@ -4887,6 +6177,25 @@ async def attachment_upload_attachment_async( Business applications can use this service API to upload a attachment in a document. + + Swagger operation ID: `V4_Attachment_UploadAttachment`. + + Args: + input: The binary request body. + package_id: Package ID of the package to which the document is + added. + document_id: ID of the document to which the attachment needs to be + add. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4898,7 +6207,7 @@ async def attachment_upload_attachment_async( f"/attachments" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -4915,6 +6224,7 @@ async def attachment_upload_attachment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4922,9 +6232,9 @@ async def attachment_upload_attachment_async( return json.loads(response.text) - async def checkbox_add_check_box_async( + def checkbox_add_check_box( self, - input: CheckBoxFieldRequest, + input: CheckBoxFieldRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -4950,6 +6260,24 @@ async def checkbox_add_check_box_async( will be assigned. If either width or height (or both) is provided, the system will compare these provided values with each other. The larger value between width and height will be assigned to both dimensions. + + Swagger operation ID: `V4_Checkbox_AddCheckBox`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4962,7 +6290,7 @@ async def checkbox_add_check_box_async( f"/checkbox" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4976,6 +6304,7 @@ async def checkbox_add_check_box_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4983,9 +6312,9 @@ async def checkbox_add_check_box_async( return json.loads(response.text) - async def checkbox_update_check_box_async( + def checkbox_update_check_box( self, - input: UpdateCheckBoxFieldRequest, + input: UpdateCheckBoxFieldRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -5006,6 +6335,24 @@ async def checkbox_update_check_box_async( be used when a template was applied or the document was created using the GUI interface. It's width and height cannot be updated. They will remain the same as when they were added. + + Swagger operation ID: `V4_Checkbox_UpdateCheckBox`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5018,7 +6365,7 @@ async def checkbox_update_check_box_async( f"/checkbox" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -5032,6 +6379,7 @@ async def checkbox_update_check_box_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5039,18 +6387,18 @@ async def checkbox_update_check_box_async( return json.loads(response.text) - async def contacts_get_async( + def list_contacts_get( self, record_per_page: int, page_no: int, + *, sort_by: Optional[str] = None, asc: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Contacts @@ -5061,6 +6409,28 @@ async def contacts_get_async( specific contacts or that of the enterprise to which the user belongs. The search response information contains the user email address and respective user name. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `V4_Contacts_Get`. + + Args: + record_per_page: Total number of records to be retrieved in a page. + page_no: Page number to be retrieved. + sort_by: Sort the result by possible values are mentioned above. + asc: Order the result set by ascending or descending. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5083,29 +6453,50 @@ async def contacts_get_async( query_params.append(f"asc={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def documents_delete_document_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def documents_delete_document( self, package_id: int, document_id: int, @@ -5120,6 +6511,23 @@ async def documents_delete_document_async( Business applications can use this service API to delete a document in a package. + + Swagger operation ID: `V4_Documents_DeleteDocument`. + + Args: + package_id: Package ID of the package to which the document is + added. + document_id: ID of the document to be deleted. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5130,7 +6538,7 @@ async def documents_delete_document_async( f"/{quote(str(document_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -5144,6 +6552,7 @@ async def documents_delete_document_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5151,7 +6560,7 @@ async def documents_delete_document_async( return json.loads(response.text) - async def documents_download_document_bytes_async( + def documents_download_document_bytes( self, package_id: int, document_id: int, @@ -5166,6 +6575,23 @@ async def documents_download_document_bytes_async( Business applications can use this service API to download the document bytes. The package ID and document ID is provided in the resource URL. + + Swagger operation ID: `V4_Documents_DownloadDocumentBytes`. + + Args: + package_id: Package ID of the package to which the document is + added. + document_id: The ID of the document to be downloaded. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5176,7 +6602,7 @@ async def documents_download_document_bytes_async( f"/{quote(str(document_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5190,6 +6616,7 @@ async def documents_download_document_bytes_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5197,7 +6624,7 @@ async def documents_download_document_bytes_async( return json.loads(response.text) - async def documents_get_certify_policy_async( + def documents_get_certify_policy( self, package_id: int, document_id: int, @@ -5212,6 +6639,23 @@ async def documents_get_certify_policy_async( Business applications can use this service API to get certify signature settings of a document in a package. + + Swagger operation ID: `V4_Documents_GetCertifyPolicy`. + + Args: + package_id: Package ID of the package to which the document is + added. + document_id: The ID of the document to be downloaded. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5223,7 +6667,7 @@ async def documents_get_certify_policy_async( f"/certify" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5237,6 +6681,7 @@ async def documents_get_certify_policy_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5244,7 +6689,7 @@ async def documents_get_certify_policy_async( return json.loads(response.text) - async def documents_get_document_details_async( + def documents_get_document_details( self, package_id: int, document_id: int, @@ -5259,6 +6704,24 @@ async def documents_get_document_details_async( Business applications can use this service API to get the document details. The document ID is provided in the URL as \"{document_id}\". + + Swagger operation ID: `V4_Documents_GetDocumentDetails`. + + Args: + package_id: The Package ID of the package to which the document is + added. + document_id: The document ID for which the document details are + requested. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5270,7 +6733,7 @@ async def documents_get_document_details_async( f"/details" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5284,6 +6747,7 @@ async def documents_get_document_details_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5291,9 +6755,9 @@ async def documents_get_document_details_async( return json.loads(response.text) - async def documents_rename_document_async( + def documents_rename_document( self, - input: RenameDocumentRequest, + input: RenameDocumentRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -5307,6 +6771,26 @@ async def documents_rename_document_async( Business applications can use this service API to rename a document in a package. + + Swagger operation ID: `V4_Documents_RenameDocument`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID of the package to which the document is + added. + document_id: The ID of the document to on which the action is to be + performed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5317,7 +6801,7 @@ async def documents_rename_document_async( f"/{quote(str(document_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -5331,6 +6815,7 @@ async def documents_rename_document_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5338,9 +6823,9 @@ async def documents_rename_document_async( return json.loads(response.text) - async def documents_update_certify_policy_async( + def documents_update_certify_policy( self, - input: UpdateCertifyPolicyRequest, + input: UpdateCertifyPolicyRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -5354,6 +6839,26 @@ async def documents_update_certify_policy_async( Business applications can use this service API to update certify signature settings for a document in a package. + + Swagger operation ID: `V4_Documents_UpdateCertifyPolicy`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID of the package to which the document is + added. + document_id: The ID of the document on which the action is to be + performed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5365,7 +6870,7 @@ async def documents_update_certify_policy_async( f"/certify" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -5379,6 +6884,7 @@ async def documents_update_certify_policy_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5386,7 +6892,7 @@ async def documents_update_certify_policy_async( return json.loads(response.text) - async def documents_upload_from_library_async( + def documents_upload_from_library( self, package_id: int, document_id: int, @@ -5405,6 +6911,23 @@ async def documents_upload_from_library_async( resource URL to identify the library document to be copied. Note a package must already exist before you can add a document using this call. + + Swagger operation ID: `V4_Documents_UploadFromLibrary`. + + Args: + package_id: The Package ID of the package to which the document is + being added. + document_id: The library document ID that need to add/updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5416,7 +6939,7 @@ async def documents_upload_from_library_async( f"/{quote(str(document_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -5430,6 +6953,7 @@ async def documents_upload_from_library_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5437,7 +6961,7 @@ async def documents_upload_from_library_async( return json.loads(response.text) - async def documents_upload_stream_async( + def documents_upload_stream( self, input: bytes, package_id: int, @@ -5461,13 +6985,30 @@ async def documents_upload_stream_async( converted to PDF format upon upload.Click here for the full list. Note PDF documents are not altered upon upload to the system. Note a package must already exist before you can add a document using this call. + + Swagger operation ID: `V4_Documents_UploadStream`. + + Args: + input: The binary request body. + package_id: Package ID of the package to which the document is + being added. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/documents" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -5484,6 +7025,7 @@ async def documents_upload_stream_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5491,7 +7033,7 @@ async def documents_upload_stream_async( return json.loads(response.text) - async def enterprise_documents_get_enterprise_workflow_access_async( + def enterprise_documents_get_enterprise_workflow_access( self, package_id: int, order: int, @@ -5512,6 +7054,25 @@ async def enterprise_documents_get_enterprise_workflow_access_async( to access document package outside the scope of this duration if the access security is enabled. Document owner can also configure authentication based security of the package for a recipient. + + Swagger operation ID: + `V4_EnterpriseDocuments_GetEnterpriseWorkflowAccess`. + + Args: + package_id: The package ID for which workflow access security and + authentication is to be updated. + order: Order of the recipient in the workflow for which the access + security and authentication is to be updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5524,7 +7085,7 @@ async def enterprise_documents_get_enterprise_workflow_access_async( f"/authentication" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5538,6 +7099,7 @@ async def enterprise_documents_get_enterprise_workflow_access_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5545,9 +7107,9 @@ async def enterprise_documents_get_enterprise_workflow_access_async( return json.loads(response.text) - async def enterprise_documents_update_enterprise_workflow_access_async( + def enterprise_documents_update_enterprise_workflow_access( self, - input: AccessUpdateRequest, + input: AccessUpdateRequest | Mapping[str, Any], package_id: int, order: int, *, @@ -5564,6 +7126,27 @@ async def enterprise_documents_update_enterprise_workflow_access_async( authentications and access duration for the recipients. This API can also be used by the enterprise administrator or the enterprise user if the \"scope\" variable was used in the authentication request + + Swagger operation ID: + `V4_EnterpriseDocuments_UpdateEnterpriseWorkflowAccess`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The package ID for which workflow access security and + authentication is to be updated. + order: Order of the recipient in the workflow for which the access + security and authentication is to be updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5576,7 +7159,7 @@ async def enterprise_documents_update_enterprise_workflow_access_async( f"/authentication" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -5590,6 +7173,7 @@ async def enterprise_documents_update_enterprise_workflow_access_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5597,7 +7181,7 @@ async def enterprise_documents_update_enterprise_workflow_access_async( return json.loads(response.text) - async def fields_auto_assign_field_async( + def fields_auto_assign_field( self, input: FieldsAutoAssignFieldInput, package_id: int, @@ -5621,6 +7205,24 @@ async def fields_auto_assign_field_async( they are numbered \"1\", \"2\", and \"3\" respectfully.This API call allows you to assign a user by their workflow order number, to an input field on the document. + + Swagger operation ID: `V4_Fields_AutoAssignField`. + + Args: + input: The request body. + package_id: Package ID to which the document is added. + document_id: The document ID for which workflow user needs to be + updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5633,7 +7235,7 @@ async def fields_auto_assign_field_async( f"/assign" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -5647,6 +7249,7 @@ async def fields_auto_assign_field_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5654,9 +7257,9 @@ async def fields_auto_assign_field_async( return json.loads(response.text) - async def fields_auto_place_async( + def fields_auto_place( self, - input: AutoPlaceFieldRequest, + input: AutoPlaceFieldRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -5693,6 +7296,25 @@ async def fields_auto_place_async( Workflow](#operation/Workflow_WorkflowAddUser) for more information. Note if you have a document with a template applied, or have applied one using the APIs, then the workflow will already contain users. + + Swagger operation ID: `V4_Fields_AutoPlace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The ID of the package to which the document is added. + document_id: The ID of the document for which the fields are + requested. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5705,7 +7327,7 @@ async def fields_auto_place_async( f"/autoplace" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5719,6 +7341,7 @@ async def fields_auto_place_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5726,9 +7349,9 @@ async def fields_auto_place_async( return json.loads(response.text) - async def fields_delete_document_field_async( + def fields_delete_document_field( self, - input: DeleteDocumentFieldRequest, + input: DeleteDocumentFieldRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -5742,6 +7365,24 @@ async def fields_delete_document_field_async( Business applications can use this service API to delete a field of document in a package. + + Swagger operation ID: `V4_Fields_DeleteDocumentField`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5753,7 +7394,7 @@ async def fields_delete_document_field_async( f"/fields" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=input, timeout=timeout, headers=headers, @@ -5767,6 +7408,7 @@ async def fields_delete_document_field_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5774,9 +7416,9 @@ async def fields_delete_document_field_async( return json.loads(response.text) - async def fields_fill_form_fields_async( + def fields_fill_form_fields( self, - input: FormFillingRequest, + input: FormFillingRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -5790,6 +7432,24 @@ async def fields_fill_form_fields_async( Business applications can use this service API to fill one or more form fields in a document by a specified user in the order. + + Swagger operation ID: `V4_Fields_FillFormFields`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The ID of the document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5801,7 +7461,7 @@ async def fields_fill_form_fields_async( f"/fields" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -5815,6 +7475,7 @@ async def fields_fill_form_fields_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5822,7 +7483,7 @@ async def fields_fill_form_fields_async( return json.loads(response.text) - async def fields_get_all_document_fields_async( + def fields_get_all_document_fields( self, package_id: int, document_id: int, @@ -5838,6 +7499,26 @@ async def fields_get_all_document_fields_async( Business applications can use this service API to get document fields i.e., initials, in-persons, signature fields or form fields. + + Swagger operation ID: `V4_Fields_GetAllDocumentFields`. + + Args: + package_id: The ID of the package to which the document is added. + document_id: The ID of the document for which the fields are + requested. + page_no: Page no of the document for which the fields are + requested. If page number is not provided fields of whole + document are returned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5850,7 +7531,7 @@ async def fields_get_all_document_fields_async( f"/{quote(str(page_no), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5864,6 +7545,7 @@ async def fields_get_all_document_fields_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5871,9 +7553,9 @@ async def fields_get_all_document_fields_async( return json.loads(response.text) - async def folder_move_package_async( + def folder_move_package( self, - input: MoveToRequest, + input: MoveToRequest | Mapping[str, Any], package_id: int, *, timeout: Optional[float] = None, @@ -5886,13 +7568,30 @@ async def folder_move_package_async( Business applications can use this service API to move the document package to a shared space or user's custom folder. + + Swagger operation ID: `V4_Folder_MovePackage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package id that need to move to folder. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/move_to" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -5906,6 +7605,7 @@ async def folder_move_package_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5913,9 +7613,9 @@ async def folder_move_package_async( return json.loads(response.text) - async def initials_add_initial_async( + def initials_add_initial( self, - input: InitialFieldRequest, + input: InitialFieldRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -5937,6 +7637,24 @@ async def initials_add_initial_async( Workflow](#operation/Workflow_WorkflowAddUser) for more information. Note if you have a document with a template applied, or have applied one using the APIs, then the workflow will already contain users. + + Swagger operation ID: `V4_Initials_AddInitial`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5949,7 +7667,7 @@ async def initials_add_initial_async( f"/initials" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5963,6 +7681,7 @@ async def initials_add_initial_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5970,9 +7689,9 @@ async def initials_add_initial_async( return json.loads(response.text) - async def initials_fill_async( + def initials_fill( self, - input: InitialFillingRequest, + input: InitialFillingRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -5986,6 +7705,24 @@ async def initials_fill_async( Business applications can use this service API to fill an initials field in a document by a specified user in the order. + + Swagger operation ID: `V4_Initials_Fill`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The ID of the document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5997,7 +7734,7 @@ async def initials_fill_async( f"/initial" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6011,6 +7748,7 @@ async def initials_fill_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6018,9 +7756,9 @@ async def initials_fill_async( return json.loads(response.text) - async def initials_update_initial_async( + def initials_update_initial( self, - input: UpdateInitialFieldRequest, + input: UpdateInitialFieldRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -6040,6 +7778,24 @@ async def initials_update_initial_async( Document Fields](#operation/Documents_GetDocumentFields).The latter can be used when a template was applied or the document was created using the GUI interface. + + Swagger operation ID: `V4_Initials_UpdateInitial`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6052,7 +7808,7 @@ async def initials_update_initial_async( f"/initials" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -6066,6 +7822,7 @@ async def initials_update_initial_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6073,9 +7830,9 @@ async def initials_update_initial_async( return json.loads(response.text) - async def in_person_add_in_person_async( + def in_person_add_in_person( self, - input: InPersonFieldRequest, + input: InPersonFieldRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -6106,6 +7863,24 @@ async def in_person_add_in_person_async( recipient would be in the same location.This type of signature is not intended for use whereby a document is shared with recipients over email link in the normal loose integration method. + + Swagger operation ID: `V4_InPerson_AddInPerson`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6118,7 +7893,7 @@ async def in_person_add_in_person_async( f"/in_person_signature" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6132,6 +7907,7 @@ async def in_person_add_in_person_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6139,9 +7915,9 @@ async def in_person_add_in_person_async( return json.loads(response.text) - async def in_person_update_in_person_async( + def in_person_update_in_person( self, - input: UpdateInPersonFieldRequest, + input: UpdateInPersonFieldRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -6162,6 +7938,24 @@ async def in_person_update_in_person_async( Fields](#operation/Documents_GetDocumentFields).The latter can be used when a template was applied or the document was created using the GUI interface. + + Swagger operation ID: `V4_InPerson_UpdateInPerson`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6174,7 +7968,7 @@ async def in_person_update_in_person_async( f"/in_person_signature" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -6188,6 +7982,7 @@ async def in_person_update_in_person_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6195,9 +7990,9 @@ async def in_person_update_in_person_async( return json.loads(response.text) - async def package_add_package_async( + def package_add_package( self, - input: AddDocumentPackageRequest, + input: AddDocumentPackageRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -6214,10 +8009,26 @@ async def package_add_package_async( exist before you can upload or add documents to SigningHub.. Even a single document is a part of a package: a package containing one document. Note: A package can be renamed if required once created. + + Swagger operation ID: `V4_Package_AddPackage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v4/packages" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6231,6 +8042,7 @@ async def package_add_package_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6238,9 +8050,9 @@ async def package_add_package_async( return json.loads(response.text) - async def package_approve_async( + def package_approve( self, - input: ApproveRequest, + input: ApproveRequest | Mapping[str, Any], package_id: int, *, timeout: Optional[float] = None, @@ -6253,13 +8065,30 @@ async def package_approve_async( Business applications can use this service API to approve a document by a specified user in the order. + + Swagger operation ID: `V4_Package_Approve`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The ID of the package to be approved. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/approve" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6273,6 +8102,7 @@ async def package_approve_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6280,9 +8110,9 @@ async def package_approve_async( return json.loads(response.text) - async def package_decline_async( + def package_decline( self, - input: DeclineRequest, + input: DeclineRequest | Mapping[str, Any], package_id: int, *, timeout: Optional[float] = None, @@ -6295,13 +8125,30 @@ async def package_decline_async( Business applications can use this service API to decline a document by a specified user in the order. + + Swagger operation ID: `V4_Package_Decline`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The ID of the package to be declined. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/decline" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6315,6 +8162,7 @@ async def package_decline_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6322,7 +8170,7 @@ async def package_decline_async( return json.loads(response.text) - async def package_delete_package_async( + def package_delete_package( self, package_id_bulk_action: int, *, @@ -6340,13 +8188,29 @@ async def package_delete_package_async( automatically declined as result of delete operation. If the document status is SHARED, then the document is automatically recalled and workflow is stopped before the document is deleted. + + Swagger operation ID: `V4_Package_DeletePackage`. + + Args: + package_id_bulk_action: Package ID of the package which contains + the document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id_bulk_action), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -6360,6 +8224,7 @@ async def package_delete_package_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6367,11 +8232,11 @@ async def package_delete_package_async( return json.loads(response.text) - async def package_download_package_bytes_async( + def package_download_package_bytes( self, package_id_bulk_action: int, - document_ids: Optional[List[int]] = None, *, + document_ids: Optional[List[int]] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -6387,6 +8252,24 @@ async def package_download_package_bytes_async( document, the download is the binary zip file of all documents. The x-password and x-otp headers are optional. They are required if the document owner set them during the workflow creation phase. + + Swagger operation ID: `V4_Package_DownloadPackageBytes`. + + Args: + package_id_bulk_action: The package ID to be downloaded. + document_ids: The Document IDs parameter is optional. If + x-combine-files is set to true, the documents will be merged + based on the mentioned documents of the package. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6412,7 +8295,7 @@ async def package_download_package_bytes_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6426,6 +8309,7 @@ async def package_download_package_bytes_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6433,7 +8317,7 @@ async def package_download_package_bytes_async( return json.loads(response.text) - async def package_finish_async( + def package_finish( self, package_id: int, *, @@ -6464,13 +8348,28 @@ async def package_finish_async( SigningHub App, this method is invoked by the application to ensure the workflow continues to process and the next signatory is notified, and the document status is available via the configured call-back URL. + + Swagger operation ID: `V4_Package_Finish`. + + Args: + package_id: The ID of the package to be finished. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/finish" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -6484,6 +8383,7 @@ async def package_finish_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6491,9 +8391,9 @@ async def package_finish_async( return json.loads(response.text) - async def package_gatekeeper_approve_async( + def package_gatekeeper_approve( self, - input: ApproveRequest, + input: ApproveRequest | Mapping[str, Any], package_id: int, *, timeout: Optional[float] = None, @@ -6506,6 +8406,23 @@ async def package_gatekeeper_approve_async( Business applications can use this service API to gatekeeper approve a document by a specified user in the order. + + Swagger operation ID: `V4_Package_GatekeeperApprove`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The ID of the package to be approved. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6516,7 +8433,7 @@ async def package_gatekeeper_approve_async( f"/approve" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6530,6 +8447,7 @@ async def package_gatekeeper_approve_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6537,9 +8455,9 @@ async def package_gatekeeper_approve_async( return json.loads(response.text) - async def package_gatekeeper_decline_async( + def package_gatekeeper_decline( self, - input: DeclineRequest, + input: DeclineRequest | Mapping[str, Any], package_id: int, *, timeout: Optional[float] = None, @@ -6552,6 +8470,23 @@ async def package_gatekeeper_decline_async( Business applications can use this service API to gatekeeper decline a document by a specified user in the order. + + Swagger operation ID: `V4_Package_GatekeeperDecline`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The ID of the package to be declined. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6562,7 +8497,7 @@ async def package_gatekeeper_decline_async( f"/decline" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6576,6 +8511,7 @@ async def package_gatekeeper_decline_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6583,11 +8519,12 @@ async def package_gatekeeper_decline_async( return json.loads(response.text) - async def package_get_all_packages_async( + def list_package_get_all_packages( self, document_status: str, page_no: int, record_per_page: int, + *, package_name: Optional[str] = None, package_id: Optional[int] = None, recipient_from: Optional[str] = None, @@ -6607,18 +8544,61 @@ async def package_get_all_packages_async( document_statuses: Optional[List[str]] = None, owned_by: Optional[str] = None, smart_form: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Packages Business applications can use this service API to get a list of documents filtered by different statuses. Users can divide the records into pages by providing a number of records per page. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `V4_Package_GetAllPackages`. + + Args: + document_status: Filter by document status possible values are ALL, + DRAFT, PENDING, SIGNED, DECLINED, INPROGRESS, EDITED, REVIEWED, + COMPLETED, EXPIRING_IN_SEVEN_DAYS. + page_no: Page number, according the division of records per page. + record_per_page: Number of records that are needed to be fetched in + one request. + package_name: Package Name. + package_id: Package Id. + recipient_from: From. + recipient_to: To. + document_id: Document Id. + expiry: Expiry (Days). + modified_from: From Modified Date. + modified_to: To Modified Date. + size_from: From Size (KB). + size_to: To Size (KB). + certified_documents: Only certified signed documents. + form_fields: Only documents that have form fields. + attachments: Only documents that have attachments. + document_type: Document Type like XML, PDF, DOCX etc. + sort_by: Sort the resultant records as per your choice. + asc: Sorted the resultant records by ascending or descending order. + document_statuses: Document Type. + owned_by: Owned By filter possible values are ME_OTHERS, ME, + OTHERS. + smart_form: Smart form name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6733,33 +8713,54 @@ async def package_get_all_packages_async( if smart_form is not None: value = str(smart_form) if isinstance(smart_form, bool): - value = value.lower() - query_params.append(f"smart-form={quote(value, safe='')}") - if query_params: - request_url += '?' + '&'.join(query_params) - - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + value = value.lower() + query_params.append(f"smart-form={quote(value, safe='')}") + if query_params: + request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - async def package_get_package_details_async( + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def package_get_package_details( self, package_id: int, *, @@ -6775,13 +8776,28 @@ async def package_get_package_details_async( package. This API can also be used by the business application to perform action on behalf of the enterprise user via \"Scope Authentication\". + + Swagger operation ID: `V4_Package_GetPackageDetails`. + + Args: + package_id: Package ID of the document package. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/details" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6795,6 +8811,7 @@ async def package_get_package_details_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6802,9 +8819,9 @@ async def package_get_package_details_async( return json.loads(response.text) - async def package_rename_package_async( + def package_rename_package( self, - input: RenameDocumentPackageRequest, + input: RenameDocumentPackageRequest | Mapping[str, Any], package_id_bulk_action: int, *, timeout: Optional[float] = None, @@ -6817,13 +8834,30 @@ async def package_rename_package_async( This service API is used to rename a document package. The document package is identified by its unique identifier in the URL of the call. + + Swagger operation ID: `V4_Package_RenamePackage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id_bulk_action: Package ID to change the name of. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id_bulk_action), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -6837,6 +8871,7 @@ async def package_rename_package_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6844,7 +8879,7 @@ async def package_rename_package_async( return json.loads(response.text) - async def package_submit_async( + def package_submit( self, package_id: int, *, @@ -6864,13 +8899,29 @@ async def package_submit_async( [SigningHub Roles](http://manuals.ascertia.com/SigningHubv7/default.aspx#pageid=1056) for a description of all available workflow recipient roles. + + Swagger operation ID: `V4_Package_Submit`. + + Args: + package_id: The SigningHub package ID that contains the document to + be submitted. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/submit" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -6884,6 +8935,7 @@ async def package_submit_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6891,9 +8943,9 @@ async def package_submit_async( return json.loads(response.text) - async def qr_add_qr_code_async( + def qr_add_qr_code( self, - input: QrCodeRequest, + input: QrCodeRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -6907,6 +8959,24 @@ async def qr_add_qr_code_async( Business applications can use this service API to add a QR Code to a document in a package. + + Swagger operation ID: `V4_QR_AddQRCode`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6919,7 +8989,7 @@ async def qr_add_qr_code_async( f"/qrcode" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6933,6 +9003,7 @@ async def qr_add_qr_code_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6940,9 +9011,9 @@ async def qr_add_qr_code_async( return json.loads(response.text) - async def qr_update_qr_code_async( + def qr_update_qr_code( self, - input: UpdateQrCodeRequest, + input: UpdateQrCodeRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -6956,6 +9027,24 @@ async def qr_update_qr_code_async( Business applications can use this service API to update a QR Code of a document in a package. + + Swagger operation ID: `V4_QR_UpdateQRCode`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6968,7 +9057,7 @@ async def qr_update_qr_code_async( f"/qrcode" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -6982,6 +9071,7 @@ async def qr_update_qr_code_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6989,9 +9079,9 @@ async def qr_update_qr_code_async( return json.loads(response.text) - async def radio_add_radio_box_async( + def radio_add_radio_box( self, - input: RadioBoxFieldRequest, + input: RadioBoxFieldRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -7017,6 +9107,24 @@ async def radio_add_radio_box_async( will be assigned. If either width or height (or both) is provided, the system will compare these provided values with each other. The larger value between width and height will be assigned to both dimensions. + + Swagger operation ID: `V4_Radio_AddRadioBox`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7029,7 +9137,7 @@ async def radio_add_radio_box_async( f"/radio" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7043,6 +9151,7 @@ async def radio_add_radio_box_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7050,9 +9159,9 @@ async def radio_add_radio_box_async( return json.loads(response.text) - async def radio_update_radio_box_async( + def radio_update_radio_box( self, - input: UpdateRadioBoxFieldRequest, + input: UpdateRadioBoxFieldRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -7073,6 +9182,24 @@ async def radio_update_radio_box_async( when a template was applied or the document was created using the GUI interface. It's width and height cannot be updated. They will remain the same as when they were added. + + Swagger operation ID: `V4_Radio_UpdateRadioBox`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7085,7 +9212,7 @@ async def radio_update_radio_box_async( f"/radio" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -7099,6 +9226,7 @@ async def radio_update_radio_box_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7106,18 +9234,18 @@ async def radio_update_radio_box_async( return json.loads(response.text) - async def settings_get_templates_async( + def list_settings_get_templates( self, record_per_page: int, page_no: int, + *, sort_by: Optional[str] = None, asc: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Templates @@ -7126,6 +9254,30 @@ async def settings_get_templates_async( supplied under the \"x-search-text\" header.Furthermore, it is possible to search a user's personal templates or the enterprise templates as allowed against their user role by their enterprise admin. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `V4_Settings_GetTemplates`. + + Args: + record_per_page: Total number of records to be retrieved in a page. + page_no: Page number to be retrieved. + sort_by: Sort by column. Possible Values are CREATED_ON and NAME. + Default is sort by CREATED_ON. + asc: The resulting list order. Default resulting list will be + descending. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7148,31 +9300,52 @@ async def settings_get_templates_async( query_params.append(f"asc={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def signature_add_signature_async( + def signature_add_signature( self, - input: DigitalSignatureFieldRequest, + input: DigitalSignatureFieldRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -7195,6 +9368,25 @@ async def signature_add_signature_async( information.Note if you have a document with a template applied, or have applied one using the APIs, then the workflow will already contain users. + + Swagger operation ID: `V4_Signature_AddSignature`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The package ID for which workflow details need to be + updated. + document_id: The document ID where the field is to be added. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7207,7 +9399,7 @@ async def signature_add_signature_async( f"/signature" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7221,6 +9413,7 @@ async def signature_add_signature_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7228,9 +9421,9 @@ async def signature_add_signature_async( return json.loads(response.text) - async def signature_update_signature_async( + def signature_update_signature( self, - input: UpdateDigitalSignatureFieldRequest, + input: UpdateDigitalSignatureFieldRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -7251,6 +9444,24 @@ async def signature_update_signature_async( Fields](#operation/Documents_GetDocumentFields).The latter can be used when a template was applied or the document was created using the GUI interface. + + Swagger operation ID: `V4_Signature_UpdateSignature`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7263,7 +9474,7 @@ async def signature_update_signature_async( f"/signature" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -7277,6 +9488,7 @@ async def signature_update_signature_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7284,9 +9496,9 @@ async def signature_update_signature_async( return json.loads(response.text) - async def signing_bulk_sign_documents_async( + def signing_bulk_sign_documents( self, - input: BulkSignRequest, + input: BulkSignRequest | Mapping[str, Any], package_id_bulk_action: str, *, timeout: Optional[float] = None, @@ -7334,13 +9546,31 @@ async def signing_bulk_sign_documents_async( applications must retrieve the OTP from the use and submit it when making the API call. This is done using the \"x-otp\" header in the request. + + Swagger operation ID: `V4_Signing_BulkSignDocuments`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id_bulk_action: Bulk action to be performed. Possible + values are: SIGN | SHARE. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id_bulk_action), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7354,6 +9584,7 @@ async def signing_bulk_sign_documents_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7361,9 +9592,9 @@ async def signing_bulk_sign_documents_async( return json.loads(response.text) - async def signing_bulk_sign_status_async( + def signing_bulk_sign_status( self, - input: BulkSignStatusRequest, + input: BulkSignStatusRequest | Mapping[str, Any], bulk_action: str, *, timeout: Optional[float] = None, @@ -7392,13 +9623,31 @@ async def signing_bulk_sign_status_async( signing process to complete the signing process on failed documents, the ACTION property will be REINITIATE_SIGNING_PROCESS, and the STATUS property will be PENDING. + + Swagger operation ID: `V4_Signing_BulkSignStatus`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + bulk_action: Bulk action to be performed. Possible values are: SIGN + | SHARE. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(bulk_action), safe='')}/status" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7412,6 +9661,7 @@ async def signing_bulk_sign_status_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7419,9 +9669,9 @@ async def signing_bulk_sign_status_async( return json.loads(response.text) - async def signing_sign_document_async( + def signing_sign_document( self, - input: SignDocumentRequest, + input: SignDocumentRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -7466,6 +9716,25 @@ async def signing_sign_document_async( business applications must retrieve the OTP from the use and submit it when making the API call. This is done using the \"x-otp\" header in the request. + + Swagger operation ID: `V4_Signing_SignDocument`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The identifier of the package that contains the + document for signature. + document_id: Identifier of the document to be signed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7477,7 +9746,7 @@ async def signing_sign_document_async( f"/sign" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7491,6 +9760,7 @@ async def signing_sign_document_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7498,19 +9768,19 @@ async def signing_sign_document_async( return json.loads(response.text) - async def template_get_enterprise_templates_async( + def list_template_get_enterprise_templates( self, record_per_page: int, page_no: int, + *, sort_by: Optional[str] = None, asc: Optional[bool] = None, id: Optional[List[int]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Enterprise Templates @@ -7519,6 +9789,29 @@ async def template_get_enterprise_templates_async( administrator or the enterprise user if the \"scope\" variable was used in the authentication request. It is possible to search based upon the criterion supplied under the \"x-search-text\" header. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `V4_Template_GetEnterpriseTemplates`. + + Args: + record_per_page: Total number of records to be retrieved in a page. + page_no: Page number to be retrieved. + sort_by: Sort the result by possible values are mentioned above. + asc: Order the result set by ascending or descending. + id: Search by template ids. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7557,31 +9850,52 @@ async def template_get_enterprise_templates_async( query_params.append(f"id={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def text_box_add_text_box_async( + return ItemPaged(get_next, extract_data) + + def text_box_add_text_box( self, - input: TextBoxFieldRequest, + input: TextBoxFieldRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -7603,6 +9917,24 @@ async def text_box_add_text_box_async( to Workflow](#operation/Workflow_WorkflowAddUser) for more information. Note if you have a document with a template applied, or have applied one using the APIs, then the workflow will already contain users. + + Swagger operation ID: `V4_TextBox_AddTextBox`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7615,7 +9947,7 @@ async def text_box_add_text_box_async( f"/text" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7629,6 +9961,7 @@ async def text_box_add_text_box_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7636,9 +9969,9 @@ async def text_box_add_text_box_async( return json.loads(response.text) - async def text_box_update_text_box_async( + def text_box_update_text_box( self, - input: UpdateTextBoxFieldRequest, + input: UpdateTextBoxFieldRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -7658,6 +9991,24 @@ async def text_box_update_text_box_async( Fields](#operation/Documents_GetDocumentFields). The latter can be used when a template was applied or the document was created using the GUI interface. + + Swagger operation ID: `V4_TextBox_UpdateTextBox`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: Package ID to which the document is added. + document_id: The document ID for which the action is to be taken. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7670,7 +10021,7 @@ async def text_box_update_text_box_async( f"/text" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -7684,6 +10035,7 @@ async def text_box_update_text_box_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7691,9 +10043,9 @@ async def text_box_update_text_box_async( return json.loads(response.text) - async def workflow_apply_template_async( + def workflow_apply_template( self, - input: ApplyTemplateRequest, + input: ApplyTemplateRequest | Mapping[str, Any], package_id: int, document_id: int, *, @@ -7722,6 +10074,27 @@ async def workflow_apply_template_async( applying such a template, these form fields will be created on the target document even if these form fields were already present in the document. + + Swagger operation ID: `V4_Workflow_ApplyTemplate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The Package ID of the package to which the template + needs to be applied. + document_id: The document ID on which the template needs to be + applied. If the value is set to 0, if template is to be applied + on all the documents in the package. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7733,7 +10106,7 @@ async def workflow_apply_template_async( f"/template" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7747,6 +10120,7 @@ async def workflow_apply_template_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7754,7 +10128,7 @@ async def workflow_apply_template_async( return json.loads(response.text) - async def workflow_evidence_report_download_bytes_async( + def workflow_evidence_report_download_bytes( self, package_id: int, *, @@ -7768,13 +10142,28 @@ async def workflow_evidence_report_download_bytes_async( Business applications can use this service API to download the workflow process evidence report of a document. + + Swagger operation ID: `V4_WorkflowEvidenceReport_DownloadBytes`. + + Args: + package_id: The ID of the document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/report" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7788,6 +10177,7 @@ async def workflow_evidence_report_download_bytes_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7795,7 +10185,7 @@ async def workflow_evidence_report_download_bytes_async( return json.loads(response.text) - async def workflow_get_workflow_detail_async( + def workflow_get_workflow_detail( self, package_id: int, *, @@ -7809,13 +10199,28 @@ async def workflow_get_workflow_detail_async( Business applications can use this service API to get workflow details for the package. + + Swagger operation ID: `V4_Workflow_GetWorkflowDetail`. + + Args: + package_id: The ID of the package to be downloaded. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/workflow" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7829,6 +10234,7 @@ async def workflow_get_workflow_detail_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7836,7 +10242,7 @@ async def workflow_get_workflow_detail_async( return json.loads(response.text) - async def workflow_get_workflow_history_async( + def workflow_get_workflow_history( self, package_id: int, page_no: int, @@ -7854,6 +10260,24 @@ async def workflow_get_workflow_history_async( of actions performed on a document. The package ID is provided in the resource URL. The search field (x-search-text header) is intended for email, document name, action, infokey, and infovalue. + + Swagger operation ID: `V4_Workflow_GetWorkflowHistory`. + + Args: + package_id: The ID of the document for which the log is required. + page_no: Page number to be retrieved. + records_per_page: Total number of records to be retrieved in a + page. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7865,7 +10289,7 @@ async def workflow_get_workflow_history_async( f"/{quote(str(records_per_page), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7879,6 +10303,7 @@ async def workflow_get_workflow_history_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7886,7 +10311,7 @@ async def workflow_get_workflow_history_async( return json.loads(response.text) - async def workflow_get_workflow_reminder_async( + def workflow_get_workflow_reminder( self, package_id: int, order: int, @@ -7906,6 +10331,24 @@ async def workflow_get_workflow_reminder_async( the workflow. The ID of the workflow document is provided in the resource URL, and the workflow recipient is identified by the order at which it is added to the workflow. + + Swagger operation ID: `V4_Workflow_GetWorkflowReminder`. + + Args: + package_id: The package ID for which workflow reminders to be + updated. + order: The order of the user for which the workflow reminders to be + updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7917,7 +10360,7 @@ async def workflow_get_workflow_reminder_async( f"/reminders" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7931,6 +10374,7 @@ async def workflow_get_workflow_reminder_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7938,7 +10382,7 @@ async def workflow_get_workflow_reminder_async( return json.loads(response.text) - async def workflow_get_workflow_users_async( + def list_workflow_get_workflow_users( self, package_id: int, *, @@ -7946,40 +10390,80 @@ async def workflow_get_workflow_users_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Workflow Users Business applications can use this service API to get workflow details for the package. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `V4_Workflow_GetWorkflowUsers`. + + Args: + package_id: The ID of the package to be downloaded. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/workflow/users" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def workflow_mark_workflow_completed_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def workflow_mark_workflow_completed( self, package_id: int, *, @@ -7999,13 +10483,29 @@ async def workflow_mark_workflow_completed_async( Bearer token should belong to document owner or enterprise admin can use scope variable to get the access token on behalf of document owner to perform this action. + + Swagger operation ID: `V4_Workflow_MarkWorkflowCompleted`. + + Args: + package_id: The package ID from which the recipient is to be + deleted. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/complete" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -8019,6 +10519,7 @@ async def workflow_mark_workflow_completed_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8026,7 +10527,7 @@ async def workflow_mark_workflow_completed_async( return json.loads(response.text) - async def workflow_permission_get_workflow_permissions_async( + def workflow_permission_get_workflow_permissions( self, package_id: int, order: int, @@ -8042,6 +10543,26 @@ async def workflow_permission_get_workflow_permissions_async( Business applications can use this service API to get document permissions for a recipient. Recipient is identified by the order in the workflow. The ID of the package is provided in the resource URL. + + Swagger operation ID: `V4_WorkflowPermission_GetWorkflowPermissions`. + + Args: + package_id: The document ID for which workflow user needs to be + updated. + order: The order of the user in workflow for which the permissions + are requested. By providing the value 0 in order, service would + return the permissions of most recently added collaborator in + the workflow. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8053,7 +10574,7 @@ async def workflow_permission_get_workflow_permissions_async( f"/permissions" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -8067,6 +10588,7 @@ async def workflow_permission_get_workflow_permissions_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8074,9 +10596,9 @@ async def workflow_permission_get_workflow_permissions_async( return json.loads(response.text) - async def workflow_permission_update_workflow_permissions_async( + def workflow_permission_update_workflow_permissions( self, - input: WorkflowPermissionsUpdateRequest, + input: WorkflowPermissionsUpdateRequest | Mapping[str, Any], package_id: int, order: int, *, @@ -8095,6 +10617,27 @@ async def workflow_permission_update_workflow_permissions_async( within the workflow. The ID of the document package is provided in the resource URL, and the workflow user is identified by the order at which it is added to the workflow. + + Swagger operation ID: + `V4_WorkflowPermission_UpdateWorkflowPermissions`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The package ID for which workflow permissions to be + updated. + order: The order of the recipient for which the workflow + permissions to be updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8106,7 +10649,7 @@ async def workflow_permission_update_workflow_permissions_async( f"/permissions" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -8120,6 +10663,7 @@ async def workflow_permission_update_workflow_permissions_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8127,7 +10671,7 @@ async def workflow_permission_update_workflow_permissions_async( return json.loads(response.text) - async def workflow_recall_workflow_async( + def workflow_recall_workflow( self, package_id: int, *, @@ -8142,13 +10686,28 @@ async def workflow_recall_workflow_async( Business applications can use this service API to stop a workflow in progress. The document ID is provided in the resource URL. After recall the document status automatically changes to \"DRAFT\". + + Swagger operation ID: `V4_Workflow_RecallWorkflow`. + + Args: + package_id: The ID of the package to be recalled. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/workflow" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -8162,6 +10721,7 @@ async def workflow_recall_workflow_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8169,7 +10729,7 @@ async def workflow_recall_workflow_async( return json.loads(response.text) - async def workflow_start_workflow_async( + def workflow_start_workflow( self, package_id: int, *, @@ -8186,13 +10746,28 @@ async def workflow_start_workflow_async( already have been prepared by applying a template and optionally updating the users and actions defined in template. The package ID to be shared is provided in the resource URL. + + Swagger operation ID: `V4_Workflow_StartWorkflow`. + + Args: + package_id: The document package to be shared. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/workflow" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -8206,6 +10781,7 @@ async def workflow_start_workflow_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8213,9 +10789,9 @@ async def workflow_start_workflow_async( return json.loads(response.text) - async def workflow_update_workflow_async( + def workflow_update_workflow( self, - input: WorkflowDetailUpdateRequest, + input: WorkflowDetailUpdateRequest | Mapping[str, Any], package_id: int, *, timeout: Optional[float] = None, @@ -8231,13 +10807,31 @@ async def workflow_update_workflow_async( to a document, but business applications wants to override the certify permission or post processing details. The package ID is provided in the resource URL. + + Swagger operation ID: `V4_Workflow_UpdateWorkflow`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The package ID for which workflow details need to be + updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/workflow" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -8251,6 +10845,7 @@ async def workflow_update_workflow_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8258,9 +10853,9 @@ async def workflow_update_workflow_async( return json.loads(response.text) - async def workflow_update_workflow_post_process_async( + def workflow_update_workflow_post_process( self, - input: PostProcessUpdateRequest, + input: PostProcessUpdateRequest | Mapping[str, Any], package_id: int, *, timeout: Optional[float] = None, @@ -8273,6 +10868,24 @@ async def workflow_update_workflow_post_process_async( Business applications can use this service API to add placeholder to a workflow a document in a package. + + Swagger operation ID: `V4_Workflow_UpdateWorkflowPostProcess`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: ID of the document package for which the post + processing is being updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8283,7 +10896,7 @@ async def workflow_update_workflow_post_process_async( f"/post_process" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -8297,6 +10910,7 @@ async def workflow_update_workflow_post_process_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8304,9 +10918,9 @@ async def workflow_update_workflow_post_process_async( return json.loads(response.text) - async def workflow_update_workflow_reminder_async( + def workflow_update_workflow_reminder( self, - input: UpdateReminderRequest, + input: UpdateReminderRequest | Mapping[str, Any], package_id: int, order: int, *, @@ -8325,6 +10939,26 @@ async def workflow_update_workflow_reminder_async( settings within the workflow. The ID of the workflow document is provided in the resource URL, and the workflow recipient is identified by the order at which it is added to the workflow. + + Swagger operation ID: `V4_Workflow_UpdateWorkflowReminder`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The package ID for which workflow reminders to be + updated. + order: The order of the user for which the workflow reminders to be + updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8336,7 +10970,7 @@ async def workflow_update_workflow_reminder_async( f"/reminders" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -8350,6 +10984,7 @@ async def workflow_update_workflow_reminder_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8357,7 +10992,7 @@ async def workflow_update_workflow_reminder_async( return json.loads(response.text) - async def workflow_workflow_add_group_async( + def workflow_workflow_add_group( self, input: WorkflowWorkflowAddGroupInput, package_id: int, @@ -8378,13 +11013,29 @@ async def workflow_workflow_add_group_async( user/group, already present in the workflow. While XML type document preparation, only supported role types are \"SIGNER\", \"REVIEWER\" and \"CARBON_COPY\" + + Swagger operation ID: `V4_Workflow_WorkflowAddGroup`. + + Args: + input: The request body. + package_id: ID of the package for which the group is to be added. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/workflow/groups" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -8398,6 +11049,7 @@ async def workflow_workflow_add_group_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8405,7 +11057,7 @@ async def workflow_workflow_add_group_async( return json.loads(response.text) - async def workflow_workflow_add_placeholder_async( + def workflow_workflow_add_placeholder( self, input: WorkflowWorkflowAddPlaceholderInput, package_id: int, @@ -8428,6 +11080,23 @@ async def workflow_workflow_add_placeholder_async( be assigned to individual users at a later stage. While XML type document preparation, only supported role types are \"SIGNER\", \"REVIEWER\" and \"CARBON_COPY\" + + Swagger operation ID: `V4_Workflow_WorkflowAddPlaceholder`. + + Args: + input: The request body. + package_id: ID of the package for which the placeholder is to be + added. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8438,7 +11107,7 @@ async def workflow_workflow_add_placeholder_async( f"/placeholder" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -8452,6 +11121,7 @@ async def workflow_workflow_add_placeholder_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8459,7 +11129,7 @@ async def workflow_workflow_add_placeholder_async( return json.loads(response.text) - async def workflow_workflow_add_user_async( + def workflow_workflow_add_user( self, input: WorkflowWorkflowAddUserInput, package_id: int, @@ -8500,13 +11170,30 @@ async def workflow_workflow_add_user_async( workflow; all in parallel order. Note, while XML type document preparation, only supported role types are \"SIGNER\", \"REVIEWER\" and \"CARBON_COPY\" + + Swagger operation ID: `V4_Workflow_WorkflowAddUser`. + + Args: + input: The request body. + package_id: SigningHub package ID, which the recipients are to be + added to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/packages/{quote(str(package_id), safe='')}/workflow/users" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -8520,6 +11207,7 @@ async def workflow_workflow_add_user_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8527,7 +11215,7 @@ async def workflow_workflow_add_user_async( return json.loads(response.text) - async def workflow_workflow_delete_user_async( + def workflow_workflow_delete_user( self, package_id: int, order: int, @@ -8542,6 +11230,24 @@ async def workflow_workflow_delete_user_async( Business applications can use this service API to delete workflow recipient. + + Swagger operation ID: `V4_Workflow_WorkflowDeleteUser`. + + Args: + package_id: The package ID from which the recipient is to be + deleted. + order: Order of the recipient in the workflow which is to be + deleted. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8552,7 +11258,7 @@ async def workflow_workflow_delete_user_async( f"/{quote(str(order), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -8566,6 +11272,7 @@ async def workflow_workflow_delete_user_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8573,9 +11280,9 @@ async def workflow_workflow_delete_user_async( return json.loads(response.text) - async def workflow_workflow_update_placeholder_async( + def workflow_workflow_update_placeholder( self, - input: WorkflowPlaceholderUpdateRequest, + input: WorkflowPlaceholderUpdateRequest | Mapping[str, Any], package_id: int, order: int, *, @@ -8595,6 +11302,25 @@ async def workflow_workflow_update_placeholder_async( place holder is identified by the order at which it is added to the workflow. While XML type document preparation, only supported role types are \"SIGNER\", \"REVIEWER\" and \"CARBON_COPY\" + + Swagger operation ID: `V4_Workflow_WorkflowUpdatePlaceholder`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: ID of the package for which the placeholder is to be + added. + order: Order of the recipient in the workflow. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8606,7 +11332,7 @@ async def workflow_workflow_update_placeholder_async( f"/placeholder" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -8620,6 +11346,7 @@ async def workflow_workflow_update_placeholder_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8627,9 +11354,9 @@ async def workflow_workflow_update_placeholder_async( return json.loads(response.text) - async def workflow_workflow_user_update_async( + def workflow_workflow_user_update( self, - input: WorkflowUserUpdateRequest, + input: WorkflowUserUpdateRequest | Mapping[str, Any], package_id: int, order: int, *, @@ -8650,6 +11377,25 @@ async def workflow_workflow_user_update_async( identified by the order at which it is added to the workflow. Note, while XML type document preparation, only supports role types \"SIGNER\", \"REVIEWER\" and \"CARBON_COPY\". + + Swagger operation ID: `V4_Workflow_WorkflowUserUpdate`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: The package ID for which workflow user needs to be + updated. + order: The order of the user in workflow. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8661,7 +11407,7 @@ async def workflow_workflow_user_update_async( f"/user" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -8675,6 +11421,7 @@ async def workflow_workflow_user_update_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8682,9 +11429,9 @@ async def workflow_workflow_user_update_async( return json.loads(response.text) - async def workflow_workflow_user_update_order_async( + def workflow_workflow_user_update_order( self, - input: WorkflowUserReorderRequest, + input: WorkflowUserReorderRequest | Mapping[str, Any], package_id: int, order: int, *, @@ -8698,6 +11445,25 @@ async def workflow_workflow_user_update_order_async( Business applications can use this service API to update order of the recipient in the workflow. + + Swagger operation ID: `V4_Workflow_WorkflowUserUpdateOrder`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + package_id: ID of the package to which the recipients are to be + added. + order: Existing order of the recipient which is to be updated. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -8709,7 +11475,7 @@ async def workflow_workflow_user_update_order_async( f"/reorder" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -8723,6 +11489,7 @@ async def workflow_workflow_user_update_order_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8730,7 +11497,7 @@ async def workflow_workflow_user_update_order_async( return json.loads(response.text) - async def work_space_delete_shared_space_async( + def work_space_delete_shared_space( self, id: int, *, @@ -8746,13 +11513,28 @@ async def work_space_delete_shared_space_async( The availability of deleting shared spaces is subject to the assigned enterprise user role. To allow this provision Enterprise Admin will enable the 'Manage Shared Space' option in Roles>Document Settings. + + Swagger operation ID: `V4_WorkSpace_DeleteSharedSpace`. + + Args: + id: Id of shared space that you want to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/shared_spaces/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -8766,6 +11548,7 @@ async def work_space_delete_shared_space_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8773,7 +11556,7 @@ async def work_space_delete_shared_space_async( return json.loads(response.text) - async def work_space_get_shared_space_async( + def work_space_get_shared_space( self, id: int, *, @@ -8788,13 +11571,28 @@ async def work_space_get_shared_space_async( Business applications can use this service API to get a specific shared space. This API returns information about shared space, its owner and collaborator. + + Swagger operation ID: `V4_WorkSpace_GetSharedSpace`. + + Args: + id: Id of shared space that you want to get. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/shared_spaces/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -8808,6 +11606,7 @@ async def work_space_get_shared_space_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -8815,9 +11614,9 @@ async def work_space_get_shared_space_async( return json.loads(response.text) - async def work_space_update_shared_space_async( + def work_space_update_shared_space( self, - input: UpdateWorkSpaceRequest, + input: UpdateWorkSpaceRequest | Mapping[str, Any], id: int, *, timeout: Optional[float] = None, @@ -8832,13 +11631,30 @@ async def work_space_update_shared_space_async( The availability of updating shared spaces is subject to the assigned enterprise user role. To allow this provision Enterprise Admin will enable the 'Manage Shared Space' option in Roles>Document Settings. + + Swagger operation ID: `V4_WorkSpace_UpdateSharedSpace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + id: Id of shared space that you want to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v4/shared_spaces/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -8852,6 +11668,7 @@ async def work_space_update_shared_space_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/slack.py b/src/azure/connectors/slack.py index 33333a2..117002a 100644 --- a/src/azure/connectors/slack.py +++ b/src/azure/connectors/slack.py @@ -5,21 +5,34 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "SlackClient", + "Channel", + "CreateChannelResponse", + "JoinChannelResponse", + "ListChannelsResponse", + "PostMessageRequest", + "PostMessageResponse", + "SetDNDResponse", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +42,7 @@ class SetDNDResponse: Response for Set do not disturb """ - snooze_enabled: Optional[bool] = None + snooze_enabled: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether snooze is enabled.""" @@ -39,7 +52,7 @@ class CreateChannelResponse: Response for Create a channel """ - channel: Optional[Channel] = None + channel: Optional[Channel | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -48,8 +61,8 @@ class JoinChannelResponse: Response for Join a public channel """ - channel: Optional[Channel] = None - warning: Optional[str] = None + channel: Optional[Channel | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + warning: Optional[str] = dataclass_field(default=None, kw_only=True) """Whether the user is already in the channel or not.""" @@ -59,9 +72,15 @@ class ListChannelsResponse: Response for List public channels (Pagination support) """ - value: Optional[List[Channel]] = None - next_link: Optional[str] = field( + value: Optional[ + List[Channel | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """Link to get next page of results""" @@ -73,15 +92,15 @@ class PostMessageResponse: Response for Post message """ - ok: Optional[bool] = None + ok: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates if the operation was successful.""" - channel: Optional[str] = None + channel: Optional[str] = dataclass_field(default=None, kw_only=True) """The channel which the message was posted to.""" - ts: Optional[str] = None + ts: Optional[str] = dataclass_field(default=None, kw_only=True) """Unix timestamp for when the message was created.""" - message: Optional[Dict[str, Any]] = None + message: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """A channel message.""" - error: Optional[str] = None + error: Optional[str] = dataclass_field(default=None, kw_only=True) """Details of the error messages, if any.""" @@ -91,9 +110,9 @@ class Channel: Definition: Channel """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The id of the channel.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of channel.""" @@ -103,40 +122,40 @@ class PostMessageRequest: Definition: PostMessageRequest """ - channel: Optional[str] = None + channel: str """ Channel, private group, or IM channel to send message to. Can be a name(ex: #general) or an encoded ID. """ - text: Optional[str] = None + text: str """ Body of the message to send. Slack API will truncate messages containing more than 40,000 characters. For formatting options, see https://api.slack.com/docs/formatting """ - username: Optional[str] = None + username: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the bot.""" - as_user: Optional[bool] = None + as_user: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Pass true to post the message as the authenticated user, instead of as a bot. """ - parse: Optional[str] = None + parse: Optional[str] = dataclass_field(default=None, kw_only=True) """ Change how messages are treated. For details, see https://api.slack.com/docs/formatting """ - mrkdwn: Optional[bool] = None + mrkdwn: Optional[bool] = dataclass_field(default=None, kw_only=True) """Slack markup parsing setting. Enabled by default.""" - link_names: Optional[int] = None + link_names: Optional[int] = dataclass_field(default=None, kw_only=True) """Find and link channel names and usernames.""" - unfurl_links: Optional[bool] = None + unfurl_links: Optional[bool] = dataclass_field(default=None, kw_only=True) """Pass true to enable unfurling of primarily text-based content.""" - unfurl_media: Optional[bool] = None + unfurl_media: Optional[bool] = dataclass_field(default=None, kw_only=True) """Pass false to disable unfurling of media content.""" - icon_url: Optional[str] = None + icon_url: Optional[str] = dataclass_field(default=None, kw_only=True) """URL to an image to use as an icon for this message.""" - icon_emoji: Optional[str] = None + icon_emoji: Optional[str] = dataclass_field(default=None, kw_only=True) """Emoji to use as an icon for this message.""" @@ -148,16 +167,16 @@ class SlackClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -168,8 +187,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -177,8 +196,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -190,7 +209,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -212,7 +231,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -244,10 +263,10 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def set_dnd_async( + def set_dnd( self, - num_minutes: Optional[str] = None, *, + num_minutes: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -257,6 +276,21 @@ async def set_dnd_async( Set do not disturb Set the do not disturb status for the user. + + Swagger operation ID: `SetDND`. + + Args: + num_minutes: The number of minutes to set do not disturb. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/dnd.setSnooze" query_params = [] @@ -268,7 +302,7 @@ async def set_dnd_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -282,6 +316,7 @@ async def set_dnd_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -289,11 +324,11 @@ async def set_dnd_async( return json.loads(response.text) - async def create_channel_async( + def create_channel( self, + *, name: Optional[str] = None, is_private: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -303,6 +338,22 @@ async def create_channel_async( Create a channel Create a channel in slack. + + Swagger operation ID: `CreateChannel_V2`. + + Args: + name: The name of the new channel. + is_private: Channel is private or not. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/conversations.create" query_params = [] @@ -319,7 +370,7 @@ async def create_channel_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -333,6 +384,7 @@ async def create_channel_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -340,10 +392,10 @@ async def create_channel_async( return json.loads(response.text) - async def join_channel_async( + def join_channel( self, - channel: Optional[str] = None, *, + channel: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -353,6 +405,21 @@ async def join_channel_async( Join a public channel Join a public channel in slack. + + Swagger operation ID: `JoinChannel_V2`. + + Args: + channel: The name of the channel. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/conversations.join" query_params = [] @@ -364,7 +431,7 @@ async def join_channel_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -378,6 +445,7 @@ async def join_channel_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -385,28 +453,50 @@ async def join_channel_async( return json.loads(response.text) - async def list_channels_async( + def list_channels( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ List public channels (Pagination support) List the public channels in slack. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListChannels_V3`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v3/conversations.list" + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -419,25 +509,34 @@ async def list_channels_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def post_message_async( + return ItemPaged(get_next, extract_data) + + def post_message( self, - input: PostMessageRequest, + input: PostMessageRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -448,10 +547,26 @@ async def post_message_async( Post message This operation is used to post a message to the specified channel. + + Swagger operation ID: `PostMessage_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/chat.postMessage" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -465,6 +580,7 @@ async def post_message_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/smtp.py b/src/azure/connectors/smtp.py index 6ea363c..231e038 100644 --- a/src/azure/connectors/smtp.py +++ b/src/azure/connectors/smtp.py @@ -5,12 +5,11 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, List, Any, Mapping -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, @@ -18,6 +17,12 @@ ConnectorResponseHook, ) +__all__ = [ + "SmtpClient", + "Attachment", + "Email", +] + # Type Definitions @@ -27,23 +32,19 @@ class Attachment: Definition: Attachment """ - content_data: Optional[str] = field( - default=None, - metadata={"wire_name": "ContentData"}, - ) + content_data: str = dataclass_field(metadata={"wire_name": "ContentData"}) """Content data""" - content_type: Optional[str] = field( - default=None, - metadata={"wire_name": "ContentType"}, - ) + content_type: str = dataclass_field(metadata={"wire_name": "ContentType"}) """Content type""" - file_name: Optional[str] = field( + file_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileName"}, ) """File name""" - content_id: Optional[str] = field( + content_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContentId"}, ) """Content id""" @@ -55,47 +56,72 @@ class Email: Definition: Email """ - from_: Optional[str] = field(default=None, metadata={"wire_name": "From"}) + from_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "From"}, + ) """Email address of sender like sender@domain.com""" - to: Optional[str] = field(default=None, metadata={"wire_name": "To"}) + to: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "To"}, + ) """ Specify email addresses separated by semicolons like recipient1@domain.com;recipient2@domain.com """ - c_c: Optional[str] = field(default=None, metadata={"wire_name": "CC"}) + c_c: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "CC"}, + ) """ Specify email addresses separated by semicolons like recipient1@domain.com;recipient2@domain.com """ - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Email subject""" - body: Optional[str] = field(default=None, metadata={"wire_name": "Body"}) + body: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Body"}, + ) """Email body""" - bcc: Optional[str] = field(default=None, metadata={"wire_name": "Bcc"}) + bcc: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Bcc"}, + ) """ Specify email addresses separated by semicolons like recipient1@domain.com;recipient2@domain.com. """ - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Importance of the email (High, Normal, or Low)""" - read_receipt: Optional[str] = field( + read_receipt: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReadReceipt"}, ) """Specify email address for Read receipt""" - delivery_receipt: Optional[str] = field( + delivery_receipt: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DeliveryReceipt"}, ) """Specify email address for Delivery receipt""" - attachments: Optional[List[Attachment]] = field( + attachments: Optional[List[Attachment | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """Attachments to be sent along with the email""" @@ -109,16 +135,16 @@ class SmtpClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -129,8 +155,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -138,8 +164,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -151,7 +177,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -166,9 +192,9 @@ def __init__( def connector_name(self) -> str: return "smtp" - async def send_email_async( + def send_email( self, - input: Email, + input: Email | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -179,10 +205,26 @@ async def send_email_async( Send Email This operation sends an email to one or more recipients. + + Swagger operation ID: `SendEmailV3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/SendEmailV3" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -196,4 +238,5 @@ async def send_email_async( request_url, response.status, response.text, + response=response, ) diff --git a/src/azure/connectors/sql.py b/src/azure/connectors/sql.py index 80776bb..737f000 100644 --- a/src/azure/connectors/sql.py +++ b/src/azure/connectors/sql.py @@ -5,21 +5,82 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "SqlClient", + "BlobDataSetsMetadata", + "DataSet", + "DataSetParameter", + "DataSetsList", + "DataSetsMetadata", + "DataWithSensitivityLabelInfo", + "Database", + "DatabasesList", + "DynamicTree", + "DynamicTreeOpenBrowse", + "DynamicTreeSettings", + "DynamicValues", + "ExecutePassThroughNativeQueryResponse", + "ExecuteProcedureInput", + "ExecuteProcedureResponse", + "GetItemResponse", + "GetItemsResponse", + "GetTablesResponse", + "Item", + "ItemsList", + "NoNaturalKeyColumnConnectorMetadata", + "ODataServersList", + "ObjectEntity", + "PQMetadata", + "PQMetadataValue", + "PQRows", + "PassThroughNativeQuery", + "PassThroughNativeQueryBody", + "PassThroughNativeQueryMetadata", + "PassThroughNativeQueryResult", + "PassThroughPQBody", + "PassThroughPQResult", + "PatchItemInput", + "PatchItemResponse", + "PostItemInput", + "PostItemResponse", + "Procedure", + "ProcedureMetadata", + "ProcedureResult", + "ProceduresList", + "SensitivityLabelMetadata", + "Server", + "SqlItem", + "SqlItemsList", + "SqlPassThroughNativeQueryBody", + "SqlPassThroughNativeQueryResult", + "Table", + "TableCapabilitiesMetadata", + "TableCountRestrictionsMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TablesList", + "TabularDataSetsMetadata", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +90,7 @@ class ExecutePassThroughNativeQueryResponse: Response for Execute a SQL query """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -42,7 +103,7 @@ class ExecuteProcedureInput: Execute stored procedure """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -55,7 +116,7 @@ class ExecuteProcedureResponse: Response for Execute stored procedure """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -68,7 +129,7 @@ class GetItemResponse: Response for Get row """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -81,15 +142,24 @@ class GetItemsResponse: Response for Get rows """ - metadata: Optional[List[DataWithSensitivityLabelInfo]] = field( + metadata: Optional[ + List[DataWithSensitivityLabelInfo | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@metadata"}, ) """List of Sensitivity Labels""" - value: Optional[List[SqlItem]] = None + value: Optional[ + List[SqlItem | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Columns""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -101,7 +171,12 @@ class SqlItemsList: Response for When an item is created """ - value: Optional[List[SqlItem]] = None + value: Optional[ + List[SqlItem | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Items""" @@ -111,12 +186,20 @@ class GetTablesResponse: Response for Get tables """ - metadata: Optional[List[DataWithSensitivityLabelInfo]] = field( + metadata: Optional[ + List[DataWithSensitivityLabelInfo | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@metadata"}, ) """List of Sensitivity Labels""" - value: Optional[List[Table]] = None + value: Optional[ + List[Table | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Tables""" @@ -126,7 +209,7 @@ class PatchItemInput: Update row """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -139,7 +222,7 @@ class PatchItemResponse: Response for Update row """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -152,7 +235,7 @@ class PostItemInput: Insert row """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -165,7 +248,7 @@ class PostItemResponse: Response for Insert row """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -178,7 +261,12 @@ class ODataServersList: Response for List the servers """ - value: Optional[List[Server]] = None + value: Optional[ + List[Server | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of datasets""" @@ -188,7 +276,12 @@ class DatabasesList: Response for List the databases """ - value: Optional[List[Database]] = None + value: Optional[ + List[Database | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of datasets""" @@ -198,10 +291,16 @@ class TablesList: Response for GetTablesForDeleteItem """ - value: Optional[List[Table]] = None + value: Optional[ + List[Table | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Tables""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -213,11 +312,11 @@ class PassThroughNativeQueryMetadata: Response for Get pass-through native SQL query metadata """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Query name""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Query title""" - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -226,7 +325,12 @@ class ProceduresList: Response for Get stored procedures """ - value: Optional[List[Procedure]] = None + value: Optional[ + List[Procedure | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Procedures""" @@ -236,11 +340,11 @@ class ProcedureMetadata: Response for Get metadata of a Procedure """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Procedure name""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Procedure title""" - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -249,26 +353,30 @@ class TableMetadata: Response for Get metadata of a table """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Table name""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Table title""" - x_ms_permission: Optional[str] = field( + x_ms_permission: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-permission"}, ) """Table permission""" - x_ms_capabilities: Optional[TableCapabilitiesMetadata] = field( + x_ms_capabilities: Optional[TableCapabilitiesMetadata | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-capabilities"}, ) - schema: Optional[ObjectEntity] = None - referenced_entities: Optional[ObjectEntity] = field( + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + referenced_entities: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "referencedEntities"}, ) - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webUrl"}, ) """Url link""" @@ -280,15 +388,17 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Blob dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Blob dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Blob dataset url encoding""" @@ -300,21 +410,32 @@ class Database: Definition: Database """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the database. The name is used at runtime.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the database.""" - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DynamicProperties"}, ) """ Additional database properties provided by the connector to the clients. """ - tables: Optional[List[Table]] = None + tables: Optional[ + List[Table | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Database items""" @@ -324,14 +445,24 @@ class DataSet: Definition: DataSet """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Dataset name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Dataset display name""" - query: Optional[List[PassThroughNativeQuery]] = None + query: Optional[ + List[PassThroughNativeQuery | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Pass-through Native Queries""" @@ -341,30 +472,38 @@ class DataSetParameter: Definition: DataSetParameter """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Type""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Parameter url encoding""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description""" - required: Optional[bool] = None + required: Optional[bool] = dataclass_field(default=None, kw_only=True) """Is parameter required""" - x_ms_summary: Optional[str] = field( + x_ms_summary: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-summary"}, ) """Summary""" - x_ms_dynamic_values: Optional[DynamicValues] = field( + x_ms_dynamic_values: Optional[DynamicValues | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-dynamic-values"}, ) - x_ms_dynamic_tree: Optional[DynamicTree] = field( + x_ms_dynamic_tree: Optional[DynamicTree | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-dynamic-tree"}, ) @@ -375,7 +514,12 @@ class DataSetsList: Definition: DataSetsList """ - value: Optional[List[DataSet]] = None + value: Optional[ + List[DataSet | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of datasets""" @@ -385,17 +529,36 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None - dataset_format: Optional[str] = field( + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + dataset_format: Optional[str] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "datasetFormat"}, ) """Dataset Format""" - parameters: Optional[List[DataSetParameter]] = None + parameters: Optional[ + List[DataSetParameter | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Parameters""" - no_natural_key_column_connector: Optional[NoNaturalKeyColumnConnectorMetadata] = field( + no_natural_key_column_connector: Optional[ + NoNaturalKeyColumnConnectorMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "noNaturalKeyColumnConnector"}, ) @@ -406,10 +569,13 @@ class DataWithSensitivityLabelInfo: Definition: DataWithSensitivityLabelInfo """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name""" - sensitivity_label_info: Optional[List[SensitivityLabelMetadata]] = field( + sensitivity_label_info: Optional[ + List[SensitivityLabelMetadata | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelInfo"}, ) """List of Sensitivity Label Information""" @@ -421,9 +587,24 @@ class DynamicTree: Definition: DynamicTree """ - settings: Optional[DynamicTreeSettings] = None - open: Optional[DynamicTreeOpenBrowse] = None - browse: Optional[DynamicTreeOpenBrowse] = None + settings: Optional[ + DynamicTreeSettings | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + open: Optional[ + DynamicTreeOpenBrowse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + browse: Optional[ + DynamicTreeOpenBrowse | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -432,30 +613,35 @@ class DynamicTreeOpenBrowse: Definition: DynamicTreeOpenBrowse """ - path: Optional[str] = None + path: Optional[str] = dataclass_field(default=None, kw_only=True) """Path""" - item_value_path: Optional[str] = field( + item_value_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "itemValuePath"}, ) """Item value path""" - item_title_path: Optional[str] = field( + item_title_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "itemTitlePath"}, ) """Item title path""" - item_full_title_path: Optional[str] = field( + item_full_title_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "itemFullTitlePath"}, ) """Item full title path""" - item_is_parent: Optional[str] = field( + item_is_parent: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "itemIsParent"}, ) """Is item parent""" - selectable_filter: Optional[str] = field( + selectable_filter: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selectableFilter"}, ) """Selectable filter""" @@ -467,18 +653,21 @@ class DynamicTreeSettings: Definition: DynamicTreeSettings """ - can_select_parent_nodes: Optional[bool] = field( + can_select_parent_nodes: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "canSelectParentNodes"}, ) """Can select parent nodes""" - can_select_leaf_nodes: Optional[bool] = field( + can_select_leaf_nodes: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "canSelectLeafNodes"}, ) """Can select leaf nodes""" - selected_item_placeholder: Optional[str] = field( + selected_item_placeholder: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selectedItemPlaceholder"}, ) """Selected item placeholder in the path""" @@ -490,20 +679,23 @@ class DynamicValues: Definition: DynamicValues """ - path: Optional[str] = None + path: Optional[str] = dataclass_field(default=None, kw_only=True) """Path""" - value_collection: Optional[str] = field( + value_collection: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "value-collection"}, ) """Value collection""" - value_path: Optional[str] = field( + value_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "value-path"}, ) """Value path""" - value_title: Optional[str] = field( + value_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "value-title"}, ) """Value title""" @@ -515,8 +707,9 @@ class Item: Definition: Item """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) @@ -527,7 +720,12 @@ class ItemsList: Definition: ItemsList """ - value: Optional[List[Item]] = None + value: Optional[ + List[Item | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of Items""" @@ -537,18 +735,21 @@ class NoNaturalKeyColumnConnectorMetadata: Definition: NoNaturalKeyColumnConnectorMetadata """ - create_key_column_path: Optional[str] = field( + create_key_column_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createKeyColumnPath"}, ) """Path to create key column""" - create_key_column_method: Optional[str] = field( + create_key_column_method: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createKeyColumnMethod"}, ) """Method to create key column""" - key_column_name_url_encoding: Optional[str] = field( + key_column_name_url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "keyColumnNameUrlEncoding"}, ) """Key column name url encoding""" @@ -560,7 +761,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -573,8 +774,9 @@ class PassThroughNativeQuery: Definition: PassThroughNativeQuery """ - language: Optional[str] = field( + language: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Language"}, ) """Query language""" @@ -586,15 +788,17 @@ class PassThroughNativeQueryBody: Definition: PassThroughNativeQueryBody """ - query: Optional[str] = None + query: Optional[str] = dataclass_field(default=None, kw_only=True) """Query Text""" - formal_parameters: Optional[Dict[str, str]] = field( + formal_parameters: Optional[Dict[str, str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "formalParameters"}, ) """Formal Parameters""" - actual_parameters: Optional[Dict[str, ObjectEntity]] = field( + actual_parameters: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "actualParameters"}, ) """Actual parameters""" @@ -606,13 +810,17 @@ class PassThroughNativeQueryResult: Definition: PassThroughNativeQueryResult """ - output_parameters: Optional[Dict[str, ObjectEntity]] = field( + output_parameters: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OutputParameters"}, ) """Output parameter values""" - result_sets: Optional[Dict[str, List[Dict[str, ObjectEntity]]]] = field( + result_sets: Optional[ + Dict[str, List[Dict[str, ObjectEntity | Mapping[str, Any]]]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultSets"}, ) """Collection of all result sets""" @@ -624,10 +832,15 @@ class Procedure: Definition: Procedure """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """Procedure name""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """Procedure display name""" @@ -639,20 +852,25 @@ class ProcedureResult: Definition: ProcedureResult """ - output_parameters: Optional[Dict[str, ObjectEntity]] = field( + output_parameters: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OutputParameters"}, ) """ Output parameter values. The schema is dynamic based on the procedure. """ - return_code: Optional[int] = field( + return_code: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReturnCode"}, ) """Return code of a procedure.""" - result_sets: Optional[Dict[str, List[Dict[str, ObjectEntity]]]] = field( + result_sets: Optional[ + Dict[str, List[Dict[str, ObjectEntity | Mapping[str, Any]]]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultSets"}, ) """ @@ -667,41 +885,47 @@ class SensitivityLabelMetadata: Definition: SensitivityLabelMetadata """ - sensitivity_label_id: Optional[str] = field( + sensitivity_label_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sensitivityLabelId"}, ) """SensitivityLabel Id.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel name.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """SensitivityLabel displayName info""" - tooltip: Optional[str] = None + tooltip: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel details on tooltip.""" - priority: Optional[int] = None + priority: Optional[int] = dataclass_field(default=None, kw_only=True) """SensitivityLabel priority.""" - color: Optional[str] = None + color: Optional[str] = dataclass_field(default=None, kw_only=True) """SensitivityLabel color.""" - is_encrypted: Optional[bool] = field( + is_encrypted: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEncrypted"}, ) """ is SensitivityLabel Encrypted.""" - is_enabled: Optional[bool] = field( + is_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEnabled"}, ) """Whether SensitivityLabel is Enabled.""" - is_parent: Optional[bool] = field( + is_parent: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isParent"}, ) """Whether SensitivityLabel is Parent.""" - parent_sensitivity_label_id: Optional[str] = field( + parent_sensitivity_label_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentSensitivityLabelId"}, ) """Parent SensitivityLabel Id.""" @@ -713,21 +937,32 @@ class Server: Definition: Server """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the server. The name is used at runtime.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the server.""" - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DynamicProperties"}, ) """ Additional server properties provided by the connector to the clients. """ - databases: Optional[List[Database]] = None + databases: Optional[ + List[Database | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Table items""" @@ -737,8 +972,9 @@ class SqlItem: Definition: SqlItem """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) @@ -749,15 +985,17 @@ class SqlPassThroughNativeQueryBody: Definition: SqlPassThroughNativeQueryBody """ - actual_parameters: Optional[Dict[str, ObjectEntity]] = field( + actual_parameters: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "actualParameters"}, ) """Actual parameters""" - query: Optional[str] = None + query: Optional[str] = dataclass_field(default=None, kw_only=True) """Query Text""" - formal_parameters: Optional[Dict[str, str]] = field( + formal_parameters: Optional[Dict[str, str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "formalParameters"}, ) """Formal Parameters""" @@ -769,13 +1007,17 @@ class SqlPassThroughNativeQueryResult: Definition: SqlPassThroughNativeQueryResult """ - output_parameters: Optional[Dict[str, ObjectEntity]] = field( + output_parameters: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OutputParameters"}, ) """Output parameter values""" - result_sets: Optional[Dict[str, List[Dict[str, ObjectEntity]]]] = field( + result_sets: Optional[ + Dict[str, List[Dict[str, ObjectEntity | Mapping[str, Any]]]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResultSets"}, ) """Collection of all result sets""" @@ -787,15 +1029,21 @@ class Table: Definition: Table """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the table. The name is used at runtime.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the table.""" - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DynamicProperties"}, ) """Additional table properties provided by the connector to the clients.""" @@ -807,34 +1055,49 @@ class TableCapabilitiesMetadata: Definition: TableCapabilitiesMetadata """ - sort_restrictions: Optional[TableSortRestrictionsMetadata] = field( + sort_restrictions: Optional[ + TableSortRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sortRestrictions"}, ) - filter_restrictions: Optional[TableFilterRestrictionsMetadata] = field( + filter_restrictions: Optional[ + TableFilterRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterRestrictions"}, ) - select_restrictions: Optional[TableSelectRestrictionsMetadata] = field( + select_restrictions: Optional[ + TableSelectRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selectRestrictions"}, ) - count_restrictions: Optional[TableCountRestrictionsMetadata] = field( + count_restrictions: Optional[ + TableCountRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "countRestrictions"}, ) - is_only_server_pagable: Optional[bool] = field( + is_only_server_pagable: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isOnlyServerPagable"}, ) """Server paging restrictions""" - filter_function_support: Optional[List[str]] = field( + filter_function_support: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterFunctionSupport"}, ) """List of supported filter capabilities""" - server_paging_options: Optional[List[str]] = field( + server_paging_options: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "serverPagingOptions"}, ) """List of supported server-driven paging capabilities""" @@ -846,15 +1109,17 @@ class TableFilterRestrictionsMetadata: Definition: TableFilterRestrictionsMetadata """ - filterable: Optional[bool] = None + filterable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has filterable columns""" - non_filterable_properties: Optional[List[str]] = field( + non_filterable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nonFilterableProperties"}, ) """List of non filterable properties""" - required_properties: Optional[List[str]] = field( + required_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredProperties"}, ) """List of required properties""" @@ -866,7 +1131,7 @@ class TableSelectRestrictionsMetadata: Definition: TableSelectRestrictionsMetadata """ - selectable: Optional[bool] = None + selectable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has selectable columns""" @@ -876,7 +1141,7 @@ class TableCountRestrictionsMetadata: Definition: TableCountRestrictionsMetadata """ - countable: Optional[bool] = None + countable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has countable columns""" @@ -886,15 +1151,17 @@ class TableSortRestrictionsMetadata: Definition: TableSortRestrictionsMetadata """ - sortable: Optional[bool] = None + sortable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has sortable columns""" - unsortable_properties: Optional[List[str]] = field( + unsortable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "unsortableProperties"}, ) """List of unsortable properties""" - ascending_only_properties: Optional[List[str]] = field( + ascending_only_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ascendingOnlyProperties"}, ) """List of properties which support ascending order only""" @@ -906,25 +1173,29 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """Dataset source""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Dataset display name""" - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) """Dataset url encoding""" - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) """Table display name""" - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) """Table plural display name""" @@ -936,7 +1207,7 @@ class PassThroughPQBody: Definition: PassThroughPQBody """ - query: Optional[str] = None + query: Optional[str] = dataclass_field(default=None, kw_only=True) """Query Text""" @@ -946,9 +1217,15 @@ class PQMetadata: Definition: PQMetadata """ - value: Optional[PQMetadataValue] = None - result_type: Optional[str] = field( + value: Optional[ + PQMetadataValue | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + result_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resultType"}, ) """Result Type""" @@ -960,11 +1237,11 @@ class PQMetadataValue: Definition: PQMetadataValue """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Query name""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Query title""" - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -973,7 +1250,7 @@ class PassThroughPQResult: Definition: PassThroughPQResult """ - value: Optional[PQRows] = None + value: Optional[PQRows | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -982,7 +1259,7 @@ class PQRows: Definition: PQRows """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -997,16 +1274,16 @@ class SqlClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -1017,8 +1294,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -1026,8 +1303,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -1039,7 +1316,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -1061,7 +1338,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -1093,7 +1370,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def delete_item_async( + def delete_item( self, server: str, database: str, @@ -1109,6 +1386,24 @@ async def delete_item_async( Delete row This operation deletes a row from a table. + + Swagger operation ID: `DeleteItem_V2`. + + Args: + server: Name of SQL server. + database: Database name. + table: Name of table. + id: Unique identifier of the row to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1124,7 +1419,7 @@ async def delete_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1138,11 +1433,12 @@ async def delete_item_async( request_url, response.status, response.text, + response=response, ) - async def execute_pass_through_native_query_async( + def execute_pass_through_native_query( self, - input: SqlPassThroughNativeQueryBody, + input: SqlPassThroughNativeQueryBody | Mapping[str, Any], server: str, database: str, *, @@ -1155,6 +1451,24 @@ async def execute_pass_through_native_query_async( Execute a SQL query Execute a SQL query + + Swagger operation ID: `ExecutePassThroughNativeQuery_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1168,7 +1482,7 @@ async def execute_pass_through_native_query_async( f"/sql" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1182,6 +1496,7 @@ async def execute_pass_through_native_query_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1189,9 +1504,9 @@ async def execute_pass_through_native_query_async( return json.loads(response.text) - async def execute_procedure_async( + def execute_procedure( self, - input: ExecuteProcedureInput, + input: ExecuteProcedureInput | Mapping[str, Any], server: str, database: str, procedure: str, @@ -1205,6 +1520,25 @@ async def execute_procedure_async( Execute stored procedure This operation runs a stored procedure. + + Swagger operation ID: `ExecuteProcedure_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + server: Name of SQL server. + database: Database name. + procedure: Name of stored procedure. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1218,7 +1552,7 @@ async def execute_procedure_async( f"/{quote(quote(str(procedure), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1232,6 +1566,7 @@ async def execute_procedure_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1239,7 +1574,7 @@ async def execute_procedure_async( return json.loads(response.text) - async def get_item_async( + def get_item( self, server: str, database: str, @@ -1255,6 +1590,24 @@ async def get_item_async( Get row This operation gets a row from a table. + + Swagger operation ID: `GetItem_V2`. + + Args: + server: Name of SQL server. + database: Database name. + table: Name of SQL table. + id: Unique identifier of the row to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1270,7 +1623,7 @@ async def get_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1284,6 +1637,7 @@ async def get_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1291,11 +1645,12 @@ async def get_item_async( return json.loads(response.text) - async def get_items_async( + def list_items( self, server: str, database: str, table: str, + *, apply: Optional[str] = None, filter: Optional[str] = None, orderby: Optional[str] = None, @@ -1305,19 +1660,49 @@ async def get_items_async( count: Optional[bool] = None, extract_sensitivity_label: Optional[bool] = None, purview_account_name: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get rows This operation gets rows from a table. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItems_V2`. + + Args: + server: Name of SQL server. + database: Database name. + table: Name of SQL table. + apply: A sequence of OData aggregation transformations. + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + skip: The number of entries to skip (default = 0). + top: Total number of entries to retrieve (default = all). + select: Specific fields to retrieve from entries (default = all). + count: Option to specify if only total entity count should be + returned in the query (default = false). + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1379,11 +1764,18 @@ async def get_items_async( query_params.append(f"purviewAccountName={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1396,38 +1788,70 @@ async def get_items_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def get_tables_async( + def list_tables( self, server: str, database: str, + *, extract_sensitivity_label: Optional[bool] = None, purview_account_name: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get tables This operation gets tables from a database. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTables_V2`. + + Args: + server: Name of SQL server. + database: Database name. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1452,31 +1876,52 @@ async def get_tables_async( query_params.append(f"purviewAccountName={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def patch_item_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def patch_item( self, - input: PatchItemInput, + input: PatchItemInput | Mapping[str, Any], server: str, database: str, table: str, @@ -1491,6 +1936,26 @@ async def patch_item_async( Update row This operation updates an existing row in a table. + + Swagger operation ID: `PatchItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + server: Name of SQL server. + database: Database name. + table: Name of table. + id: Unique identifier of the row to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1506,7 +1971,7 @@ async def patch_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -1520,6 +1985,7 @@ async def patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1527,9 +1993,9 @@ async def patch_item_async( return json.loads(response.text) - async def post_item_async( + def post_item( self, - input: PostItemInput, + input: PostItemInput | Mapping[str, Any], server: str, database: str, table: str, @@ -1543,6 +2009,25 @@ async def post_item_async( Insert row This operation inserts a new row into a table. + + Swagger operation ID: `PostItem_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + server: Name of SQL server. + database: Database name. + table: Name of table. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1557,7 +2042,7 @@ async def post_item_async( f"/items" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1571,6 +2056,7 @@ async def post_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1578,43 +2064,82 @@ async def post_item_async( return json.loads(response.text) - async def get_servers_async( + def list_servers( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List the servers List the servers + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetServers`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/servers" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def get_databases_async( + return ItemPaged(get_next, extract_data) + + def list_databases( self, server: str, *, @@ -1622,11 +2147,30 @@ async def get_databases_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List the databases List the databases + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetDatabases`. + + Args: + server: Server name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/databases" query_params = [] @@ -1636,29 +2180,50 @@ async def get_databases_async( query_params.append(f"server={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def get_tables_for_delete_item_async( + return ItemPaged(get_next, extract_data) + + def list_tables_for_delete_item( self, server: str, database: str, @@ -1667,14 +2232,31 @@ async def get_tables_for_delete_item_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ GetTablesForDeleteItem GetTablesForDeleteItem - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTablesForDeleteItem_V2`. + + Args: + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1687,11 +2269,18 @@ async def get_tables_for_delete_item_async( f"/tablesfor" f"/deleteitem" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1704,25 +2293,34 @@ async def get_tables_for_delete_item_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def get_pass_through_native_query_metadata_async( + def get_pass_through_native_query_metadata( self, - input: SqlPassThroughNativeQueryBody, + input: SqlPassThroughNativeQueryBody | Mapping[str, Any], server: str, database: str, *, @@ -1735,6 +2333,24 @@ async def get_pass_through_native_query_metadata_async( Get pass-through native SQL query metadata Retrieves metadata for a pass-through native SQL query. + + Swagger operation ID: `GetPassThroughNativeQueryMetadata_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1749,7 +2365,7 @@ async def get_pass_through_native_query_metadata_async( f"/sql" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1763,6 +2379,7 @@ async def get_pass_through_native_query_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1770,7 +2387,7 @@ async def get_pass_through_native_query_metadata_async( return json.loads(response.text) - async def get_procedures_v2_async( + def list_procedures_v2( self, server: str, database: str, @@ -1779,11 +2396,31 @@ async def get_procedures_v2_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get stored procedures This operation gets stored procedures for a database. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetProcedures_V2`. + + Args: + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1795,29 +2432,50 @@ async def get_procedures_v2_async( f"{quote(quote(str(database), safe=''), safe='')}" f"/procedures" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_procedure_v2_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_procedure_v2( self, server: str, database: str, @@ -1832,6 +2490,23 @@ async def get_procedure_v2_async( Get metadata of a Procedure Get metadata of a Procedure. + + Swagger operation ID: `GetProcedure_V2`. + + Args: + server: Name of SQL server. + database: Database name. + procedure: Procedure name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1846,7 +2521,7 @@ async def get_procedure_v2_async( f"/{quote(quote(str(procedure), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1860,6 +2535,7 @@ async def get_procedure_v2_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1867,7 +2543,7 @@ async def get_procedure_v2_async( return json.loads(response.text) - async def get_tables_for_get_item_async( + def list_tables_for_get_item( self, server: str, database: str, @@ -1876,14 +2552,31 @@ async def get_tables_for_get_item_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ GetTablesForGetItem GetTablesForGetItem - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTablesForGetItem_V2`. + + Args: + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1896,11 +2589,18 @@ async def get_tables_for_get_item_async( f"/tablesfor" f"/getitem" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1913,30 +2613,39 @@ async def get_tables_for_get_item_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_table_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def get_table( self, server: str, database: str, table: str, + *, extract_sensitivity_label: Optional[bool] = None, purview_account_name: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1946,6 +2655,26 @@ async def get_table_async( Get metadata of a table Get metadata of a table. + + Swagger operation ID: `GetTable_V2`. + + Args: + server: Name of SQL server. + database: Database name. + table: table name. + extract_sensitivity_label: Specify whether to extract MIP labels. + purview_account_name: Default collection will be queried unless + specified. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1973,7 +2702,7 @@ async def get_table_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1987,6 +2716,7 @@ async def get_table_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1994,7 +2724,7 @@ async def get_table_async( return json.loads(response.text) - async def get_tables_for_get_on_new_items_async( + def list_tables_for_get_on_new_items( self, server: str, database: str, @@ -2003,14 +2733,31 @@ async def get_tables_for_get_on_new_items_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ GetTablesForOnItemCreated GetTablesForOnItemCreated - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTablesForGetOnNewItems_V2`. + + Args: + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2023,11 +2770,18 @@ async def get_tables_for_get_on_new_items_async( f"/tablesfor" f"/getonnewitems" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2040,23 +2794,32 @@ async def get_tables_for_get_on_new_items_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def get_tables_for_get_on_updated_items_async( + def list_tables_for_get_on_updated_items( self, server: str, database: str, @@ -2065,14 +2828,31 @@ async def get_tables_for_get_on_updated_items_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ GetTablesForOnItemUpdated GetTablesForOnItemUpdated - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTablesForGetOnUpdatedItems_V2`. + + Args: + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2085,11 +2865,18 @@ async def get_tables_for_get_on_updated_items_async( f"/tablesfor" f"/getonupdateditems" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2102,23 +2889,32 @@ async def get_tables_for_get_on_updated_items_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def get_tables_for_patch_item_async( + def list_tables_for_patch_item( self, server: str, database: str, @@ -2127,14 +2923,31 @@ async def get_tables_for_patch_item_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ GetTablesForPatchItem GetTablesForPatchItem - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTablesForPatchItem_V2`. + + Args: + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2147,11 +2960,18 @@ async def get_tables_for_patch_item_async( f"/tablesfor" f"/patchitem" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2164,23 +2984,32 @@ async def get_tables_for_patch_item_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_table_for_patch_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def get_table_for_patch( self, server: str, database: str, @@ -2195,6 +3024,23 @@ async def get_table_for_patch_async( Get metadata of a table for Patch operation Get metadata of a table for Patch operation. + + Swagger operation ID: `GetTableForPatch_V2`. + + Args: + server: Name of SQL server. + database: Database name. + table: table name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2210,7 +3056,7 @@ async def get_table_for_patch_async( f"/forPatchItem" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2224,6 +3070,7 @@ async def get_table_for_patch_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2231,7 +3078,7 @@ async def get_table_for_patch_async( return json.loads(response.text) - async def get_tables_for_post_item_async( + def list_tables_for_post_item( self, server: str, database: str, @@ -2240,14 +3087,31 @@ async def get_tables_for_post_item_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ GetTablesForPostItem GetTablesForPostItem - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTablesForPostItem_V2`. + + Args: + server: Name of SQL server. + database: Database name. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2260,11 +3124,18 @@ async def get_tables_for_post_item_async( f"/tablesfor" f"/postitem" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2277,23 +3148,32 @@ async def get_tables_for_post_item_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_procedure_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def get_procedure( self, procedure: str, *, @@ -2306,6 +3186,21 @@ async def get_procedure_async( Get procedure metadata This operation gets metadata for a stored procedure. + + Swagger operation ID: `GetProcedure`. + + Args: + procedure: Name of stored procedure. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2316,7 +3211,7 @@ async def get_procedure_async( f"/{quote(quote(str(procedure), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2330,6 +3225,7 @@ async def get_procedure_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2337,43 +3233,82 @@ async def get_procedure_async( return json.loads(response.text) - async def get_procedures_async( + def list_procedures( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get stored procedures This operation gets stored procedures for a database. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetProcedures`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/datasets/default/procedures" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/starmind.py b/src/azure/connectors/starmind.py index 4e0e0b0..b196d4d 100644 --- a/src/azure/connectors/starmind.py +++ b/src/azure/connectors/starmind.py @@ -5,14 +5,13 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, Dict, List, Literal, Any, Mapping from urllib.parse import quote import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, @@ -20,6 +19,31 @@ ConnectorResponseHook, ) +__all__ = [ + "StarmindClient", + "Attachment", + "Comment", + "ConceptLabelMatch", + "ExpertConceptScores", + "FindExpertsInput", + "FindExpertsResponse", + "FindQuestionsResponse", + "GraphQLError", + "GraphQLUserResponse", + "KnowledgeSpace", + "Language", + "PostQuestionDraftInput", + "PublishQuestionDraftResponse", + "Question", + "QuestionComplete", + "Solution", + "SolutionAuthorityApproval", + "SolutionValidation", + "User", + "UserId", + "UserLegacy", +] + # Type Definitions @@ -29,8 +53,8 @@ class FindExpertsInput: Find experts """ - language: Optional[Language] = None - text_query: Optional[str] = None + language: Optional[Language] = dataclass_field(default=None, kw_only=True) + text_query: str """ Primary search text to identify experts. Can be a question, a summary of a text, one or multiple topics. @@ -43,12 +67,17 @@ class FindExpertsResponse: Response for Find experts """ - experts: Optional[List[Dict[str, Any]]] = None + experts: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """ List of experts matching the search query. May be empty if no experts are found. """ - label_matches: Optional[List[ConceptLabelMatch]] = None + label_matches: Optional[ + List[ConceptLabelMatch | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """ The matched labels for the expert search query. May be empty if no labels match. @@ -61,14 +90,20 @@ class FindQuestionsResponse: Response for Find questions """ - links: Optional[Dict[str, Any]] = field( + links: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) """_links""" - items: Optional[List[Question]] = None + items: Optional[ + List[Question | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Paginated results of the question search.""" - total: Optional[int] = None + total: Optional[int] = dataclass_field(default=None, kw_only=True) """Total number of questions matching the request.""" @@ -78,8 +113,13 @@ class GraphQLUserResponse: Response for Get user by id """ - data: Optional[Dict[str, Any]] = None - errors: Optional[List[GraphQLError]] = None + data: Dict[str, Any] + errors: Optional[ + List[GraphQLError | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Optional array of GraphQL errors; only present if errors occurred""" @@ -89,22 +129,22 @@ class PostQuestionDraftInput: Create a question draft """ - category: Optional[int] = None + category: Optional[int] = dataclass_field(default=None, kw_only=True) """The optional id of the category to assign the question draft to""" - title: Optional[str] = None + title: str """ Question title, Between 4 and 100 characters by default. Depending on the network configuration the title max length may be limited or extended further. """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """ The optional question description providing detailed context and information about the question. Depending on the network configuration the description might be enforced to be non-empty. """ - language: Optional[Language] = None - knowledge_space: Optional[int] = None + language: Optional[Language] = dataclass_field(default=None, kw_only=True) + knowledge_space: Optional[int] = dataclass_field(default=None, kw_only=True) """the id of the knowledge space to assign the question to""" @@ -114,63 +154,63 @@ class Question: Response for Create a question draft """ - knowledge_space_id: Optional[int] = None + knowledge_space_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The unique knowledge space id to which the question belongs.""" - upvote_count: Optional[int] = None + upvote_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The total number of upvotes the question has received.""" - view_count: Optional[int] = None + view_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of times the question has been viewed by users.""" - published: Optional[str] = None + published: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the question was published (yyyy-MM-ddTHH:mm:ss.fffZ) """ - is_deleted: Optional[bool] = None + is_deleted: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Indicates if the question is deleted. Deleted questions are not visible to users, but can still be accessed by the administrators. """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The question title""" - last_activity: Optional[str] = None + last_activity: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating the last activity with the question (yyyy-MM-ddTHH:mm:ss.fffZ) """ - is_published: Optional[bool] = None + is_published: Optional[bool] = dataclass_field(default=None, kw_only=True) """ The question is_published flag indicates whether the question is published or not. A published solution is visible to all users, while an unpublished solution is in draft state only visible to the author. """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the question was created (yyyy-MM-ddTHH:mm:ss.fffZ) """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """ Question description providing detailed context and information about the question """ - solution_count: Optional[int] = None + solution_count: Optional[int] = dataclass_field(default=None, kw_only=True) """ This is the number of solutions that have been provided for this question. """ - content_updated: Optional[str] = None + content_updated: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the question's content or attachments were last updated (yyyy-MM-ddTHH:mm:ss.fffZ) """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The unique question id""" - updated: Optional[str] = None + updated: Optional[str] = dataclass_field(default=None, kw_only=True) """ Last time the resource has been updated in the DB. This date does not reflect content updates but any update to any fields of the record. Use content_updated for information about content updates. """ - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The question language""" @@ -180,7 +220,7 @@ class PublishQuestionDraftResponse: Response for Publish a question """ - number_of_experts: Optional[int] = None + number_of_experts: Optional[int] = dataclass_field(default=None, kw_only=True) """number_of_experts""" @@ -190,75 +230,100 @@ class QuestionComplete: Definition: QuestionComplete """ - knowledge_space_id: Optional[int] = None + knowledge_space_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The unique knowledge space id to which the question belongs.""" - upvote_count: Optional[int] = None + upvote_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The total number of upvotes the question has received.""" - view_count: Optional[int] = None + view_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of times the question has been viewed by users.""" - published: Optional[str] = None + published: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the question was published (yyyy-MM-ddTHH:mm:ss.fffZ) """ - is_deleted: Optional[bool] = None + is_deleted: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Indicates if the question is deleted. Deleted questions are not visible to users, but can still be accessed by the administrators. """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The question title""" - last_activity: Optional[str] = None + last_activity: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating the last activity with the question (yyyy-MM-ddTHH:mm:ss.fffZ) """ - is_published: Optional[bool] = None + is_published: Optional[bool] = dataclass_field(default=None, kw_only=True) """ The question is_published flag indicates whether the question is published or not. A published solution is visible to all users, while an unpublished solution is in draft state only visible to the author. """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the question was created (yyyy-MM-ddTHH:mm:ss.fffZ) """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """ Question description providing detailed context and information about the question """ - solution_count: Optional[int] = None + solution_count: Optional[int] = dataclass_field(default=None, kw_only=True) """ This is the number of solutions that have been provided for this question. """ - content_updated: Optional[str] = None + content_updated: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the question's content or attachments were last updated (yyyy-MM-ddTHH:mm:ss.fffZ) """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The unique question id""" - updated: Optional[str] = None + updated: Optional[str] = dataclass_field(default=None, kw_only=True) """ Last time the resource has been updated in the DB. This date does not reflect content updates but any update to any fields of the record. Use content_updated for information about content updates. """ - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The question language""" - source: Optional[str] = None + source: Optional[str] = dataclass_field(default=None, kw_only=True) """source""" - concepts: Optional[List[ConceptLabelMatch]] = None + concepts: Optional[ + List[ConceptLabelMatch | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The assigned question concepts""" - knowledge_space: Optional[KnowledgeSpace] = None + knowledge_space: Optional[ + KnowledgeSpace | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The assigned question knowledge space""" - solutions: Optional[List[Solution]] = None + solutions: Optional[ + List[Solution | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The question solutions""" - attachments: Optional[List[Attachment]] = None + attachments: Optional[ + List[Attachment | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The question attachments""" - comments: Optional[List[Comment]] = None + comments: Optional[ + List[Comment | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The question comments""" @@ -268,19 +333,19 @@ class ConceptLabelMatch: Definition: ConceptLabelMatch """ - concept_id: Optional[str] = None + concept_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique concept id""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """The concept description""" - is_flat: Optional[bool] = None + is_flat: Optional[bool] = dataclass_field(default=None, kw_only=True) """is_flat""" - label_match: Optional[str] = None + label_match: Optional[str] = dataclass_field(default=None, kw_only=True) """The label that matched the concept""" - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """Concept language""" - ontology_id: Optional[str] = None + ontology_id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ontology id to which the concept belongs""" - primary_label: Optional[str] = None + primary_label: Optional[str] = dataclass_field(default=None, kw_only=True) """Concept primary label""" @@ -290,22 +355,22 @@ class Attachment: Definition: Attachment """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the attachment was created (yyyy-MM-ddTHH:mm:ss.fffZ) """ - hash: Optional[str] = None + hash: Optional[str] = dataclass_field(default=None, kw_only=True) """The attachment hash""" - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """the unique attachment id""" - link: Optional[str] = None + link: Optional[str] = dataclass_field(default=None, kw_only=True) """The relative url to the attachment resource""" - mime_type: Optional[str] = None + mime_type: Optional[str] = dataclass_field(default=None, kw_only=True) """The attachment file mime_type""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The attachment file name""" - size: Optional[int] = None + size: Optional[int] = dataclass_field(default=None, kw_only=True) """The attachment file size""" @@ -315,34 +380,34 @@ class Comment: Definition: Comment """ - content_updated: Optional[str] = None + content_updated: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the comment's description was last updated (yyyy-MM-ddTHH:mm:ss.fffZ) """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the comment was created (yyyy-MM-ddTHH:mm:ss.fffZ) """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """ This is the main text of the comment that provides additional information or context to the question or solution. """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The unique comment id""" - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The comment language""" - updated: Optional[str] = None + updated: Optional[str] = dataclass_field(default=None, kw_only=True) """ Last time the resource has been updated in the DB. This date does not reflect content updates but any update to any fields of the record. Use content_updated for information about content updates. """ - upvote_count: Optional[int] = None + upvote_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of upvotes the comment has received.""" - user: Optional[UserLegacy] = None + user: Optional[UserLegacy | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -351,64 +416,84 @@ class Solution: Definition: Solution """ - accepted_by_question_poser: Optional[str] = None + accepted_by_question_poser: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating whether the solution has been accepted by the question poser (yyyy-MM-ddTHH:mm:ss.fffZ) """ - attachments: Optional[List[Attachment]] = None + attachments: Optional[ + List[Attachment | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The solution attachments""" - comments: Optional[List[Comment]] = None + comments: Optional[ + List[Comment | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The solution comments""" - content_updated: Optional[str] = None + content_updated: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the solution's content was last updated (yyyy-MM-ddTHH:mm:ss.fffZ) """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the solution was created (yyyy-MM-ddTHH:mm:ss.fffZ) """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """ This is the main text of the solution that provides the answer or guidance to the question posed. """ - expires: Optional[str] = None + expires: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the solution is about to expiry and requires revalidation (yyyy-MM-ddTHH:mm:ss.fffZ) """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """the unique solution id""" - is_published: Optional[bool] = None + is_published: Optional[bool] = dataclass_field(default=None, kw_only=True) """ The solution is_published flag indicates whether the solution is published or not. A published solution is visible to all users. """ - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """The solution language""" - published: Optional[str] = None + published: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the solution was published (yyyy-MM-ddTHH:mm:ss.fffZ) """ - rating_count: Optional[int] = None + rating_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Total number of ratings for the solution.""" - solution_authority_approval: Optional[SolutionAuthorityApproval] = None - updated: Optional[str] = None + solution_authority_approval: Optional[ + SolutionAuthorityApproval | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + updated: Optional[str] = dataclass_field(default=None, kw_only=True) """ Last time the resource has been updated in the DB. This date does not reflect content updates but any update to any fields of the record. Use content_updated for information about content updates. """ - upvote_count: Optional[int] = None + upvote_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The total number of upvotes the solution has received.""" - user: Optional[UserLegacy] = None + user: Optional[UserLegacy | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) """The user who created the solution""" - validated: Optional[SolutionValidation] = None - validity_period: Optional[str] = None + validated: Optional[ + SolutionValidation | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + validity_period: Optional[str] = dataclass_field(default=None, kw_only=True) """Validity period until the solution is considered expired""" @@ -418,17 +503,19 @@ class SolutionValidation: Definition: SolutionValidation """ - revalidated_at: Optional[str] = field( + revalidated_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "revalidatedAt"}, ) """The date when the solution was revalidated""" - validity_period: Optional[str] = field( + validity_period: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "validityPeriod"}, ) """The validity period until the solution is considered expired""" - user: Optional[UserLegacy] = None + user: Optional[UserLegacy | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) """The user who validated the solution""" @@ -438,13 +525,13 @@ class SolutionAuthorityApproval: Definition: SolutionAuthorityApproval """ - approval_date: Optional[str] = None + approval_date: Optional[str] = dataclass_field(default=None, kw_only=True) """Date of the solution authority approval (yyyy-MM-ddTHH:mm:ss.fffZ)""" - solution_authority_id: Optional[int] = None + solution_authority_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ID of the solution authority""" - solution_authority_name: Optional[str] = None + solution_authority_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the solution authority""" - user: Optional[UserLegacy] = None + user: Optional[UserLegacy | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -453,18 +540,19 @@ class UserLegacy: Definition: UserLegacy """ - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """email""" - global_user_id: Optional[str] = field( + global_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "globalUserId"}, ) """global_user_id""" - image: Optional[str] = None + image: Optional[str] = dataclass_field(default=None, kw_only=True) """image""" - firstname: Optional[str] = None + firstname: Optional[str] = dataclass_field(default=None, kw_only=True) """firstname""" - lastname: Optional[str] = None + lastname: Optional[str] = dataclass_field(default=None, kw_only=True) """lastname""" @@ -477,56 +565,56 @@ class User: Definition: User """ - about: Optional[str] = None + about: Optional[str] = dataclass_field(default=None, kw_only=True) """ Custom text entered by the user to describe themselves in their 'About Me' section """ - avatar_url: Optional[str] = None + avatar_url: Optional[str] = dataclass_field(default=None, kw_only=True) """URL to the user's avatar image""" - company: Optional[str] = None + company: Optional[str] = dataclass_field(default=None, kw_only=True) """Company of the user""" - country: Optional[str] = None + country: Optional[str] = dataclass_field(default=None, kw_only=True) """ISO 3166-1 alpha-2 country code (e.g. ch, us, de) of the user""" - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the user was created (yyyy-MM-ddTHH:mm:ss.fffZ) """ - deleted: Optional[str] = None + deleted: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the user was deleted (yyyy-MM-ddTHH:mm:ss.fffZ). Without admin permissions, only non deleted user will be returned """ - department: Optional[str] = None + department: Optional[str] = dataclass_field(default=None, kw_only=True) """Department of the user""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """Email of the user""" - first_name: Optional[str] = None + first_name: Optional[str] = dataclass_field(default=None, kw_only=True) """First name of the user.""" - first_seen: Optional[str] = None + first_seen: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the user logged in the first time (yyyy-MM-ddTHH:mm:ss.fffZ) """ - id: Optional[UserId] = None - is_federated: Optional[bool] = None + id: Optional[UserId] = dataclass_field(default=None, kw_only=True) + is_federated: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Indicates whether the user authenticates using local credentials (email/password) rather than an external SSO provider (SAML, OpenID Connect) """ - is_technical: Optional[bool] = None + is_technical: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Indicates whether the user is a technical API user (non-interactive/machine account); when true the user typically authenticates via API key """ - language: Optional[Language] = None + language: Optional[Language] = dataclass_field(default=None, kw_only=True) """The user's interface language preference""" - last_name: Optional[str] = None + last_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Last name of the user.""" - location: Optional[str] = None + location: Optional[str] = dataclass_field(default=None, kw_only=True) """Location of the user""" - position: Optional[str] = None + position: Optional[str] = dataclass_field(default=None, kw_only=True) """Company of the user""" @@ -536,24 +624,24 @@ class KnowledgeSpace: Definition: KnowledgeSpace """ - automatic_new_user_assignment: Optional[bool] = None + automatic_new_user_assignment: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates if new users are automatically assigned""" - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp indicating when the knowledge space was created (yyyy-MM-ddTHH:mm:ss.fffZ) """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the knowledge space""" - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The unique knowledge space id""" - is_closed: Optional[bool] = None + is_closed: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates if the knowledge space is non public""" - member_count: Optional[int] = None + member_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of members""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the knowledge space""" - updated: Optional[str] = None + updated: Optional[str] = dataclass_field(default=None, kw_only=True) """Last time the resource has been updated in the DB.""" @@ -569,10 +657,10 @@ class GraphQLError: Definition: GraphQLError """ - extensions: Optional[Dict[str, Any]] = None - locations: Optional[List[Dict[str, Any]]] = None - message: Optional[str] = None - path: Optional[List[str]] = None + extensions: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + locations: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + message: Optional[str] = dataclass_field(default=None, kw_only=True) + path: Optional[List[str]] = dataclass_field(default=None, kw_only=True) # Client Class @@ -583,16 +671,16 @@ class StarmindClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -603,8 +691,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -612,8 +700,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -625,7 +713,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -640,9 +728,9 @@ def __init__( def connector_name(self) -> str: return "starmind" - async def find_experts_async( + def find_experts( self, - input: FindExpertsInput, + input: FindExpertsInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -660,10 +748,26 @@ async def find_experts_async( we show from returned users by selecting concepts based on the primary label in the chosen language. Returned concepts are deduplicated when multiple concepts share the same primary label. + + Swagger operation ID: `FindExperts_V3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/v3/experts" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -677,6 +781,7 @@ async def find_experts_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -684,13 +789,13 @@ async def find_experts_async( return json.loads(response.text) - async def find_questions_async( + def find_questions( self, + *, query: Optional[str] = None, limit: Optional[int] = None, filter: Optional[str] = None, sort: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -704,6 +809,24 @@ async def find_questions_async( `items`. By default, all published questions are returned, ordered by their last activity (descending). A combination of filters, search queries and ordering criteria can be applied to the result. + + Swagger operation ID: `FindQuestions_V3`. + + Args: + query: The question search query. + limit: Limit the number of returned questions. Defaults to 10. + filter: Filter the list of questions using a predefined filter. + sort: Specify the criteria the result is sorted by. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/v3/questions" query_params = [] @@ -730,7 +853,7 @@ async def find_questions_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -744,6 +867,7 @@ async def find_questions_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -751,7 +875,7 @@ async def find_questions_async( return json.loads(response.text) - async def get_user_by_id_async( + def get_user_by_id( self, id: str, *, @@ -764,13 +888,29 @@ async def get_user_by_id_async( Get user by id Retrieves user information based on the provided user id. + + Swagger operation ID: `GetUserById_V3`. + + Args: + id: The unique global user identifier (UUID) as path parameter used + to reference the user across the Starmind platform. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v3/users/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -784,6 +924,7 @@ async def get_user_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -791,9 +932,9 @@ async def get_user_by_id_async( return json.loads(response.text) - async def post_question_draft_async( + def post_question_draft( self, - input: PostQuestionDraftInput, + input: PostQuestionDraftInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -809,10 +950,26 @@ async def post_question_draft_async( discoverable, and allow other users to answer it. Providing the optional description helps experts understand the question better and increases the chances of getting high-quality answers. + + Swagger operation ID: `PostQuestionDraft_V3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/v3/questions" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -826,6 +983,7 @@ async def post_question_draft_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -833,7 +991,7 @@ async def post_question_draft_async( return json.loads(response.text) - async def publish_question_draft_async( + def publish_question_draft( self, question_id: int, *, @@ -848,13 +1006,28 @@ async def publish_question_draft_async( Publishes a question draft. Publishing the question triggers expert search, makes the question discoverable, and allows other users to answer it. Questions are always published anonymously. + + Swagger operation ID: `PublishQuestionDraft_V3`. + + Args: + question_id: The ID of the question draft to be published. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/v3/questions/{quote(str(question_id), safe='')}/publish" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -868,6 +1041,7 @@ async def publish_question_draft_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/starrezrestv1.py b/src/azure/connectors/starrezrestv1.py index fcddbe8..b355563 100644 --- a/src/azure/connectors/starrezrestv1.py +++ b/src/azure/connectors/starrezrestv1.py @@ -5,21 +5,70 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "Starrezrestv1Client", + "CreateBookingInput", + "CreateBookingResponse", + "CreateEntryApplicationInput", + "CreateEntryApplicationResponse", + "CreateEntryEnrollmentInput", + "CreateEntryEnrollmentResponse", + "CreateEntryInput", + "CreateEntryResponse", + "CreateRoomSpaceInput", + "CreateRoomSpaceMaintenanceInput", + "CreateRoomSpaceMaintenanceResponse", + "CreateRoomSpaceResponse", + "CreateTransactionInput", + "CreateTransactionResponse", + "DeleteResponse", + "SelectBookingInput", + "SelectEntryAddressInput", + "SelectEntryApplicationInput", + "SelectEntryCustomFieldInput", + "SelectEntryDetailInput", + "SelectEntryEnrollmentInput", + "SelectEntryInput", + "SelectRoomLocationInput", + "SelectRoomSpaceInput", + "SelectRoomSpaceMaintenanceInput", + "SelectTermInput", + "SelectTermSessionInput", + "SelectTransactionInput", + "UpdateBookingInput", + "UpdateBookingResponse", + "UpdateEntryAddressInput", + "UpdateEntryAddressResponse", + "UpdateEntryApplicationInput", + "UpdateEntryApplicationResponse", + "UpdateEntryCustomFieldInput", + "UpdateEntryCustomFieldResponse", + "UpdateEntryDetailInput", + "UpdateEntryDetailResponse", + "UpdateEntryEnrollmentInput", + "UpdateEntryEnrollmentResponse", + "UpdateEntryInput", + "UpdateEntryResponse", + "UpdateRoomSpaceMaintenanceInput", + "UpdateRoomSpaceMaintenanceResponse", +] + # Type Definitions @@ -29,201 +78,249 @@ class SelectEntryInput: Get Entry """ - return_empty_array_on_no_result: Optional[bool] = field( + return_empty_array_on_no_result: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_returnEmptyArrayOnNoResult"}, ) """ Determines whether an empty array should be returned when there is no result. """ - page_size: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageSize"}, - ) + page_size: int = dataclass_field(metadata={"wire_name": "_pageSize"}) """Maximum number of records to return.""" - page_index: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageIndex"}, - ) + page_index: int = dataclass_field(metadata={"wire_name": "_pageIndex"}) """Index of the first record to return.""" - orderby: Optional[str] = field( + orderby: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_orderby"}, ) """ Sort by one or more fields in ascending order. Fields must be separated by commas with no spaces (e.g. field1,field2). """ - address_type_id: Optional[int] = field( + address_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AddressTypeID"}, ) """Address type of the entry's active address record.""" - birth_gender_enum: Optional[str] = field( + birth_gender_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Birth_GenderEnum"}, ) """The gender of the entry at birth.""" - booking_id: Optional[int] = field( + booking_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingID"}, ) """Pointer to the active booking record.""" - category_id: Optional[int] = field( + category_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CategoryID"}, ) """The category that the entry belongs to.""" - conference_email: Optional[str] = field( + conference_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ConferenceEmail"}, ) """ The email that is used to identify a student through Conference registration. """ - contact_id: Optional[int] = field( + contact_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactID"}, ) """Pointer to the contact record.""" - created_by_security_user_id: Optional[int] = field( + created_by_security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CreatedBy_SecurityUserID"}, ) """Pointer to the security user record.""" - date_created: Optional[Dict[str, Any]] = field( + date_created: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateCreated"}, ) - date_modified: Optional[Dict[str, Any]] = field( + date_modified: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) - directory_flag_privacy: Optional[bool] = field( + directory_flag_privacy: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DirectoryFlagPrivacy"}, ) """Determines if the entry has elected to remain private.""" - d_o_b: Optional[Dict[str, Any]] = field( + d_o_b: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DOB"}, ) - entry_application_id: Optional[int] = field( + entry_application_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryApplicationID"}, ) """Pointer to the active application record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Unique ID for this Entry field.""" - entry_status_enum: Optional[str] = field( + entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryStatusEnum"}, ) """The status of the entry.""" - event_id: Optional[int] = field( + event_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EventID"}, ) """Pointer to the event record.""" - gender_enum: Optional[str] = field( + gender_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GenderEnum"}, ) """Entry gender.""" - i_d1: Optional[str] = field(default=None, metadata={"wire_name": "ID1"}) + i_d1: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID1"}, + ) """Generic ID field.""" - i_d2: Optional[str] = field(default=None, metadata={"wire_name": "ID2"}) + i_d2: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID2"}, + ) """Generic ID field.""" - i_d3: Optional[str] = field(default=None, metadata={"wire_name": "ID3"}) + i_d3: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID3"}, + ) """Generic ID field.""" - i_d4: Optional[int] = field(default=None, metadata={"wire_name": "ID4"}) + i_d4: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID4"}, + ) """Generic ID field.""" - i_d5: Optional[int] = field(default=None, metadata={"wire_name": "ID5"}) + i_d5: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID5"}, + ) """Generic ID field.""" - last_check_in_out_date: Optional[Dict[str, Any]] = field( + last_check_in_out_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastCheckInOutDate"}, ) - name_first: Optional[str] = field( + name_first: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameFirst"}, ) """The first or given name of the entry.""" - name_initials: Optional[str] = field( + name_initials: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameInitials"}, ) """Name initials.""" - name_last: Optional[str] = field( + name_last: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameLast"}, ) """The surname, family name or last name of the entry.""" - name_other: Optional[str] = field( + name_other: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameOther"}, ) """Alternative name.""" - name_preferred: Optional[str] = field( + name_preferred: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NamePreferred"}, ) """Preferred name.""" - name_sharer: Optional[str] = field( + name_sharer: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameSharer"}, ) """Additional occupant name.""" - name_title: Optional[str] = field( + name_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameTitle"}, ) """The title or salutation of the entry.""" - name_web: Optional[str] = field( + name_web: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameWeb"}, ) """A name to display for this entry on the Web.""" - pin_number: Optional[int] = field( + pin_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PinNumber"}, ) """Personal Identification Number.""" - portal_auth_provider_user_id: Optional[str] = field( + portal_auth_provider_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalAuthProviderUserID"}, ) """ User identification used to identify the entry in PortalX. This could be an email, username or other identifier. """ - portal_email: Optional[str] = field( + portal_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalEmail"}, ) """The email that is used by the student to login to the portal.""" - position: Optional[str] = field( + position: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Position"}, ) """Entry position in the institution.""" - previous_entry_status_enum: Optional[str] = field( + previous_entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Previous_EntryStatusEnum"}, ) """The previous entry status.""" - tax_exemption_enum: Optional[str] = field( + tax_exemption_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TaxExemptionEnum"}, ) """Tax exemption.""" - testing: Optional[bool] = field( + testing: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Testing"}, ) """Testing User.""" @@ -235,166 +332,211 @@ class CreateEntryInput: Create Entry """ - address_type_id: Optional[int] = field( + address_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AddressTypeID"}, ) """Address type of the entry's active address record.""" - birth_gender_enum: Optional[str] = field( + birth_gender_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Birth_GenderEnum"}, ) """The gender of the entry at birth.""" - booking_id: Optional[int] = field( + booking_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingID"}, ) """Pointer to the active booking record.""" - category_id: Optional[int] = field( + category_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CategoryID"}, ) """The category that the entry belongs to.""" - conference_email: Optional[str] = field( + conference_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ConferenceEmail"}, ) """ The email that is used to identify a student through Conference registration. """ - contact_id: Optional[int] = field( + contact_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactID"}, ) """Pointer to the contact record.""" - directory_flag_privacy: Optional[bool] = field( + directory_flag_privacy: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DirectoryFlagPrivacy"}, ) """Determines if the entry has elected to remain private.""" - d_o_b: Optional[str] = field(default=None, metadata={"wire_name": "DOB"}) + d_o_b: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "DOB"}, + ) """Date of birth.""" - entry_application_id: Optional[int] = field( + entry_application_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryApplicationID"}, ) """Pointer to the active application record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Unique ID for this Entry field.""" - entry_status_enum: Optional[str] = field( + entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryStatusEnum"}, ) """The status of the entry.""" - event_id: Optional[int] = field( + event_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EventID"}, ) """Pointer to the event record.""" - gender_enum: Optional[str] = field( + gender_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GenderEnum"}, ) """Entry gender.""" - i_d1: Optional[str] = field(default=None, metadata={"wire_name": "ID1"}) + i_d1: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID1"}, + ) """Generic ID field.""" - i_d2: Optional[str] = field(default=None, metadata={"wire_name": "ID2"}) + i_d2: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID2"}, + ) """Generic ID field.""" - i_d3: Optional[str] = field(default=None, metadata={"wire_name": "ID3"}) + i_d3: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID3"}, + ) """Generic ID field.""" - i_d4: Optional[int] = field(default=None, metadata={"wire_name": "ID4"}) + i_d4: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID4"}, + ) """Generic ID field.""" - i_d5: Optional[int] = field(default=None, metadata={"wire_name": "ID5"}) + i_d5: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID5"}, + ) """Generic ID field.""" - last_check_in_out_date: Optional[str] = field( + last_check_in_out_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastCheckInOutDate"}, ) """The last date a check-in or check-out was performed.""" - name_first: Optional[str] = field( - default=None, - metadata={"wire_name": "NameFirst"}, - ) + name_first: str = dataclass_field(metadata={"wire_name": "NameFirst"}) """The first or given name of the entry.""" - name_initials: Optional[str] = field( + name_initials: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameInitials"}, ) """Name initials.""" - name_last: Optional[str] = field( - default=None, - metadata={"wire_name": "NameLast"}, - ) + name_last: str = dataclass_field(metadata={"wire_name": "NameLast"}) """The surname, family name or last name of the entry.""" - name_other: Optional[str] = field( + name_other: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameOther"}, ) """Alternative name.""" - name_preferred: Optional[str] = field( + name_preferred: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NamePreferred"}, ) """Preferred name.""" - name_sharer: Optional[str] = field( + name_sharer: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameSharer"}, ) """Additional occupant name.""" - name_title: Optional[str] = field( + name_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameTitle"}, ) """The title or salutation of the entry.""" - name_web: Optional[str] = field( + name_web: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameWeb"}, ) """A name to display for this entry on the Web.""" - password: Optional[str] = field( + password: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Password"}, ) """Password""" - pin_number: Optional[int] = field( + pin_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PinNumber"}, ) """Personal Identification Number.""" - portal_auth_provider_user_id: Optional[str] = field( + portal_auth_provider_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalAuthProviderUserID"}, ) """ User identification used to identify the entry in PortalX. This could be an email, username or other identifier. """ - portal_email: Optional[str] = field( + portal_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalEmail"}, ) """The email that is used by the student to login to the portal.""" - position: Optional[str] = field( + position: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Position"}, ) """Entry position in the institution.""" - previous_entry_status_enum: Optional[str] = field( + previous_entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Previous_EntryStatusEnum"}, ) """The previous entry status.""" - tax_exemption_enum: Optional[str] = field( + tax_exemption_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TaxExemptionEnum"}, ) """Tax exemption.""" - testing: Optional[bool] = field( + testing: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Testing"}, ) """Testing User.""" @@ -406,166 +548,219 @@ class CreateEntryResponse: Response for Create Entry """ - address_type_id: Optional[int] = field( + address_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AddressTypeID"}, ) """Address type of the entry's active address record.""" - birth_gender_enum: Optional[str] = field( + birth_gender_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Birth_GenderEnum"}, ) """The gender of the entry at birth.""" - booking_id: Optional[int] = field( + booking_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingID"}, ) """Pointer to the active booking record.""" - category_id: Optional[int] = field( + category_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CategoryID"}, ) """The category that the entry belongs to.""" - conference_email: Optional[str] = field( + conference_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ConferenceEmail"}, ) """ The email that is used to identify a student through Conference registration. """ - contact_id: Optional[int] = field( + contact_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactID"}, ) """Pointer to the contact record.""" - directory_flag_privacy: Optional[bool] = field( + directory_flag_privacy: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DirectoryFlagPrivacy"}, ) """Determines if the entry has elected to remain private.""" - d_o_b: Optional[str] = field(default=None, metadata={"wire_name": "DOB"}) + d_o_b: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "DOB"}, + ) """Date of birth.""" - entry_application_id: Optional[int] = field( + entry_application_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryApplicationID"}, ) """Pointer to the active application record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Unique ID for this Entry field.""" - entry_status_enum: Optional[str] = field( + entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryStatusEnum"}, ) """The status of the entry.""" - event_id: Optional[int] = field( + event_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EventID"}, ) """Pointer to the event record.""" - gender_enum: Optional[str] = field( + gender_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GenderEnum"}, ) """Entry gender.""" - i_d1: Optional[str] = field(default=None, metadata={"wire_name": "ID1"}) + i_d1: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID1"}, + ) """Generic ID field.""" - i_d2: Optional[str] = field(default=None, metadata={"wire_name": "ID2"}) + i_d2: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID2"}, + ) """Generic ID field.""" - i_d3: Optional[str] = field(default=None, metadata={"wire_name": "ID3"}) + i_d3: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID3"}, + ) """Generic ID field.""" - i_d4: Optional[int] = field(default=None, metadata={"wire_name": "ID4"}) + i_d4: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID4"}, + ) """Generic ID field.""" - i_d5: Optional[int] = field(default=None, metadata={"wire_name": "ID5"}) + i_d5: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID5"}, + ) """Generic ID field.""" - last_check_in_out_date: Optional[str] = field( + last_check_in_out_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastCheckInOutDate"}, ) """The last date a check-in or check-out was performed.""" - name_first: Optional[str] = field( + name_first: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameFirst"}, ) """The first or given name of the entry.""" - name_initials: Optional[str] = field( + name_initials: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameInitials"}, ) """Initials in name.""" - name_last: Optional[str] = field( + name_last: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameLast"}, ) """The surname, family name or last name of the entry.""" - name_other: Optional[str] = field( + name_other: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameOther"}, ) """Alternative name.""" - name_preferred: Optional[str] = field( + name_preferred: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NamePreferred"}, ) """Preferred name.""" - name_sharer: Optional[str] = field( + name_sharer: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameSharer"}, ) """Additional occupant name.""" - name_title: Optional[str] = field( + name_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameTitle"}, ) """The title or salutation of the entry.""" - name_web: Optional[str] = field( + name_web: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameWeb"}, ) """A name to display for this entry on the Web.""" - password: Optional[str] = field( + password: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Password"}, ) """Password""" - pin_number: Optional[int] = field( + pin_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PinNumber"}, ) """Personal Identification Number.""" - portal_auth_provider_user_id: Optional[str] = field( + portal_auth_provider_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalAuthProviderUserID"}, ) """ User identification used to identify the entry in PortalX. This could be an email, username or other identifier. """ - portal_email: Optional[str] = field( + portal_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalEmail"}, ) """Portal email.""" - position: Optional[str] = field( + position: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Position"}, ) """Entry position in the institution.""" - previous_entry_status_enum: Optional[str] = field( + previous_entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Previous_EntryStatusEnum"}, ) """The previous entry status.""" - tax_exemption_enum: Optional[str] = field( + tax_exemption_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TaxExemptionEnum"}, ) """Tax exemption.""" - testing: Optional[bool] = field( + testing: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Testing"}, ) """Testing user.""" @@ -577,166 +772,219 @@ class UpdateEntryInput: Update Entry """ - address_type_id: Optional[int] = field( + address_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AddressTypeID"}, ) """Address type of the entry's active address record.""" - birth_gender_enum: Optional[str] = field( + birth_gender_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Birth_GenderEnum"}, ) """The gender of the entry at birth.""" - booking_id: Optional[int] = field( + booking_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingID"}, ) """Pointer to the active booking record.""" - category_id: Optional[int] = field( + category_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CategoryID"}, ) """The category that the entry belongs to.""" - conference_email: Optional[str] = field( + conference_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ConferenceEmail"}, ) """ The email that is used to identify a student through Conference registration. """ - contact_id: Optional[int] = field( + contact_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactID"}, ) """Pointer to the contact record.""" - directory_flag_privacy: Optional[bool] = field( + directory_flag_privacy: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DirectoryFlagPrivacy"}, ) """Determines if the entry has elected to remain private.""" - d_o_b: Optional[str] = field(default=None, metadata={"wire_name": "DOB"}) + d_o_b: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "DOB"}, + ) """Date of birth.""" - entry_application_id: Optional[int] = field( + entry_application_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryApplicationID"}, ) """Pointer to the active application record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Unique ID for this Entry field.""" - entry_status_enum: Optional[str] = field( + entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryStatusEnum"}, ) """The status of the entry.""" - event_id: Optional[int] = field( + event_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EventID"}, ) """Pointer to the event record.""" - gender_enum: Optional[str] = field( + gender_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GenderEnum"}, ) """Entry gender.""" - i_d1: Optional[str] = field(default=None, metadata={"wire_name": "ID1"}) + i_d1: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID1"}, + ) """Generic ID field.""" - i_d2: Optional[str] = field(default=None, metadata={"wire_name": "ID2"}) + i_d2: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID2"}, + ) """Generic ID field.""" - i_d3: Optional[str] = field(default=None, metadata={"wire_name": "ID3"}) + i_d3: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID3"}, + ) """Generic ID field.""" - i_d4: Optional[int] = field(default=None, metadata={"wire_name": "ID4"}) + i_d4: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID4"}, + ) """Generic ID field.""" - i_d5: Optional[int] = field(default=None, metadata={"wire_name": "ID5"}) + i_d5: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID5"}, + ) """Generic ID field.""" - last_check_in_out_date: Optional[str] = field( + last_check_in_out_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastCheckInOutDate"}, ) """The last date a check-in or check-out was performed.""" - name_first: Optional[str] = field( + name_first: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameFirst"}, ) """The first or given name of the entry.""" - name_initials: Optional[str] = field( + name_initials: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameInitials"}, ) """Name initials.""" - name_last: Optional[str] = field( + name_last: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameLast"}, ) """The surname, family name or last name of the entry.""" - name_other: Optional[str] = field( + name_other: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameOther"}, ) """Alternative name.""" - name_preferred: Optional[str] = field( + name_preferred: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NamePreferred"}, ) """Preferred name.""" - name_sharer: Optional[str] = field( + name_sharer: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameSharer"}, ) """Additional occupant name.""" - name_title: Optional[str] = field( + name_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameTitle"}, ) """The title or salutation of the entry.""" - name_web: Optional[str] = field( + name_web: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameWeb"}, ) """A name to display for this entry on the Web.""" - password: Optional[str] = field( + password: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Password"}, ) """Password""" - pin_number: Optional[int] = field( + pin_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PinNumber"}, ) """Personal Identification Number.""" - portal_auth_provider_user_id: Optional[str] = field( + portal_auth_provider_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalAuthProviderUserID"}, ) """ User identification used to identify the entry in PortalX. This could be an email, username or other identifier. """ - portal_email: Optional[str] = field( + portal_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalEmail"}, ) """The email that is used by the student to login to the portal.""" - position: Optional[str] = field( + position: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Position"}, ) """Entry position in the institution.""" - previous_entry_status_enum: Optional[str] = field( + previous_entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Previous_EntryStatusEnum"}, ) """The previous entry status.""" - tax_exemption_enum: Optional[str] = field( + tax_exemption_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TaxExemptionEnum"}, ) """Tax exemption.""" - testing: Optional[bool] = field( + testing: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Testing"}, ) """Testing User.""" @@ -748,166 +996,219 @@ class UpdateEntryResponse: Response for Update Entry """ - address_type_id: Optional[int] = field( + address_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AddressTypeID"}, ) """Pointer to this entry's active address record.""" - birth_gender_enum: Optional[str] = field( + birth_gender_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Birth_GenderEnum"}, ) """The gender of the entry at birth.""" - booking_id: Optional[int] = field( + booking_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingID"}, ) """Pointer to the active booking record.""" - category_id: Optional[int] = field( + category_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CategoryID"}, ) """The category that the entry belongs to.""" - conference_email: Optional[str] = field( + conference_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ConferenceEmail"}, ) """ The email that is used to identify a student through Conference registration. """ - contact_id: Optional[int] = field( + contact_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactID"}, ) """Pointer to the contact record.""" - directory_flag_privacy: Optional[bool] = field( + directory_flag_privacy: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DirectoryFlagPrivacy"}, ) """Determines if the entry has elected to remain private.""" - d_o_b: Optional[str] = field(default=None, metadata={"wire_name": "DOB"}) + d_o_b: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "DOB"}, + ) """Date of birth.""" - entry_application_id: Optional[int] = field( + entry_application_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryApplicationID"}, ) """Pointer to the active application record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Unique ID for this Entry field.""" - entry_status_enum: Optional[str] = field( + entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryStatusEnum"}, ) """The status of the entry.""" - event_id: Optional[int] = field( + event_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EventID"}, ) """Pointer to the event record.""" - gender_enum: Optional[str] = field( + gender_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GenderEnum"}, ) """Entry gender.""" - i_d1: Optional[str] = field(default=None, metadata={"wire_name": "ID1"}) + i_d1: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID1"}, + ) """Generic ID field.""" - i_d2: Optional[str] = field(default=None, metadata={"wire_name": "ID2"}) + i_d2: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID2"}, + ) """Generic ID field.""" - i_d3: Optional[str] = field(default=None, metadata={"wire_name": "ID3"}) + i_d3: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID3"}, + ) """Generic ID field.""" - i_d4: Optional[int] = field(default=None, metadata={"wire_name": "ID4"}) + i_d4: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID4"}, + ) """Generic ID field.""" - i_d5: Optional[int] = field(default=None, metadata={"wire_name": "ID5"}) + i_d5: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID5"}, + ) """Generic ID field.""" - last_check_in_out_date: Optional[str] = field( + last_check_in_out_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LastCheckInOutDate"}, ) """The last date a check-in or check-out was performed.""" - name_first: Optional[str] = field( + name_first: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameFirst"}, ) """The first or given name of the entry.""" - name_initials: Optional[str] = field( + name_initials: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameInitials"}, ) """Name initials.""" - name_last: Optional[str] = field( + name_last: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameLast"}, ) """The surname, family name or last name of the entry.""" - name_other: Optional[str] = field( + name_other: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameOther"}, ) """Alternative name.""" - name_preferred: Optional[str] = field( + name_preferred: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NamePreferred"}, ) """Preferred name.""" - name_sharer: Optional[str] = field( + name_sharer: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameSharer"}, ) """Additional occupant name.""" - name_title: Optional[str] = field( + name_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameTitle"}, ) """The title or salutation of the entry.""" - name_web: Optional[str] = field( + name_web: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NameWeb"}, ) """A name to display for this entry on the Web.""" - password: Optional[str] = field( + password: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Password"}, ) """Password""" - pin_number: Optional[int] = field( + pin_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PinNumber"}, ) """Personal Identification Number.""" - portal_auth_provider_user_id: Optional[str] = field( + portal_auth_provider_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalAuthProviderUserID"}, ) """ User identification used to identify the entry in PortalX. This could be an email, username or other identifier. """ - portal_email: Optional[str] = field( + portal_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalEmail"}, ) """The email that is used by the student to login to the portal.""" - position: Optional[str] = field( + position: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Position"}, ) """Entry position in the institution.""" - previous_entry_status_enum: Optional[str] = field( + previous_entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Previous_EntryStatusEnum"}, ) """The previous entry status.""" - tax_exemption_enum: Optional[str] = field( + tax_exemption_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TaxExemptionEnum"}, ) """Tax exemption.""" - testing: Optional[bool] = field( + testing: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Testing"}, ) """Testing User.""" @@ -919,7 +1220,7 @@ class DeleteResponse: Response for Delete """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -932,77 +1233,83 @@ class SelectEntryCustomFieldInput: Get Entry Custom Field """ - return_empty_array_on_no_result: Optional[bool] = field( + return_empty_array_on_no_result: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_returnEmptyArrayOnNoResult"}, ) """ Determines whether an empty array should be returned when there is no result. """ - page_size: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageSize"}, - ) + page_size: int = dataclass_field(metadata={"wire_name": "_pageSize"}) """Maximum number of records to return.""" - page_index: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageIndex"}, - ) + page_index: int = dataclass_field(metadata={"wire_name": "_pageIndex"}) """Index of the first record to return.""" - orderby: Optional[str] = field( + orderby: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_orderby"}, ) """ Sort by one or more fields in ascending order. Fields must be separated by commas with no spaces (e.g. field1,field2). """ - custom_field_definition_id: Optional[int] = field( + custom_field_definition_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomFieldDefinitionID"}, ) """Pointer to the custom field definition record.""" - date_modified: Optional[Dict[str, Any]] = field( + date_modified: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) - entry_custom_field_id: Optional[int] = field( + entry_custom_field_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryCustomFieldID"}, ) """Unique ID for this entry custom field record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - field_data_type_enum: Optional[str] = field( + field_data_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FieldDataTypeEnum"}, ) """Field data type.""" - value_boolean: Optional[bool] = field( + value_boolean: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueBoolean"}, ) """Boolean value.""" - value_date: Optional[Dict[str, Any]] = field( + value_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueDate"}, ) - value_integer: Optional[int] = field( + value_integer: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueInteger"}, ) """Integer value.""" - value_money: Optional[float] = field( + value_money: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueMoney"}, ) """Money value.""" - value_string: Optional[str] = field( + value_string: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueString"}, ) """String value.""" @@ -1014,48 +1321,57 @@ class UpdateEntryCustomFieldInput: Update Entry Custom Field """ - custom_field_definition_id: Optional[int] = field( + custom_field_definition_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomFieldDefinitionID"}, ) """Pointer to the custom field definition record.""" - entry_custom_field_id: Optional[int] = field( + entry_custom_field_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryCustomFieldID"}, ) """Unique ID for this entry custom field record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - field_data_type_enum: Optional[str] = field( + field_data_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FieldDataTypeEnum"}, ) """Field data type.""" - value_boolean: Optional[bool] = field( + value_boolean: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueBoolean"}, ) """Boolean value.""" - value_date: Optional[str] = field( + value_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueDate"}, ) """Date value.""" - value_integer: Optional[int] = field( + value_integer: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueInteger"}, ) """Integer value.""" - value_money: Optional[float] = field( + value_money: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueMoney"}, ) """Money value.""" - value_string: Optional[str] = field( + value_string: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueString"}, ) """String value.""" @@ -1067,48 +1383,57 @@ class UpdateEntryCustomFieldResponse: Response for Update Entry Custom Field """ - custom_field_definition_id: Optional[int] = field( + custom_field_definition_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomFieldDefinitionID"}, ) """Pointer to the custom field definition record.""" - entry_custom_field_id: Optional[int] = field( + entry_custom_field_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryCustomFieldID"}, ) """Unique ID for this entry custom field record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - field_data_type_enum: Optional[str] = field( + field_data_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FieldDataTypeEnum"}, ) """Field data type.""" - value_boolean: Optional[bool] = field( + value_boolean: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueBoolean"}, ) """Boolean value.""" - value_date: Optional[str] = field( + value_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueDate"}, ) """Date value.""" - value_integer: Optional[int] = field( + value_integer: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueInteger"}, ) """Integer value.""" - value_money: Optional[float] = field( + value_money: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueMoney"}, ) """Money value.""" - value_string: Optional[str] = field( + value_string: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ValueString"}, ) """String value.""" @@ -1120,86 +1445,94 @@ class SelectTermInput: Get Term """ - return_empty_array_on_no_result: Optional[bool] = field( + return_empty_array_on_no_result: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_returnEmptyArrayOnNoResult"}, ) """ Determines whether an empty array should be returned when there is no result. """ - page_size: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageSize"}, - ) + page_size: int = dataclass_field(metadata={"wire_name": "_pageSize"}) """Maximum number of records to return.""" - page_index: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageIndex"}, - ) + page_index: int = dataclass_field(metadata={"wire_name": "_pageIndex"}) """Index of the first record to return.""" - orderby: Optional[str] = field( + orderby: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_orderby"}, ) """ Sort by one or more fields in ascending order. Fields must be separated by commas with no spaces (e.g. field1,field2). """ - active: Optional[bool] = field( + active: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Active"}, ) """Current active state.""" - active_date_close: Optional[Dict[str, Any]] = field( + active_date_close: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ActiveDateClose"}, ) - active_date_open: Optional[Dict[str, Any]] = field( + active_date_open: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ActiveDateOpen"}, ) - category_id: Optional[int] = field( + category_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CategoryID"}, ) """Pointer to the category record.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Term comments.""" - date_modified: Optional[Dict[str, Any]] = field( + date_modified: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """Term description.""" - record_type_enum: Optional[str] = field( + record_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecordTypeEnum"}, ) """Record type.""" - term_code: Optional[str] = field( + term_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermCode"}, ) """Term code.""" - term_id: Optional[int] = field( + term_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermID"}, ) """Unique ID for this term record.""" - term_type_id: Optional[int] = field( + term_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermTypeID"}, ) """Pointer to the term type record.""" - web_description: Optional[str] = field( + web_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebDescription"}, ) """Term displayed in the Portal.""" @@ -1211,132 +1544,160 @@ class SelectEntryAddressInput: Get Entry Address """ - return_empty_array_on_no_result: Optional[bool] = field( + return_empty_array_on_no_result: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_returnEmptyArrayOnNoResult"}, ) """ Determines whether an empty array should be returned when there is no result. """ - page_size: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageSize"}, - ) + page_size: int = dataclass_field(metadata={"wire_name": "_pageSize"}) """Maximum number of records to return.""" - page_index: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageIndex"}, - ) + page_index: int = dataclass_field(metadata={"wire_name": "_pageIndex"}) """Index of the first record to return.""" - orderby: Optional[str] = field( + orderby: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_orderby"}, ) """ Sort by one or more fields in ascending order. Fields must be separated by commas with no spaces (e.g. field1,field2). """ - active_date_end: Optional[Dict[str, Any]] = field( + active_date_end: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ActiveDateEnd"}, ) - active_date_start: Optional[Dict[str, Any]] = field( + active_date_start: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ActiveDateStart"}, ) - address_type_id: Optional[int] = field( + address_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AddressTypeID"}, ) """Pointer to the address type record.""" - city: Optional[str] = field(default=None, metadata={"wire_name": "City"}) + city: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "City"}, + ) """City""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Address comments.""" - contact_name: Optional[str] = field( + contact_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactName"}, ) """Contact name.""" - contact_name2: Optional[str] = field( + contact_name2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactName2"}, ) """Contact name 2.""" - country_id: Optional[int] = field( + country_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CountryID"}, ) """Pointer to the country record.""" - date_modified: Optional[Dict[str, Any]] = field( + date_modified: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) - email: Optional[str] = field(default=None, metadata={"wire_name": "Email"}) + email: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Email"}, + ) """Email""" - entry_address_id: Optional[int] = field( + entry_address_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryAddressID"}, ) """Unique ID for this entry address record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - phone: Optional[str] = field(default=None, metadata={"wire_name": "Phone"}) + phone: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Phone"}, + ) """Phone""" - phone_mobile_cell: Optional[str] = field( + phone_mobile_cell: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PhoneMobileCell"}, ) """Mobile/Cell""" - phone_other: Optional[str] = field( + phone_other: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PhoneOther"}, ) """Alternative phone.""" - phone_other2: Optional[str] = field( + phone_other2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PhoneOther2"}, ) """Alternative phone 2.""" - reference: Optional[str] = field( + reference: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reference"}, ) """Reference""" - relationship: Optional[str] = field( + relationship: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Relationship"}, ) """Relationship this address has to the entry.""" - salutation: Optional[str] = field( + salutation: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Salutation"}, ) """Salutation""" - state_province: Optional[str] = field( + state_province: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StateProvince"}, ) """State/Province""" - street: Optional[str] = field( + street: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Street"}, ) """Street""" - street2: Optional[str] = field( + street2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Street2"}, ) """Street""" - zip_postcode: Optional[str] = field( + zip_postcode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ZipPostcode"}, ) """Zip/Postcode""" @@ -1348,104 +1709,135 @@ class UpdateEntryAddressInput: Update Entry Address """ - active_date_end: Optional[str] = field( + active_date_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ActiveDateEnd"}, ) """End active date.""" - active_date_start: Optional[str] = field( + active_date_start: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ActiveDateStart"}, ) """Date when this address becomes active.""" - address_type_id: Optional[int] = field( + address_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AddressTypeID"}, ) """Pointer to the address type record.""" - city: Optional[str] = field(default=None, metadata={"wire_name": "City"}) + city: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "City"}, + ) """City""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Address comments.""" - contact_name: Optional[str] = field( + contact_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactName"}, ) """Contact name.""" - contact_name2: Optional[str] = field( + contact_name2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactName2"}, ) """Contact name 2.""" - country_id: Optional[int] = field( + country_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CountryID"}, ) """Pointer to the country record.""" - email: Optional[str] = field(default=None, metadata={"wire_name": "Email"}) + email: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Email"}, + ) """Email""" - entry_address_id: Optional[int] = field( + entry_address_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryAddressID"}, ) """Unique ID for this entry address record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - phone: Optional[str] = field(default=None, metadata={"wire_name": "Phone"}) + phone: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Phone"}, + ) """Phone""" - phone_mobile_cell: Optional[str] = field( + phone_mobile_cell: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PhoneMobileCell"}, ) """Mobile/Cell""" - phone_other: Optional[str] = field( + phone_other: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PhoneOther"}, ) """Alternative phone.""" - phone_other2: Optional[str] = field( + phone_other2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PhoneOther2"}, ) """Alternative phone 2.""" - reference: Optional[str] = field( + reference: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reference"}, ) """Reference""" - relationship: Optional[str] = field( + relationship: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Relationship"}, ) """Relationship this address has to the entry.""" - salutation: Optional[str] = field( + salutation: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Salutation"}, ) """Salutation""" - state_province: Optional[str] = field( + state_province: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StateProvince"}, ) """State/Province""" - street: Optional[str] = field( + street: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Street"}, ) """Street""" - street2: Optional[str] = field( + street2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Street2"}, ) """Street""" - zip_postcode: Optional[str] = field( + zip_postcode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ZipPostcode"}, ) """Zip/Postcode""" @@ -1457,104 +1849,135 @@ class UpdateEntryAddressResponse: Response for Update Entry Address """ - active_date_end: Optional[str] = field( + active_date_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ActiveDateEnd"}, ) """End active date.""" - active_date_start: Optional[str] = field( + active_date_start: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ActiveDateStart"}, ) """Date when this address becomes active.""" - address_type_id: Optional[int] = field( + address_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AddressTypeID"}, ) """Pointer to the address type record.""" - city: Optional[str] = field(default=None, metadata={"wire_name": "City"}) + city: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "City"}, + ) """City""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Address comments.""" - contact_name: Optional[str] = field( + contact_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactName"}, ) """Contact name.""" - contact_name2: Optional[str] = field( + contact_name2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactName2"}, ) """Contact name 2.""" - country_id: Optional[int] = field( + country_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CountryID"}, ) """Pointer to the country record.""" - email: Optional[str] = field(default=None, metadata={"wire_name": "Email"}) + email: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Email"}, + ) """Email""" - entry_address_id: Optional[int] = field( + entry_address_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryAddressID"}, ) """Unique ID for this entry address record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - phone: Optional[str] = field(default=None, metadata={"wire_name": "Phone"}) + phone: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Phone"}, + ) """Phone""" - phone_mobile_cell: Optional[str] = field( + phone_mobile_cell: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PhoneMobileCell"}, ) """Mobile/Cell""" - phone_other: Optional[str] = field( + phone_other: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PhoneOther"}, ) """Alternative phone.""" - phone_other2: Optional[str] = field( + phone_other2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PhoneOther2"}, ) """Alternative phone 2.""" - reference: Optional[str] = field( + reference: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reference"}, ) """Reference""" - relationship: Optional[str] = field( + relationship: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Relationship"}, ) """Relationship this address has to the entry.""" - salutation: Optional[str] = field( + salutation: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Salutation"}, ) """Salutation""" - state_province: Optional[str] = field( + state_province: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StateProvince"}, ) """State/Province""" - street: Optional[str] = field( + street: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Street"}, ) """Street""" - street2: Optional[str] = field( + street2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Street2"}, ) """Street""" - zip_postcode: Optional[str] = field( + zip_postcode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ZipPostcode"}, ) """Zip/Postcode""" @@ -1566,295 +1989,351 @@ class SelectEntryApplicationInput: Get Entry Application """ - return_empty_array_on_no_result: Optional[bool] = field( + return_empty_array_on_no_result: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_returnEmptyArrayOnNoResult"}, ) """ Determines whether an empty array should be returned when there is no result. """ - page_size: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageSize"}, - ) + page_size: int = dataclass_field(metadata={"wire_name": "_pageSize"}) """Maximum number of records to return.""" - page_index: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageIndex"}, - ) + page_index: int = dataclass_field(metadata={"wire_name": "_pageIndex"}) """Index of the first record to return.""" - orderby: Optional[str] = field( + orderby: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_orderby"}, ) """ Sort by one or more fields in ascending order. Fields must be separated by commas with no spaces (e.g. field1,field2). """ - allocate_option_enum: Optional[str] = field( + allocate_option_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AllocateOptionEnum"}, ) """Allocate option.""" - application_date: Optional[Dict[str, Any]] = field( + application_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ApplicationDate"}, ) - application_status_id: Optional[int] = field( + application_status_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ApplicationStatusID"}, ) """Pointer to the application status record.""" - cancel_date: Optional[Dict[str, Any]] = field( + cancel_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CancelDate"}, ) - classification_id: Optional[int] = field( + classification_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClassificationID"}, ) """Pointer to the classification record.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Application comments.""" - comments_internal: Optional[str] = field( + comments_internal: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CommentsInternal"}, ) """Internal comments.""" - complete_date: Optional[Dict[str, Any]] = field( + complete_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CompleteDate"}, ) - contract_signed_date: Optional[Dict[str, Any]] = field( + contract_signed_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractSignedDate"}, ) - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_bit3: Optional[bool] = field( + custom_bit3: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit3"}, ) """Custom boolean field value.""" - custom_bit4: Optional[bool] = field( + custom_bit4: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit4"}, ) """Custom boolean field value.""" - custom_date1: Optional[Dict[str, Any]] = field( + custom_date1: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) - custom_date2: Optional[Dict[str, Any]] = field( + custom_date2: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) - custom_date3: Optional[Dict[str, Any]] = field( + custom_date3: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate3"}, ) - custom_date4: Optional[Dict[str, Any]] = field( + custom_date4: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate4"}, ) - date_created: Optional[Dict[str, Any]] = field( + date_created: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateCreated"}, ) - date_modified: Optional[Dict[str, Any]] = field( + date_modified: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) - enquiry_date: Optional[Dict[str, Any]] = field( + enquiry_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnquiryDate"}, ) - entry_application_id: Optional[int] = field( + entry_application_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryApplicationID"}, ) """Unique ID for this entry application record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - expected_arrival_date: Optional[Dict[str, Any]] = field( + expected_arrival_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedArrivalDate"}, ) - expected_arrival_date_latest: Optional[Dict[str, Any]] = field( + expected_arrival_date_latest: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedArrivalDateLatest"}, ) - expected_departure_date: Optional[Dict[str, Any]] = field( + expected_departure_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedDepartureDate"}, ) - offered_date: Optional[Dict[str, Any]] = field( + offered_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferedDate"}, ) - offer_reply_date: Optional[Dict[str, Any]] = field( + offer_reply_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyDate"}, ) - offer_reply_enum: Optional[str] = field( + offer_reply_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyEnum"}, ) """Offer reply.""" - offer_reply_reason: Optional[str] = field( + offer_reply_reason: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyReason"}, ) """Offer reply reason.""" - offer_sent_date: Optional[Dict[str, Any]] = field( + offer_sent_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferSentDate"}, ) - portal_tracking_only: Optional[bool] = field( + portal_tracking_only: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalTrackingOnly"}, ) """Whether this application is just for the portal to track progress.""" - preference_comments: Optional[str] = field( + preference_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreferenceComments"}, ) """Preference comments.""" - rating: Optional[str] = field( + rating: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Rating"}, ) """Application rating.""" - received_date: Optional[Dict[str, Any]] = field( + received_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDate"}, ) - received_deposit: Optional[bool] = field( + received_deposit: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit"}, ) """Indicates if the deposit has been received.""" - received_deposit_waived: Optional[bool] = field( + received_deposit_waived: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositWaived"}, ) """Date deposit was waived.""" - received_deposit_payment_id: Optional[int] = field( + received_deposit_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit_PaymentID"}, ) """Pointer to the payment record for the received fee.""" - received_deposit_web_payment_id: Optional[int] = field( + received_deposit_web_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit_WebPaymentID"}, ) """Most recent fee payment that was attempted.""" - received_deposit_amount: Optional[float] = field( + received_deposit_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositAmount"}, ) """Received deposit amount.""" - received_deposit_date: Optional[Dict[str, Any]] = field( + received_deposit_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositDate"}, ) - received_fee: Optional[bool] = field( + received_fee: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee"}, ) """Indicates if the fee has been received.""" - received_fee_payment_id: Optional[int] = field( + received_fee_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee_PaymentID"}, ) """Pointer to the payment record for the received fee.""" - received_fee_web_payment_id: Optional[int] = field( + received_fee_web_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee_WebPaymentID"}, ) """Most recent fee payment that was attempted.""" - received_fee_amount: Optional[float] = field( + received_fee_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFeeAmount"}, ) """Received fee amount.""" - received_fee_date: Optional[Dict[str, Any]] = field( + received_fee_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFeeDate"}, ) - received_photo_date: Optional[Dict[str, Any]] = field( + received_photo_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedPhotoDate"}, ) - returning: Optional[bool] = field( + returning: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Returning"}, ) """Indicates if the entry has been here before and is returning.""" - room_mate_description: Optional[str] = field( + room_mate_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateDescription"}, ) """ Description the applicant can write which is displayed in the roommate module. """ - roommate_group_id: Optional[int] = field( + roommate_group_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoommateGroupID"}, ) """Pointer to the Roommate group record.""" - room_mate_group_sort_order: Optional[int] = field( + room_mate_group_sort_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateGroupSortOrder"}, ) """Order that group members should be processed in.""" - room_mate_show_in_search: Optional[bool] = field( + room_mate_show_in_search: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateShowInSearch"}, ) """Whether to include this applicant in roommate searches.""" - room_preference_comments: Optional[str] = field( + room_preference_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomPreferenceComments"}, ) """Room preference comments.""" - room_selection_number: Optional[int] = field( + room_selection_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSelectionNumber"}, ) """Room selection number.""" - room_selection_timeslot: Optional[str] = field( + room_selection_timeslot: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSelectionTimeslot"}, ) """Room selection timeslot.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - term_id: Optional[int] = field( + term_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermID"}, ) """Defines the period this application is for.""" - web: Optional[bool] = field(default=None, metadata={"wire_name": "Web"}) + web: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Web"}, + ) """Indicates if this application was created on the web.""" @@ -1864,280 +2343,334 @@ class CreateEntryApplicationInput: Create Entry Application """ - allocate_option_enum: Optional[str] = field( + allocate_option_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AllocateOptionEnum"}, ) """Allocate option.""" - application_date: Optional[str] = field( + application_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ApplicationDate"}, ) """Date of application.""" - application_status_id: Optional[int] = field( + application_status_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ApplicationStatusID"}, ) """Pointer to the application status record.""" - cancel_date: Optional[str] = field( + cancel_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CancelDate"}, ) """Cancellation date.""" - classification_id: Optional[int] = field( + classification_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClassificationID"}, ) """Pointer to the classification record.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Application comments.""" - comments_internal: Optional[str] = field( + comments_internal: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CommentsInternal"}, ) """Internal comments.""" - complete_date: Optional[str] = field( + complete_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CompleteDate"}, ) """Completion date.""" - contract_signed_date: Optional[str] = field( + contract_signed_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractSignedDate"}, ) """Date contract was signed.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_bit3: Optional[bool] = field( + custom_bit3: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit3"}, ) """Custom boolean field value.""" - custom_bit4: Optional[bool] = field( + custom_bit4: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit4"}, ) """Custom boolean field value.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date field value.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date field value.""" - custom_date3: Optional[str] = field( + custom_date3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate3"}, ) """Custom date field value.""" - custom_date4: Optional[str] = field( + custom_date4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate4"}, ) """Custom date field value.""" - enquiry_date: Optional[str] = field( + enquiry_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnquiryDate"}, ) """Date of enquiry.""" - entry_application_id: Optional[int] = field( + entry_application_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryApplicationID"}, ) """Unique ID for this entry application record.""" - entry_id: Optional[int] = field( - default=None, - metadata={"wire_name": "EntryID"}, - ) + entry_id: int = dataclass_field(metadata={"wire_name": "EntryID"}) """Pointer to the entry record.""" - expected_arrival_date: Optional[str] = field( + expected_arrival_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedArrivalDate"}, ) """Date entry is expected to arrive.""" - expected_arrival_date_latest: Optional[str] = field( + expected_arrival_date_latest: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedArrivalDateLatest"}, ) """Latest expected arrival date.""" - expected_departure_date: Optional[str] = field( + expected_departure_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedDepartureDate"}, ) """Date entry is expected to depart.""" - offered_date: Optional[str] = field( + offered_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferedDate"}, ) """Date application was offered.""" - offer_reply_date: Optional[str] = field( + offer_reply_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyDate"}, ) """Date offer was replied to.""" - offer_reply_enum: Optional[str] = field( + offer_reply_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyEnum"}, ) """Offer reply.""" - offer_reply_reason: Optional[str] = field( + offer_reply_reason: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyReason"}, ) """Offer reply reason.""" - offer_sent_date: Optional[str] = field( + offer_sent_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferSentDate"}, ) """Date offer sent.""" - portal_tracking_only: Optional[bool] = field( + portal_tracking_only: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalTrackingOnly"}, ) """Whether this application is just for the portal to track progress.""" - preference_comments: Optional[str] = field( + preference_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreferenceComments"}, ) """Preference comments.""" - rating: Optional[str] = field( + rating: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Rating"}, ) """Application rating.""" - received_date: Optional[str] = field( + received_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDate"}, ) """Date received.""" - received_deposit: Optional[bool] = field( + received_deposit: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit"}, ) """Indicates if the deposit has been received.""" - received_deposit_payment_id: Optional[int] = field( + received_deposit_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit_PaymentID"}, ) """Pointer to the payment record for the received deposit.""" - received_deposit_web_payment_id: Optional[int] = field( + received_deposit_web_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit_WebPaymentID"}, ) """Most recent deposit payment that was attempted.""" - received_deposit_amount: Optional[float] = field( + received_deposit_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositAmount"}, ) """Received deposit amount.""" - received_deposit_date: Optional[str] = field( + received_deposit_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositDate"}, ) """Date deposit was received.""" - received_deposit_waived: Optional[bool] = field( + received_deposit_waived: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositWaived"}, ) """Date deposit was waived.""" - received_fee: Optional[bool] = field( + received_fee: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee"}, ) """Indicates if the fee has been received.""" - received_fee_payment_id: Optional[int] = field( + received_fee_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee_PaymentID"}, ) """Pointer to the payment record for the received fee.""" - received_fee_web_payment_id: Optional[int] = field( + received_fee_web_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee_WebPaymentID"}, ) """Most recent fee payment that was attempted.""" - received_fee_amount: Optional[float] = field( + received_fee_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFeeAmount"}, ) """Received fee amount.""" - received_fee_date: Optional[str] = field( + received_fee_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFeeDate"}, ) """Date fee was received.""" - received_photo_date: Optional[str] = field( + received_photo_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedPhotoDate"}, ) """Date photo was received.""" - returning: Optional[bool] = field( + returning: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Returning"}, ) """Indicates if the entry has been here before and is returning.""" - room_mate_description: Optional[str] = field( + room_mate_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateDescription"}, ) """ Description the applicant can write which is displayed in the roommate module. """ - roommate_group_id: Optional[int] = field( + roommate_group_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoommateGroupID"}, ) """Pointer to the Roommate group record.""" - room_mate_group_sort_order: Optional[int] = field( + room_mate_group_sort_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateGroupSortOrder"}, ) """Order that group members should be processed in.""" - room_mate_show_in_search: Optional[bool] = field( + room_mate_show_in_search: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateShowInSearch"}, ) """Whether to include this applicant in roommate searches.""" - room_preference_comments: Optional[str] = field( + room_preference_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomPreferenceComments"}, ) """Room preference comments.""" - room_selection_number: Optional[int] = field( + room_selection_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSelectionNumber"}, ) """Room selection number.""" - room_selection_timeslot: Optional[str] = field( + room_selection_timeslot: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSelectionTimeslot"}, ) """Room selection timeslot.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - term_id: Optional[int] = field( + term_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermID"}, ) """Defines the period this application is for.""" - web: Optional[bool] = field(default=None, metadata={"wire_name": "Web"}) + web: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Web"}, + ) """Indicates if this application was created on the web.""" @@ -2147,280 +2680,338 @@ class CreateEntryApplicationResponse: Response for Create Entry Application """ - allocate_option_enum: Optional[str] = field( + allocate_option_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AllocateOptionEnum"}, ) """Allocate option.""" - application_date: Optional[str] = field( + application_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ApplicationDate"}, ) """Date of application.""" - application_status_id: Optional[int] = field( + application_status_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ApplicationStatusID"}, ) """Pointer to the application status record.""" - cancel_date: Optional[str] = field( + cancel_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CancelDate"}, ) """Cancellation date.""" - classification_id: Optional[int] = field( + classification_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClassificationID"}, ) """Pointer to the classification record.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Application comments.""" - comments_internal: Optional[str] = field( + comments_internal: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CommentsInternal"}, ) """Internal comments.""" - complete_date: Optional[str] = field( + complete_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CompleteDate"}, ) """Completion date.""" - contract_signed_date: Optional[str] = field( + contract_signed_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractSignedDate"}, ) """Date contract was signed.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_bit3: Optional[bool] = field( + custom_bit3: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit3"}, ) """Custom boolean field value.""" - custom_bit4: Optional[bool] = field( + custom_bit4: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit4"}, ) """Custom boolean field value.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date field value.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date field value.""" - custom_date3: Optional[str] = field( + custom_date3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate3"}, ) """Custom date field value.""" - custom_date4: Optional[str] = field( + custom_date4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate4"}, ) """Custom date field value.""" - entry_application_id: Optional[int] = field( + entry_application_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryApplicationID"}, ) """Unique ID for this entry application record.""" - enquiry_date: Optional[str] = field( + enquiry_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnquiryDate"}, ) """Date of enquiry.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - expected_arrival_date: Optional[str] = field( + expected_arrival_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedArrivalDate"}, ) """Date entry is expected to arrive.""" - expected_arrival_date_latest: Optional[str] = field( + expected_arrival_date_latest: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedArrivalDateLatest"}, ) """Latest expected arrival date.""" - expected_departure_date: Optional[str] = field( + expected_departure_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedDepartureDate"}, ) """Date entry is expected to depart.""" - offered_date: Optional[str] = field( + offered_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferedDate"}, ) """Date application was offered.""" - offer_reply_date: Optional[str] = field( + offer_reply_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyDate"}, ) """Date offer was replied to.""" - offer_reply_enum: Optional[str] = field( + offer_reply_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyEnum"}, ) """Offer reply.""" - offer_reply_reason: Optional[str] = field( + offer_reply_reason: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyReason"}, ) """Offer reply reason.""" - offer_sent_date: Optional[str] = field( + offer_sent_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferSentDate"}, ) """Date offer sent.""" - portal_tracking_only: Optional[bool] = field( + portal_tracking_only: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalTrackingOnly"}, ) """Whether this application is just for the portal to track progress.""" - preference_comments: Optional[str] = field( + preference_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreferenceComments"}, ) """Preference comments.""" - rating: Optional[str] = field( + rating: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Rating"}, ) """Application rating.""" - received_date: Optional[str] = field( + received_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDate"}, ) """Date received.""" - received_deposit: Optional[bool] = field( + received_deposit: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit"}, ) """Indicates if the deposit has been received.""" - received_deposit_payment_id: Optional[int] = field( + received_deposit_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit_PaymentID"}, ) """Pointer to the payment record for the received deposit.""" - received_deposit_web_payment_id: Optional[int] = field( + received_deposit_web_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit_WebPaymentID"}, ) """Most recent deposit payment that was attempted.""" - received_deposit_amount: Optional[float] = field( + received_deposit_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositAmount"}, ) """Received deposit amount.""" - received_deposit_date: Optional[str] = field( + received_deposit_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositDate"}, ) """Date deposit was received.""" - received_deposit_waived: Optional[bool] = field( + received_deposit_waived: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositWaived"}, ) """Date deposit was waived.""" - received_fee: Optional[bool] = field( + received_fee: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee"}, ) """Indicates if the fee has been received.""" - received_fee_payment_id: Optional[int] = field( + received_fee_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee_PaymentID"}, ) """Pointer to the payment record for the received fee.""" - received_fee_web_payment_id: Optional[int] = field( + received_fee_web_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee_WebPaymentID"}, ) """Most recent fee payment that was attempted.""" - received_fee_amount: Optional[float] = field( + received_fee_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFeeAmount"}, ) """Received fee amount.""" - received_fee_date: Optional[str] = field( + received_fee_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFeeDate"}, ) """Date fee was received.""" - received_photo_date: Optional[str] = field( + received_photo_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedPhotoDate"}, ) """Date photo was received.""" - returning: Optional[bool] = field( + returning: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Returning"}, ) """Indicates if the entry has been here before and is returning.""" - room_mate_description: Optional[str] = field( + room_mate_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateDescription"}, ) """ Description the applicant can write which is displayed in the roommate module. """ - roommate_group_id: Optional[int] = field( + roommate_group_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoommateGroupID"}, ) """Pointer to the Roommate group record.""" - room_mate_group_sort_order: Optional[int] = field( + room_mate_group_sort_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateGroupSortOrder"}, ) """Order that group members should be processed in.""" - room_mate_show_in_search: Optional[bool] = field( + room_mate_show_in_search: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateShowInSearch"}, ) """Whether to include this applicant in roommate searches.""" - room_preference_comments: Optional[str] = field( + room_preference_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomPreferenceComments"}, ) """Room preference comments.""" - room_selection_number: Optional[int] = field( + room_selection_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSelectionNumber"}, ) """Room selection number.""" - room_selection_timeslot: Optional[str] = field( + room_selection_timeslot: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSelectionTimeslot"}, ) """Room selection timeslot.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - term_id: Optional[int] = field( + term_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermID"}, ) """Defines the period this application is for.""" - web: Optional[bool] = field(default=None, metadata={"wire_name": "Web"}) + web: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Web"}, + ) """Indicates if this application was created on the web.""" @@ -2430,280 +3021,338 @@ class UpdateEntryApplicationInput: Update Entry Application """ - allocate_option_enum: Optional[str] = field( + allocate_option_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AllocateOptionEnum"}, ) """Allocate option.""" - application_date: Optional[str] = field( + application_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ApplicationDate"}, ) """Date of application.""" - application_status_id: Optional[int] = field( + application_status_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ApplicationStatusID"}, ) """Pointer to the application status record.""" - cancel_date: Optional[str] = field( + cancel_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CancelDate"}, ) """Cancellation date.""" - classification_id: Optional[int] = field( + classification_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClassificationID"}, ) """Pointer to the classification record.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Application comments.""" - comments_internal: Optional[str] = field( + comments_internal: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CommentsInternal"}, ) """Internal comments.""" - complete_date: Optional[str] = field( + complete_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CompleteDate"}, ) """Completion date.""" - contract_signed_date: Optional[str] = field( + contract_signed_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractSignedDate"}, ) """Date contract was signed.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_bit3: Optional[bool] = field( + custom_bit3: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit3"}, ) """Custom boolean field value.""" - custom_bit4: Optional[bool] = field( + custom_bit4: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit4"}, ) """Custom boolean field value.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date field value.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date field value.""" - custom_date3: Optional[str] = field( + custom_date3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate3"}, ) """Custom date field value.""" - custom_date4: Optional[str] = field( + custom_date4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate4"}, ) """Custom date field value.""" - entry_application_id: Optional[int] = field( + entry_application_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryApplicationID"}, ) """Unique ID for this entry application record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - enquiry_date: Optional[str] = field( + enquiry_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnquiryDate"}, ) """Date of enquiry.""" - expected_arrival_date: Optional[str] = field( + expected_arrival_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedArrivalDate"}, ) """Date entry is expected to arrive.""" - expected_arrival_date_latest: Optional[str] = field( + expected_arrival_date_latest: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedArrivalDateLatest"}, ) """Latest expected arrival date.""" - expected_departure_date: Optional[str] = field( + expected_departure_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedDepartureDate"}, ) """Date entry is expected to depart.""" - offered_date: Optional[str] = field( + offered_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferedDate"}, ) """Date application was offered.""" - offer_reply_date: Optional[str] = field( + offer_reply_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyDate"}, ) """Date offer was replied to.""" - offer_reply_enum: Optional[str] = field( + offer_reply_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyEnum"}, ) """Offer reply.""" - offer_reply_reason: Optional[str] = field( + offer_reply_reason: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyReason"}, ) """Offer reply reason.""" - offer_sent_date: Optional[str] = field( + offer_sent_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferSentDate"}, ) """Date offer sent.""" - portal_tracking_only: Optional[bool] = field( + portal_tracking_only: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalTrackingOnly"}, ) """Whether this application is just for the portal to track progress.""" - preference_comments: Optional[str] = field( + preference_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreferenceComments"}, ) """Preference comments.""" - rating: Optional[str] = field( + rating: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Rating"}, ) """Application rating.""" - received_date: Optional[str] = field( + received_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDate"}, ) """Date received.""" - received_deposit: Optional[bool] = field( + received_deposit: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit"}, ) """Indicates if the deposit has been received.""" - received_deposit_payment_id: Optional[int] = field( + received_deposit_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit_PaymentID"}, ) """Pointer to the payment record for the received deposit.""" - received_deposit_web_payment_id: Optional[int] = field( + received_deposit_web_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit_WebPaymentID"}, ) """Most recent deposit payment that was attempted.""" - received_deposit_amount: Optional[float] = field( + received_deposit_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositAmount"}, ) """Received deposit amount.""" - received_deposit_date: Optional[str] = field( + received_deposit_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositDate"}, ) """Date deposit was received.""" - received_deposit_waived: Optional[bool] = field( + received_deposit_waived: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositWaived"}, ) """Date deposit was waived.""" - received_fee: Optional[bool] = field( + received_fee: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee"}, ) """Indicates if the fee has been received.""" - received_fee_payment_id: Optional[int] = field( + received_fee_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee_PaymentID"}, ) """Pointer to the payment record for the received fee.""" - received_fee_web_payment_id: Optional[int] = field( + received_fee_web_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee_WebPaymentID"}, ) """Most recent fee payment that was attempted.""" - received_fee_amount: Optional[float] = field( + received_fee_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFeeAmount"}, ) """Received fee amount.""" - received_fee_date: Optional[str] = field( + received_fee_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFeeDate"}, ) """Date fee was received.""" - received_photo_date: Optional[str] = field( + received_photo_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedPhotoDate"}, ) """Date photo was received.""" - returning: Optional[bool] = field( + returning: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Returning"}, ) """Indicates if the entry has been here before and is returning.""" - room_mate_description: Optional[str] = field( + room_mate_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateDescription"}, ) """ Description the applicant can write which is displayed in the roommate module. """ - roommate_group_id: Optional[int] = field( + roommate_group_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoommateGroupID"}, ) """Pointer to the Roommate group record.""" - room_mate_group_sort_order: Optional[int] = field( + room_mate_group_sort_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateGroupSortOrder"}, ) """Order that group members should be processed in.""" - room_mate_show_in_search: Optional[bool] = field( + room_mate_show_in_search: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateShowInSearch"}, ) """Whether to include this applicant in roommate searches.""" - room_preference_comments: Optional[str] = field( + room_preference_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomPreferenceComments"}, ) """Room preference comments.""" - room_selection_number: Optional[int] = field( + room_selection_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSelectionNumber"}, ) """Room selection number.""" - room_selection_timeslot: Optional[str] = field( + room_selection_timeslot: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSelectionTimeslot"}, ) """Room selection timeslot.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - term_id: Optional[int] = field( + term_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermID"}, ) """Defines the period this application is for.""" - web: Optional[bool] = field(default=None, metadata={"wire_name": "Web"}) + web: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Web"}, + ) """Indicates if this application was created on the web.""" @@ -2713,280 +3362,338 @@ class UpdateEntryApplicationResponse: Response for Update Entry Application """ - allocate_option_enum: Optional[str] = field( + allocate_option_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AllocateOptionEnum"}, ) """Allocate option.""" - application_date: Optional[str] = field( + application_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ApplicationDate"}, ) """Date of application.""" - application_status_id: Optional[int] = field( + application_status_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ApplicationStatusID"}, ) """Pointer to the application status record.""" - cancel_date: Optional[str] = field( + cancel_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CancelDate"}, ) """Cancellation date.""" - classification_id: Optional[int] = field( + classification_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClassificationID"}, ) """Pointer to the classification record.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Application comments.""" - comments_internal: Optional[str] = field( + comments_internal: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CommentsInternal"}, ) """Internal comments.""" - complete_date: Optional[str] = field( + complete_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CompleteDate"}, ) """Completion date.""" - contract_signed_date: Optional[str] = field( + contract_signed_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractSignedDate"}, ) """Date contract was signed.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_bit3: Optional[bool] = field( + custom_bit3: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit3"}, ) """Custom boolean field value.""" - custom_bit4: Optional[bool] = field( + custom_bit4: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit4"}, ) """Custom boolean field value.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date field value.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date field value.""" - custom_date3: Optional[str] = field( + custom_date3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate3"}, ) """Custom date field value.""" - custom_date4: Optional[str] = field( + custom_date4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate4"}, ) """Custom date field value.""" - entry_application_id: Optional[int] = field( + entry_application_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryApplicationID"}, ) """Unique ID for this entry application record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - enquiry_date: Optional[str] = field( + enquiry_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnquiryDate"}, ) """Date of enquiry.""" - expected_arrival_date: Optional[str] = field( + expected_arrival_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedArrivalDate"}, ) """Date entry is expected to arrive.""" - expected_arrival_date_latest: Optional[str] = field( + expected_arrival_date_latest: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedArrivalDateLatest"}, ) """Latest expected arrival date.""" - expected_departure_date: Optional[str] = field( + expected_departure_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedDepartureDate"}, ) """Date entry is expected to depart.""" - offered_date: Optional[str] = field( + offered_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferedDate"}, ) """Date application was offered.""" - offer_reply_date: Optional[str] = field( + offer_reply_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyDate"}, ) """Date offer was replied to.""" - offer_reply_enum: Optional[str] = field( + offer_reply_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyEnum"}, ) """Offer reply.""" - offer_reply_reason: Optional[str] = field( + offer_reply_reason: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferReplyReason"}, ) """Offer reply reason.""" - offer_sent_date: Optional[str] = field( + offer_sent_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OfferSentDate"}, ) """Date offer sent.""" - portal_tracking_only: Optional[bool] = field( + portal_tracking_only: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PortalTrackingOnly"}, ) """Whether this application is just for the portal to track progress.""" - preference_comments: Optional[str] = field( + preference_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreferenceComments"}, ) """Preference comments.""" - rating: Optional[str] = field( + rating: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Rating"}, ) """Application rating.""" - received_date: Optional[str] = field( + received_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDate"}, ) """Date received.""" - received_deposit: Optional[bool] = field( + received_deposit: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit"}, ) """Indicates if the deposit has been received.""" - received_deposit_payment_id: Optional[int] = field( + received_deposit_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit_PaymentID"}, ) """Pointer to the payment record for the received deposit.""" - received_deposit_web_payment_id: Optional[int] = field( + received_deposit_web_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDeposit_WebPaymentID"}, ) """Most recent deposit payment that was attempted.""" - received_deposit_amount: Optional[float] = field( + received_deposit_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositAmount"}, ) """Received deposit amount.""" - received_deposit_date: Optional[str] = field( + received_deposit_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositDate"}, ) """Date deposit was received.""" - received_deposit_waived: Optional[bool] = field( + received_deposit_waived: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedDepositWaived"}, ) """Date deposit was waived.""" - received_fee: Optional[bool] = field( + received_fee: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee"}, ) """Indicates if the fee has been received.""" - received_fee_payment_id: Optional[int] = field( + received_fee_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee_PaymentID"}, ) """Pointer to the payment record for the received fee.""" - received_fee_web_payment_id: Optional[int] = field( + received_fee_web_payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFee_WebPaymentID"}, ) """Most recent fee payment that was attempted.""" - received_fee_amount: Optional[float] = field( + received_fee_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFeeAmount"}, ) """Received fee amount.""" - received_fee_date: Optional[str] = field( + received_fee_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedFeeDate"}, ) """Date fee was received.""" - received_photo_date: Optional[str] = field( + received_photo_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReceivedPhotoDate"}, ) """Date photo was received.""" - returning: Optional[bool] = field( + returning: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Returning"}, ) """Indicates if the entry has been here before and is returning.""" - room_mate_description: Optional[str] = field( + room_mate_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateDescription"}, ) """ Description the applicant can write which is displayed in the roommate module. """ - roommate_group_id: Optional[int] = field( + roommate_group_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoommateGroupID"}, ) """Pointer to the Roommate group record.""" - room_mate_group_sort_order: Optional[int] = field( + room_mate_group_sort_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateGroupSortOrder"}, ) """Order that group members should be processed in.""" - room_mate_show_in_search: Optional[bool] = field( + room_mate_show_in_search: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomMateShowInSearch"}, ) """Whether to include this applicant in roommate searches.""" - room_preference_comments: Optional[str] = field( + room_preference_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomPreferenceComments"}, ) """Room preference comments.""" - room_selection_number: Optional[int] = field( + room_selection_number: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSelectionNumber"}, ) """Room selection number.""" - room_selection_timeslot: Optional[str] = field( + room_selection_timeslot: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSelectionTimeslot"}, ) """Room selection timeslot.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - term_id: Optional[int] = field( + term_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermID"}, ) """Defines the period this application is for.""" - web: Optional[bool] = field(default=None, metadata={"wire_name": "Web"}) + web: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Web"}, + ) """Indicates if this application was created on the web.""" @@ -2996,264 +3703,314 @@ class SelectTermSessionInput: Get Term Session """ - return_empty_array_on_no_result: Optional[bool] = field( + return_empty_array_on_no_result: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_returnEmptyArrayOnNoResult"}, ) """ Determines whether an empty array should be returned when there is no result. """ - page_size: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageSize"}, - ) + page_size: int = dataclass_field(metadata={"wire_name": "_pageSize"}) """Maximum number of records to return.""" - page_index: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageIndex"}, - ) + page_index: int = dataclass_field(metadata={"wire_name": "_pageIndex"}) """Index of the first record to return.""" - orderby: Optional[str] = field( + orderby: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_orderby"}, ) """ Sort by one or more fields in ascending order. Fields must be separated by commas with no spaces (e.g. field1,field2). """ - booking_type_id: Optional[int] = field( + booking_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingTypeID"}, ) """Pointer to the booking type record.""" - cancel_booking_default_end_booking_reason_id: Optional[int] = field( + cancel_booking_default_end_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CancelBookingDefaultEnd_BookingReasonID"}, ) """The default booking end reason when cancelling a booking.""" - cancel_booking_update_end_booking_reason_boolean_ask_enum: Optional[str] = field( + cancel_booking_update_end_booking_reason_boolean_ask_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CancelBookingUpdateEndBookingReason_BooleanAskEnum"}, ) """Update booking end reason on booking cancel.""" - check_in_date: Optional[Dict[str, Any]] = field( + check_in_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInDate"}, ) - check_in_date_actual_decrease_boolean_ask_enum: Optional[str] = field( + check_in_date_actual_decrease_boolean_ask_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInDateActualDecrease_BooleanAskEnum"}, ) """ Update CheckInDateActual if check-in date moves backward (in the past). """ - check_in_date_actual_increase_boolean_ask_enum: Optional[str] = field( + check_in_date_actual_increase_boolean_ask_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInDateActualIncrease_BooleanAskEnum"}, ) """ Update CheckInDateActual if check-in date moves forward (in the future). """ - check_in_default_start_booking_reason_id: Optional[int] = field( + check_in_default_start_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInDefaultStart_BookingReasonID"}, ) """The default booking start reason when checking in.""" - check_in_update_start_booking_reason_boolean_ask_enum: Optional[str] = field( + check_in_update_start_booking_reason_boolean_ask_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInUpdateStartBookingReason_BooleanAskEnum"}, ) """Update booking start reason on check-in.""" - check_out_date: Optional[Dict[str, Any]] = field( + check_out_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutDate"}, ) - check_out_date_actual_decrease_boolean_ask_enum: Optional[str] = field( + check_out_date_actual_decrease_boolean_ask_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutDateActualDecrease_BooleanAskEnum"}, ) """ Update CheckOutDateActual if check-in date moves backward (in the past). """ - check_out_date_actual_increase_boolean_ask_enum: Optional[str] = field( + check_out_date_actual_increase_boolean_ask_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutDateActualIncrease_BooleanAskEnum"}, ) """ Update CheckOutDateActual if check-in date moves forward (in the future). """ - check_out_default_end_booking_reason_id: Optional[int] = field( + check_out_default_end_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutDefaultEnd_BookingReasonID"}, ) """The default booking end reason when checking out.""" - check_out_update_end_booking_reason_boolean_ask_enum: Optional[str] = field( + check_out_update_end_booking_reason_boolean_ask_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutUpdateEndBookingReason_BooleanAskEnum"}, ) """Update booking end reason on check-out.""" - contract_date_check_in_decrease_boolean_ask_enum: Optional[str] = field( + contract_date_check_in_decrease_boolean_ask_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateCheckInDecrease_BooleanAskEnum"}, ) """Update Charge Dates if check-in date moves backward (in the past).""" - contract_date_check_in_increase_boolean_ask_enum: Optional[str] = field( + contract_date_check_in_increase_boolean_ask_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateCheckInIncrease_BooleanAskEnum"}, ) """Update Charge Dates if check-in date moves forward (in the future).""" - contract_date_check_out_decrease_boolean_ask_enum: Optional[str] = field( + contract_date_check_out_decrease_boolean_ask_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateCheckOutDecrease_BooleanAskEnum"}, ) """Update Charge Dates if check-out date moves backward (in the past).""" - contract_date_check_out_increase_boolean_ask_enum: Optional[str] = field( + contract_date_check_out_increase_boolean_ask_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateCheckOutIncrease_BooleanAskEnum"}, ) """Update Charge Dates if check-out date moves forward (in the future).""" - contract_date_end: Optional[Dict[str, Any]] = field( + contract_date_end: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateEnd"}, ) - contract_date_start: Optional[Dict[str, Any]] = field( + contract_date_start: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateStart"}, ) - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_date1: Optional[Dict[str, Any]] = field( + custom_date1: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) - custom_date2: Optional[Dict[str, Any]] = field( + custom_date2: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string field value.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string field value.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string field value.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string field value.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string field value.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string field value.""" - date_modified: Optional[Dict[str, Any]] = field( + date_modified: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """Term description.""" - end_booking_reason_id: Optional[int] = field( + end_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "End_BookingReasonID"}, ) """Pointer to the end booking reason record.""" - entry_status_enum: Optional[str] = field( + entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryStatusEnum"}, ) """Entry status.""" - e_t_a: Optional[str] = field(default=None, metadata={"wire_name": "ETA"}) + e_t_a: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETA"}, + ) """Minutes since midnight for estimated time of arrival.""" - e_t_d: Optional[str] = field(default=None, metadata={"wire_name": "ETD"}) + e_t_d: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETD"}, + ) """Minutes since midnight for estimated time of departure.""" - housekeeping_id: Optional[int] = field( + housekeeping_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HousekeepingID"}, ) """Pointer to the house-keeping record.""" - record_type_enum: Optional[str] = field( + record_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecordTypeEnum"}, ) """Record type.""" - room_location_fixed: Optional[bool] = field( + room_location_fixed: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomLocationFixed"}, ) """Fixed room location.""" - room_location_id: Optional[int] = field( + room_location_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomLocationID"}, ) """Pointer to the address room location record.""" - room_rate_amount: Optional[float] = field( + room_rate_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateAmount"}, ) """Room rate amount.""" - room_rate_id: Optional[int] = field( + room_rate_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateID"}, ) """Pointer to the room rate record.""" - room_type_id: Optional[int] = field( + room_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomTypeID"}, ) """Pointer to the room type record.""" - start_booking_reason_id: Optional[int] = field( + start_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Start_BookingReasonID"}, ) """Pointer to the start booking reason record.""" - term_id: Optional[int] = field( + term_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermID"}, ) """Pointer to the term record.""" - term_session_code: Optional[str] = field( + term_session_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermSessionCode"}, ) """Term session code.""" - term_session_id: Optional[int] = field( + term_session_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermSessionID"}, ) """Unique ID for this term session record.""" - use_active_booking_as_template: Optional[bool] = field( + use_active_booking_as_template: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UseActiveBookingAsTemplate"}, ) """Indicates if the active booking should be used as a template.""" - web_description: Optional[str] = field( + web_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebDescription"}, ) """Term Session displayed in PortalX.""" @@ -3265,463 +4022,551 @@ class SelectEntryDetailInput: Get Entry Detail """ - return_empty_array_on_no_result: Optional[bool] = field( + return_empty_array_on_no_result: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_returnEmptyArrayOnNoResult"}, ) """ Determines whether an empty array should be returned when there is no result. """ - page_size: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageSize"}, - ) + page_size: int = dataclass_field(metadata={"wire_name": "_pageSize"}) """Maximum number of records to return.""" - page_index: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageIndex"}, - ) + page_index: int = dataclass_field(metadata={"wire_name": "_pageIndex"}) """Index of the first record to return.""" - orderby: Optional[str] = field( + orderby: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_orderby"}, ) """ Sort by one or more fields in ascending order. Fields must be separated by commas with no spaces (e.g. field1,field2). """ - academic_hold: Optional[bool] = field( + academic_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AcademicHold"}, ) """Indicates if the academic hold flag has been set.""" - account_payment_type_id: Optional[int] = field( + account_payment_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Account_PaymentTypeID"}, ) """Pointer to the payment type record.""" - account_hold: Optional[bool] = field( + account_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountHold"}, ) """Indicates if the account hold flag has been set.""" - account_bank_name: Optional[str] = field( + account_bank_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountBankName"}, ) """Account bank name.""" - account_bank_number: Optional[str] = field( + account_bank_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountBankNumber"}, ) """Account bank number.""" - account_code: Optional[str] = field( + account_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountCode"}, ) """Account code.""" - account_comments: Optional[str] = field( + account_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountComments"}, ) """Account comments.""" - account_detail1: Optional[str] = field( + account_detail1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDetail1"}, ) """Account detail.""" - account_detail2: Optional[str] = field( + account_detail2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDetail2"}, ) """Account detail.""" - account_detail3: Optional[str] = field( + account_detail3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDetail3"}, ) """Account detail.""" - account_detail4: Optional[str] = field( + account_detail4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDetail4"}, ) """Account detail.""" - account_due_date: Optional[Dict[str, Any]] = field( + account_due_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDueDate"}, ) - athlete: Optional[bool] = field( + athlete: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Athlete"}, ) """Indicates if the athlete flag has been set.""" - athlete_team: Optional[str] = field( + athlete_team: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AthleteTeam"}, ) """Athlete team.""" - attendee_status_enum: Optional[str] = field( + attendee_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AttendeeStatusEnum"}, ) """Attendee status.""" - career: Optional[str] = field( + career: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Career"}, ) """Intended career.""" - career_comments: Optional[str] = field( + career_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CareerComments"}, ) """Reasons for choosing intended career.""" - citizenship_country_id: Optional[int] = field( + citizenship_country_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Citizenship_CountryID"}, ) """Pointer to the citizenship record.""" - classification_id: Optional[int] = field( + classification_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClassificationID"}, ) """Pointer to the classification record.""" - classification_override: Optional[bool] = field( + classification_override: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClassificationOverride"}, ) """Classification override.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Comments.""" - country_of_birth_country_id: Optional[int] = field( + country_of_birth_country_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CountryOfBirth_CountryID"}, ) """Pointer to the country of birth record.""" - country_of_residence_country_id: Optional[int] = field( + country_of_residence_country_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CountryOfResidence_CountryID"}, ) """Pointer to the country of residence record.""" - cumulative_g_p_a: Optional[float] = field( + cumulative_g_p_a: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CumulativeGPA"}, ) """Cumulative GPA.""" - cumulative_hours: Optional[float] = field( + cumulative_hours: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CumulativeHours"}, ) """Cumulative hours.""" - current_g_p_a: Optional[float] = field( + current_g_p_a: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CurrentGPA"}, ) """Current GPA.""" - current_hours: Optional[float] = field( + current_hours: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CurrentHours"}, ) """Current hours.""" - current_major: Optional[str] = field( + current_major: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CurrentMajor"}, ) """The major chosen by the Entry.""" - current_minor: Optional[str] = field( + current_minor: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CurrentMinor"}, ) """The minor chosen by the Entry.""" - date_entry: Optional[Dict[str, Any]] = field( + date_entry: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateEntry"}, ) - date_exit: Optional[Dict[str, Any]] = field( + date_exit: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateExit"}, ) - date_modified: Optional[Dict[str, Any]] = field( + date_modified: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) - deceased: Optional[bool] = field( + deceased: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Deceased"}, ) """Indicates if the Entry is deceased.""" - deceased_date: Optional[Dict[str, Any]] = field( + deceased_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DeceasedDate"}, ) - dietary: Optional[str] = field( + dietary: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Dietary"}, ) """Dietary requirements.""" - disability: Optional[str] = field( + disability: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Disability"}, ) """Disability.""" - employment_details: Optional[str] = field( + employment_details: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmploymentDetails"}, ) """Employment details.""" - enrollment_class: Optional[str] = field( + enrollment_class: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentClass"}, ) """First year, freshman, sophomore, etc.""" - enrollment_level: Optional[str] = field( + enrollment_level: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentLevel"}, ) """Undergraduate, post graduate, etc.""" - enrollment_status: Optional[str] = field( + enrollment_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentStatus"}, ) """Newly admitted, current, active, etc.""" - enrollment_term: Optional[str] = field( + enrollment_term: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentTerm"}, ) """Spring, fall, post graduate, etc.""" - enrollment_year: Optional[int] = field( + enrollment_year: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentYear"}, ) """Year/Level of enrollment.""" - entry_detail_id: Optional[int] = field( + entry_detail_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryDetailID"}, ) """Unique ID for this entry detail record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - ethnicity: Optional[str] = field( + ethnicity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Ethnicity"}, ) """Ethnicity.""" - event_registration_fee_id: Optional[int] = field( + event_registration_fee_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EventRegistrationFeeID"}, ) """Pointer to the event registration fee record.""" - expected_graduation_date: Optional[Dict[str, Any]] = field( + expected_graduation_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedGraduationDate"}, ) - financial_comments: Optional[str] = field( + financial_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FinancialComments"}, ) """Financial support comments.""" - financial_support_id: Optional[int] = field( + financial_support_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FinancialSupportID"}, ) """Pointer to the financial support record.""" - hear_about_us: Optional[str] = field( + hear_about_us: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HearAboutUs"}, ) """How did the Entry hear about us.""" - honors_indicator: Optional[bool] = field( + honors_indicator: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HonorsIndicator"}, ) """Honors indicator.""" - immunizations_hold: Optional[bool] = field( + immunizations_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImmunizationsHold"}, ) """Immunizations hold.""" - incident_hold: Optional[bool] = field( + incident_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IncidentHold"}, ) """Incident hold.""" - incident_hold_comments: Optional[str] = field( + incident_hold_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IncidentHoldComments"}, ) """Incident hold comments.""" - international: Optional[bool] = field( + international: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "International"}, ) """Indicates if the Entry is considered an international student.""" - international_details: Optional[str] = field( + international_details: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InternationalDetails"}, ) """International details.""" - living_with_dependents: Optional[bool] = field( + living_with_dependents: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LivingWithDependents"}, ) """Living with dependents.""" - married: Optional[bool] = field( + married: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Married"}, ) """Indicates if the Entry is married.""" - medical: Optional[str] = field( + medical: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Medical"}, ) """Medical details.""" - nationality_id: Optional[int] = field( + nationality_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NationalityID"}, ) """Pointer to the nationality record.""" - occupation: Optional[str] = field( + occupation: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Occupation"}, ) """Occupation.""" - photo_path: Optional[str] = field( + photo_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PhotoPath"}, ) """Photo path.""" - previous_member_name: Optional[str] = field( + previous_member_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMemberName"}, ) """Previous member name.""" - previous_member_relationship: Optional[str] = field( + previous_member_relationship: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMemberRelationship"}, ) """Previous member relationship.""" - previous_membership: Optional[str] = field( + previous_membership: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMembership"}, ) """Previous membership.""" - previous_membership_years: Optional[str] = field( + previous_membership_years: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMembershipYears"}, ) """Previous membership years.""" - previous_member_years: Optional[str] = field( + previous_member_years: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMemberYears"}, ) """Previous member years.""" - profile_interests: Optional[str] = field( + profile_interests: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ProfileInterests"}, ) """Profile interests.""" - region_of_birth_id: Optional[int] = field( + region_of_birth_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RegionOfBirthID"}, ) """Pointer to the Region of birth record.""" - religion: Optional[str] = field( + religion: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Religion"}, ) """Religion.""" - residency: Optional[str] = field( + residency: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Residency"}, ) """Residency.""" - resident_status: Optional[str] = field( + resident_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResidentStatus"}, ) """Resident status.""" - resident_year: Optional[int] = field( + resident_year: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResidentYear"}, ) """Resident year.""" - situation_response_comments: Optional[str] = field( + situation_response_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseComments"}, ) """Situation response comments.""" - situation_response_detail: Optional[str] = field( + situation_response_detail: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseDetail"}, ) """Situation response detail.""" - situation_response_enum: Optional[str] = field( + situation_response_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseEnum"}, ) """Situation response.""" - situation_response_expiry_date: Optional[Dict[str, Any]] = field( + situation_response_expiry_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseExpiryDate"}, ) - situation_response_modified_date: Optional[Dict[str, Any]] = field( + situation_response_modified_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseModifiedDate"}, ) - situation_response_situation: Optional[str] = field( + situation_response_situation: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseSituation"}, ) """Situation response situation.""" - special_needs: Optional[str] = field( + special_needs: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SpecialNeeds"}, ) """Special needs.""" - staff_id: Optional[int] = field( + staff_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StaffID"}, ) """Pointer to the staff record.""" - uses_screen_reader: Optional[bool] = field( + uses_screen_reader: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UsesScreenReader"}, ) """Uses screen reader.""" - vehicle_details: Optional[str] = field( + vehicle_details: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VehicleDetails"}, ) """Vehicle details.""" - vehicle_permit: Optional[str] = field( + vehicle_permit: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VehiclePermit"}, ) """Vehicle permit.""" - vehicle_registration: Optional[str] = field( + vehicle_registration: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VehicleRegistration"}, ) """Vehicle registration.""" - veteran_status: Optional[str] = field( + veteran_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VeteranStatus"}, ) """Veteran status.""" - visa: Optional[bool] = field(default=None, metadata={"wire_name": "Visa"}) + visa: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Visa"}, + ) """Indicates if the Entry holds a visa.""" - visa_details: Optional[str] = field( + visa_details: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VisaDetails"}, ) """Visa details.""" - visitor_hold: Optional[bool] = field( + visitor_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VisitorHold"}, ) """Visitor hold.""" @@ -3733,440 +4578,531 @@ class UpdateEntryDetailInput: Update Entry Detail """ - academic_hold: Optional[bool] = field( + academic_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AcademicHold"}, ) """Indicates if the academic hold flag has been set.""" - account_payment_type_id: Optional[int] = field( + account_payment_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Account_PaymentTypeID"}, ) """Pointer to the preferred payment type record.""" - account_bank_name: Optional[str] = field( + account_bank_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountBankName"}, ) """Account bank name.""" - account_bank_number: Optional[str] = field( + account_bank_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountBankNumber"}, ) """Account bank number.""" - account_code: Optional[str] = field( + account_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountCode"}, ) """Account code.""" - account_comments: Optional[str] = field( + account_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountComments"}, ) """Account comments.""" - account_detail1: Optional[str] = field( + account_detail1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDetail1"}, ) """Account detail.""" - account_detail2: Optional[str] = field( + account_detail2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDetail2"}, ) """Account detail.""" - account_detail3: Optional[str] = field( + account_detail3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDetail3"}, ) """Account detail.""" - account_detail4: Optional[str] = field( + account_detail4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDetail4"}, ) """Account detail.""" - account_due_date: Optional[str] = field( + account_due_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDueDate"}, ) """Paid to date.""" - account_hold: Optional[bool] = field( + account_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountHold"}, ) """Indicates if the account hold flag has been set.""" - athlete: Optional[bool] = field( + athlete: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Athlete"}, ) """Indicates if the athlete flag has been set.""" - athlete_team: Optional[str] = field( + athlete_team: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AthleteTeam"}, ) """Athlete team.""" - attendee_status_enum: Optional[str] = field( + attendee_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AttendeeStatusEnum"}, ) """Attendee status.""" - career: Optional[str] = field( + career: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Career"}, ) """Intended career.""" - career_comments: Optional[str] = field( + career_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CareerComments"}, ) """Reasons for choosing intended career.""" - citizenship_country_id: Optional[int] = field( + citizenship_country_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Citizenship_CountryID"}, ) """Pointer to the citizenship record.""" - classification_id: Optional[int] = field( + classification_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClassificationID"}, ) """Pointer to the classification record.""" - classification_override: Optional[bool] = field( + classification_override: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClassificationOverride"}, ) """Classification override.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Comments.""" - country_of_birth_country_id: Optional[int] = field( + country_of_birth_country_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CountryOfBirth_CountryID"}, ) """Pointer to the country of birth record.""" - country_of_residence_country_id: Optional[int] = field( + country_of_residence_country_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CountryOfResidence_CountryID"}, ) """Pointer to the country of residence record.""" - cumulative_g_p_a: Optional[float] = field( + cumulative_g_p_a: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CumulativeGPA"}, ) """Cumulative GPA.""" - cumulative_hours: Optional[float] = field( + cumulative_hours: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CumulativeHours"}, ) """Cumulative hours.""" - current_g_p_a: Optional[float] = field( + current_g_p_a: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CurrentGPA"}, ) """Current GPA.""" - current_hours: Optional[float] = field( + current_hours: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CurrentHours"}, ) """Current hours.""" - current_major: Optional[str] = field( + current_major: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CurrentMajor"}, ) """The major chosen by the Entry.""" - current_minor: Optional[str] = field( + current_minor: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CurrentMinor"}, ) """The minor chosen by the Entry.""" - date_entry: Optional[str] = field( + date_entry: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateEntry"}, ) """Entry date.""" - date_exit: Optional[str] = field( + date_exit: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateExit"}, ) """Exit date.""" - deceased: Optional[bool] = field( + deceased: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Deceased"}, ) """Indicates if the Entry is deceased.""" - deceased_date: Optional[str] = field( + deceased_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DeceasedDate"}, ) """Deceased date.""" - dietary: Optional[str] = field( + dietary: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Dietary"}, ) """Dietary requirements.""" - disability: Optional[str] = field( + disability: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Disability"}, ) """Disability.""" - employment_details: Optional[str] = field( + employment_details: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmploymentDetails"}, ) """Employment details.""" - enrollment_class: Optional[str] = field( + enrollment_class: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentClass"}, ) """First year, freshman, sophomore, etc.""" - enrollment_level: Optional[str] = field( + enrollment_level: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentLevel"}, ) """Undergraduate, post graduate, etc.""" - enrollment_status: Optional[str] = field( + enrollment_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentStatus"}, ) """Newly admitted, current, active, etc.""" - enrollment_term: Optional[str] = field( + enrollment_term: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentTerm"}, ) """Spring, fall, post graduate, etc.""" - enrollment_year: Optional[int] = field( + enrollment_year: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentYear"}, ) """Year/Level of enrollment.""" - entry_detail_id: Optional[int] = field( + entry_detail_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryDetailID"}, ) """Unique ID for this entry detail record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - ethnicity: Optional[str] = field( + ethnicity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Ethnicity"}, ) """Ethnicity.""" - event_registration_fee_id: Optional[int] = field( + event_registration_fee_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EventRegistrationFeeID"}, ) """Pointer to the Event registration fee record.""" - expected_graduation_date: Optional[str] = field( + expected_graduation_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedGraduationDate"}, ) """Expected graduation date.""" - financial_comments: Optional[str] = field( + financial_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FinancialComments"}, ) """Financial support comments.""" - financial_support_id: Optional[int] = field( + financial_support_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FinancialSupportID"}, ) """Pointer to the financial support record.""" - hear_about_us: Optional[str] = field( + hear_about_us: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HearAboutUs"}, ) """How did the Entry hear about us.""" - honors_indicator: Optional[bool] = field( + honors_indicator: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HonorsIndicator"}, ) """Honors indicator.""" - immunizations_hold: Optional[bool] = field( + immunizations_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImmunizationsHold"}, ) """Immunizations hold.""" - incident_hold: Optional[bool] = field( + incident_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IncidentHold"}, ) """Incident hold.""" - incident_hold_comments: Optional[str] = field( + incident_hold_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IncidentHoldComments"}, ) """Incident hold comments.""" - international: Optional[bool] = field( + international: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "International"}, ) """Indicates if the Entry is considered an international student.""" - international_details: Optional[str] = field( + international_details: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InternationalDetails"}, ) """International details.""" - living_with_dependents: Optional[bool] = field( + living_with_dependents: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LivingWithDependents"}, ) """Living with dependents.""" - married: Optional[bool] = field( + married: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Married"}, ) """Indicates if the Entry is married.""" - medical: Optional[str] = field( + medical: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Medical"}, ) """Medical details.""" - nationality_id: Optional[int] = field( + nationality_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NationalityID"}, ) """Pointer to the nationality record.""" - occupation: Optional[str] = field( + occupation: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Occupation"}, ) """Occupation.""" - photo_path: Optional[str] = field( + photo_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PhotoPath"}, ) """Photo path.""" - previous_member_name: Optional[str] = field( + previous_member_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMemberName"}, ) """Previous member name.""" - previous_member_relationship: Optional[str] = field( + previous_member_relationship: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMemberRelationship"}, ) """Previous member relationship.""" - previous_membership: Optional[str] = field( + previous_membership: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMembership"}, ) """Previous membership.""" - previous_membership_years: Optional[str] = field( + previous_membership_years: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMembershipYears"}, ) """Previous membership years.""" - previous_member_years: Optional[str] = field( + previous_member_years: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMemberYears"}, ) """Previous member years.""" - profile_interests: Optional[str] = field( + profile_interests: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ProfileInterests"}, ) """Profile interests.""" - region_of_birth_id: Optional[int] = field( + region_of_birth_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RegionOfBirthID"}, ) """Pointer to the region of birth record.""" - religion: Optional[str] = field( + religion: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Religion"}, ) """Religion.""" - residency: Optional[str] = field( + residency: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Residency"}, ) """Residency.""" - resident_status: Optional[str] = field( + resident_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResidentStatus"}, ) """Resident status.""" - resident_year: Optional[int] = field( + resident_year: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResidentYear"}, ) """Resident year.""" - situation_response_comments: Optional[str] = field( + situation_response_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseComments"}, ) """Situation response comments.""" - situation_response_detail: Optional[str] = field( + situation_response_detail: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseDetail"}, ) """Situation response detail.""" - situation_response_enum: Optional[str] = field( + situation_response_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseEnum"}, ) """Situation response.""" - situation_response_expiry_date: Optional[str] = field( + situation_response_expiry_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseExpiryDate"}, ) """The date when the response ends (e.g because the emergency is over)""" - situation_response_modified_date: Optional[str] = field( + situation_response_modified_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseModifiedDate"}, ) """The date the response was last modified.""" - situation_response_situation: Optional[str] = field( + situation_response_situation: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseSituation"}, ) """Situation response situation.""" - special_needs: Optional[str] = field( + special_needs: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SpecialNeeds"}, ) """Special needs.""" - staff_id: Optional[int] = field( + staff_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StaffID"}, ) """Pointer to the staff record.""" - uses_screen_reader: Optional[bool] = field( + uses_screen_reader: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UsesScreenReader"}, ) """Uses screen reader.""" - vehicle_details: Optional[str] = field( + vehicle_details: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VehicleDetails"}, ) """Vehicle details.""" - vehicle_permit: Optional[str] = field( + vehicle_permit: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VehiclePermit"}, ) """Vehicle permit.""" - vehicle_registration: Optional[str] = field( + vehicle_registration: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VehicleRegistration"}, ) """Vehicle registration.""" - veteran_status: Optional[str] = field( + veteran_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VeteranStatus"}, ) """Veteran status.""" - visa: Optional[bool] = field(default=None, metadata={"wire_name": "Visa"}) + visa: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Visa"}, + ) """Indicates if the Entry holds a visa.""" - visa_details: Optional[str] = field( + visa_details: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VisaDetails"}, ) """Visa details.""" - visitor_hold: Optional[bool] = field( + visitor_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VisitorHold"}, ) """Visitor hold.""" @@ -4178,440 +5114,531 @@ class UpdateEntryDetailResponse: Response for Update Entry Detail """ - academic_hold: Optional[bool] = field( + academic_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AcademicHold"}, ) """Indicates if the academic hold flag has been set.""" - account_payment_type_id: Optional[int] = field( + account_payment_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Account_PaymentTypeID"}, ) """Pointer to the preferred payment type record.""" - account_bank_name: Optional[str] = field( + account_bank_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountBankName"}, ) """Account bank name.""" - account_bank_number: Optional[str] = field( + account_bank_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountBankNumber"}, ) """Account bank number.""" - account_code: Optional[str] = field( + account_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountCode"}, ) """Account code.""" - account_comments: Optional[str] = field( + account_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountComments"}, ) """Account comments.""" - account_detail1: Optional[str] = field( + account_detail1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDetail1"}, ) """Account detail.""" - account_detail2: Optional[str] = field( + account_detail2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDetail2"}, ) """Account detail.""" - account_detail3: Optional[str] = field( + account_detail3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDetail3"}, ) """Account detail.""" - account_detail4: Optional[str] = field( + account_detail4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDetail4"}, ) """Account detail.""" - account_due_date: Optional[str] = field( + account_due_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountDueDate"}, ) """Paid to date.""" - account_hold: Optional[bool] = field( + account_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountHold"}, ) """Indicates if the account hold flag has been set.""" - athlete: Optional[bool] = field( + athlete: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Athlete"}, ) """Indicates if the athlete flag has been set.""" - athlete_team: Optional[str] = field( + athlete_team: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AthleteTeam"}, ) """Athlete team.""" - attendee_status_enum: Optional[str] = field( + attendee_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AttendeeStatusEnum"}, ) """Attendee status.""" - career: Optional[str] = field( + career: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Career"}, ) """Intended career.""" - career_comments: Optional[str] = field( + career_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CareerComments"}, ) """Reasons for choosing intended career.""" - citizenship_country_id: Optional[int] = field( + citizenship_country_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Citizenship_CountryID"}, ) """Pointer to the citizenship record.""" - classification_id: Optional[int] = field( + classification_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClassificationID"}, ) """Pointer to the classification record.""" - classification_override: Optional[bool] = field( + classification_override: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ClassificationOverride"}, ) """Classification override.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Comments.""" - country_of_birth_country_id: Optional[int] = field( + country_of_birth_country_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CountryOfBirth_CountryID"}, ) """Pointer to the country of birth record.""" - country_of_residence_country_id: Optional[int] = field( + country_of_residence_country_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CountryOfResidence_CountryID"}, ) """Pointer to the country of residence record.""" - cumulative_g_p_a: Optional[float] = field( + cumulative_g_p_a: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CumulativeGPA"}, ) """Cumulative GPA.""" - cumulative_hours: Optional[float] = field( + cumulative_hours: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CumulativeHours"}, ) """Cumulative hours.""" - current_g_p_a: Optional[float] = field( + current_g_p_a: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CurrentGPA"}, ) """Current GPA.""" - current_hours: Optional[float] = field( + current_hours: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CurrentHours"}, ) """Current hours.""" - current_major: Optional[str] = field( + current_major: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CurrentMajor"}, ) """The major chosen by the Entry.""" - current_minor: Optional[str] = field( + current_minor: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CurrentMinor"}, ) """The minor chosen by the Entry.""" - date_entry: Optional[str] = field( + date_entry: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateEntry"}, ) """Entry date.""" - date_exit: Optional[str] = field( + date_exit: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateExit"}, ) """Exit date.""" - deceased: Optional[bool] = field( + deceased: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Deceased"}, ) """Indicates if the Entry is deceased.""" - deceased_date: Optional[str] = field( + deceased_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DeceasedDate"}, ) """Deceased date.""" - dietary: Optional[str] = field( + dietary: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Dietary"}, ) """Dietary requirements.""" - disability: Optional[str] = field( + disability: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Disability"}, ) """Disability.""" - employment_details: Optional[str] = field( + employment_details: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmploymentDetails"}, ) """Employment details.""" - enrollment_class: Optional[str] = field( + enrollment_class: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentClass"}, ) """First year, freshman, sophomore, etc.""" - enrollment_level: Optional[str] = field( + enrollment_level: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentLevel"}, ) """Undergraduate, post graduate, etc.""" - enrollment_status: Optional[str] = field( + enrollment_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentStatus"}, ) """Newly admitted, current, active, etc.""" - enrollment_term: Optional[str] = field( + enrollment_term: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentTerm"}, ) """Spring, fall, post graduate, etc.""" - enrollment_year: Optional[int] = field( + enrollment_year: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentYear"}, ) """Year/Level of enrollment.""" - entry_detail_id: Optional[int] = field( + entry_detail_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryDetailID"}, ) """Unique ID for this entry detail record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - ethnicity: Optional[str] = field( + ethnicity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Ethnicity"}, ) """Ethnicity.""" - event_registration_fee_id: Optional[int] = field( + event_registration_fee_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EventRegistrationFeeID"}, ) """Pointer to the event registration fee record.""" - expected_graduation_date: Optional[str] = field( + expected_graduation_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExpectedGraduationDate"}, ) """Expected graduation date.""" - financial_comments: Optional[str] = field( + financial_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FinancialComments"}, ) """Financial support comments.""" - financial_support_id: Optional[int] = field( + financial_support_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FinancialSupportID"}, ) """Pointer to the financial support fee record.""" - hear_about_us: Optional[str] = field( + hear_about_us: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HearAboutUs"}, ) """How did the Entry hear about us.""" - honors_indicator: Optional[bool] = field( + honors_indicator: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HonorsIndicator"}, ) """Honors indicator.""" - immunizations_hold: Optional[bool] = field( + immunizations_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ImmunizationsHold"}, ) """Immunizations hold.""" - incident_hold: Optional[bool] = field( + incident_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IncidentHold"}, ) """Incident hold.""" - incident_hold_comments: Optional[str] = field( + incident_hold_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IncidentHoldComments"}, ) """Incident hold comments.""" - international: Optional[bool] = field( + international: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "International"}, ) """Indicates if the Entry is considered an international student.""" - international_details: Optional[str] = field( + international_details: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InternationalDetails"}, ) """International details.""" - living_with_dependents: Optional[bool] = field( + living_with_dependents: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "LivingWithDependents"}, ) """Living with dependents.""" - married: Optional[bool] = field( + married: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Married"}, ) """Indicates if the Entry is married.""" - medical: Optional[str] = field( + medical: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Medical"}, ) """Medical details.""" - nationality_id: Optional[int] = field( + nationality_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NationalityID"}, ) """Pointer to the nationality record.""" - occupation: Optional[str] = field( + occupation: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Occupation"}, ) """Occupation.""" - photo_path: Optional[str] = field( + photo_path: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PhotoPath"}, ) """Photo path.""" - previous_member_name: Optional[str] = field( + previous_member_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMemberName"}, ) """Previous member name.""" - previous_member_relationship: Optional[str] = field( + previous_member_relationship: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMemberRelationship"}, ) """Previous member relationship.""" - previous_membership: Optional[str] = field( + previous_membership: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMembership"}, ) """Previous membership.""" - previous_membership_years: Optional[str] = field( + previous_membership_years: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMembershipYears"}, ) """Previous membership years.""" - previous_member_years: Optional[str] = field( + previous_member_years: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PreviousMemberYears"}, ) """Previous member years.""" - profile_interests: Optional[str] = field( + profile_interests: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ProfileInterests"}, ) """Profile interests.""" - region_of_birth_id: Optional[int] = field( + region_of_birth_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RegionOfBirthID"}, ) """Pointer to the region of birth record.""" - religion: Optional[str] = field( + religion: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Religion"}, ) """Religion.""" - residency: Optional[str] = field( + residency: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Residency"}, ) """Residency.""" - resident_status: Optional[str] = field( + resident_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResidentStatus"}, ) """Resident status.""" - resident_year: Optional[int] = field( + resident_year: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResidentYear"}, ) """Resident year.""" - situation_response_comments: Optional[str] = field( + situation_response_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseComments"}, ) """Situation response comments.""" - situation_response_detail: Optional[str] = field( + situation_response_detail: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseDetail"}, ) """Situation response detail.""" - situation_response_enum: Optional[str] = field( + situation_response_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseEnum"}, ) """Situation response.""" - situation_response_expiry_date: Optional[str] = field( + situation_response_expiry_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseExpiryDate"}, ) """The date when the response ends (e.g. because the emergency is over)""" - situation_response_modified_date: Optional[str] = field( + situation_response_modified_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseModifiedDate"}, ) """The date the response was last modified.""" - situation_response_situation: Optional[str] = field( + situation_response_situation: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SituationResponseSituation"}, ) """Situation response situation.""" - special_needs: Optional[str] = field( + special_needs: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SpecialNeeds"}, ) """Special needs.""" - staff_id: Optional[int] = field( + staff_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StaffID"}, ) """Pointer to the staff record.""" - uses_screen_reader: Optional[bool] = field( + uses_screen_reader: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UsesScreenReader"}, ) """Uses screen reader.""" - vehicle_details: Optional[str] = field( + vehicle_details: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VehicleDetails"}, ) """Vehicle details.""" - vehicle_permit: Optional[str] = field( + vehicle_permit: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VehiclePermit"}, ) """Vehicle permit.""" - vehicle_registration: Optional[str] = field( + vehicle_registration: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VehicleRegistration"}, ) """Vehicle registration.""" - veteran_status: Optional[str] = field( + veteran_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VeteranStatus"}, ) """Veteran status.""" - visa: Optional[bool] = field(default=None, metadata={"wire_name": "Visa"}) + visa: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Visa"}, + ) """Indicates if the Entry holds a visa.""" - visa_details: Optional[str] = field( + visa_details: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VisaDetails"}, ) """Visa details.""" - visitor_hold: Optional[bool] = field( + visitor_hold: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "VisitorHold"}, ) """Visitor hold.""" @@ -4623,191 +5650,231 @@ class SelectEntryEnrollmentInput: Get Entry Enrollment """ - return_empty_array_on_no_result: Optional[bool] = field( + return_empty_array_on_no_result: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_returnEmptyArrayOnNoResult"}, ) """ Determines whether an empty array should be returned when there is no result. """ - page_size: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageSize"}, - ) + page_size: int = dataclass_field(metadata={"wire_name": "_pageSize"}) """Maximum number of records to return.""" - page_index: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageIndex"}, - ) + page_index: int = dataclass_field(metadata={"wire_name": "_pageIndex"}) """Index of the first record to return.""" - orderby: Optional[str] = field( + orderby: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_orderby"}, ) """ Sort by one or more fields in ascending order. Fields must be separated by commas with no spaces (e.g. field1,field2). """ - campus: Optional[str] = field( + campus: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Campus"}, ) """Campus where entry is enrolled.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Enrollment comments.""" - course_id: Optional[int] = field( + course_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CourseID"}, ) """Pointer to the course record.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_date1: Optional[Dict[str, Any]] = field( + custom_date1: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) - custom_date2: Optional[Dict[str, Any]] = field( + custom_date2: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string field value.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string field value.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string field value.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string field value.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string field value.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string field value.""" - date_end: Optional[Dict[str, Any]] = field( + date_end: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateEnd"}, ) - date_modified: Optional[Dict[str, Any]] = field( + date_modified: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) - date_start: Optional[Dict[str, Any]] = field( + date_start: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateStart"}, ) - department: Optional[str] = field( + department: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Department"}, ) """Department entry is enrolled in.""" - enrollment_field: Optional[str] = field( + enrollment_field: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentField"}, ) """Field of enrollment.""" - enrollment_order: Optional[int] = field( + enrollment_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentOrder"}, ) """Enrollment order.""" - enrollment_type_enum: Optional[str] = field( + enrollment_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentTypeEnum"}, ) """Enrollment type.""" - entry_enrollment_id: Optional[int] = field( + entry_enrollment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryEnrollmentID"}, ) """Unique ID for this entry enrollment record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - faculty: Optional[str] = field( + faculty: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Faculty"}, ) """Course faculty.""" - full_time: Optional[bool] = field( + full_time: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FullTime"}, ) """Indicates if the entry is enrolled full time.""" - graduation_date: Optional[Dict[str, Any]] = field( + graduation_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GraduationDate"}, ) - institution: Optional[str] = field( + institution: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Institution"}, ) """Course institution.""" - is_enrolled: Optional[bool] = field( + is_enrolled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsEnrolled"}, ) """Indicates if the entry is enrolled.""" - major: Optional[str] = field(default=None, metadata={"wire_name": "Major"}) + major: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Major"}, + ) """Course Major.""" - major_category: Optional[str] = field( + major_category: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MajorCategory"}, ) """Major category.""" - minor: Optional[str] = field(default=None, metadata={"wire_name": "Minor"}) + minor: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Minor"}, + ) """Course Minor.""" - post_grad: Optional[bool] = field( + post_grad: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PostGrad"}, ) """Indicates if this is a post graduate course.""" - sequence: Optional[int] = field( + sequence: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sequence"}, ) """Sequence""" - subjects: Optional[str] = field( + subjects: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subjects"}, ) """The subjects the entry is enrolled in.""" - term_id: Optional[int] = field( + term_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermID"}, ) """Pointer to the term record.""" - years: Optional[str] = field(default=None, metadata={"wire_name": "Years"}) + years: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Years"}, + ) """Years enrolled.""" @@ -4817,166 +5884,205 @@ class CreateEntryEnrollmentInput: Create Entry Enrollment """ - campus: Optional[str] = field( + campus: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Campus"}, ) """Campus where entry is enrolled.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Enrollment comments.""" - course_id: Optional[int] = field( + course_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CourseID"}, ) """Pointer to the course record.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date field value.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date field value.""" - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string field value.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string field value.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string field value.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string field value.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string field value.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string field value.""" - date_end: Optional[str] = field( + date_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateEnd"}, ) """Date enrollment ends.""" - date_start: Optional[str] = field( + date_start: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateStart"}, ) """Date enrollment starts.""" - department: Optional[str] = field( + department: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Department"}, ) """Department entry is enrolled in.""" - enrollment_field: Optional[str] = field( + enrollment_field: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentField"}, ) """Field of enrollment.""" - enrollment_order: Optional[int] = field( + enrollment_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentOrder"}, ) """Enrollment order.""" - enrollment_type_enum: Optional[str] = field( + enrollment_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentTypeEnum"}, ) """Enrollment type.""" - entry_enrollment_id: Optional[int] = field( + entry_enrollment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryEnrollmentID"}, ) """Unique ID for this entry enrollment record.""" - entry_id: Optional[int] = field( - default=None, - metadata={"wire_name": "EntryID"}, - ) + entry_id: int = dataclass_field(metadata={"wire_name": "EntryID"}) """Pointer to the entry record.""" - faculty: Optional[str] = field( + faculty: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Faculty"}, ) """Course faculty.""" - full_time: Optional[bool] = field( + full_time: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FullTime"}, ) """Indicates if the entry is enrolled full time.""" - graduation_date: Optional[str] = field( + graduation_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GraduationDate"}, ) """Date of graduation.""" - institution: Optional[str] = field( + institution: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Institution"}, ) """Course institution.""" - is_enrolled: Optional[bool] = field( + is_enrolled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsEnrolled"}, ) """Indicates if the entry is enrolled.""" - major: Optional[str] = field(default=None, metadata={"wire_name": "Major"}) + major: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Major"}, + ) """Course Major.""" - major_category: Optional[str] = field( + major_category: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MajorCategory"}, ) """Major category.""" - minor: Optional[str] = field(default=None, metadata={"wire_name": "Minor"}) + minor: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Minor"}, + ) """Course Minor.""" - post_grad: Optional[bool] = field( + post_grad: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PostGrad"}, ) """Indicates if this is a post graduate course.""" - sequence: Optional[int] = field( + sequence: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sequence"}, ) """Sequence""" - subjects: Optional[str] = field( + subjects: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subjects"}, ) """The subjects the entry is enrolled in.""" - term_id: Optional[int] = field( + term_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermID"}, ) """Pointer to the term record.""" - years: Optional[str] = field(default=None, metadata={"wire_name": "Years"}) + years: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Years"}, + ) """Years enrolled.""" @@ -4986,166 +6092,209 @@ class CreateEntryEnrollmentResponse: Response for Create Entry Enrollment """ - campus: Optional[str] = field( + campus: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Campus"}, ) """Campus where entry is enrolled.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Enrollment comments.""" - course_id: Optional[int] = field( + course_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CourseID"}, ) """Pointer to the course record.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date field value.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date field value.""" - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string field value.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string field value.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string field value.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string field value.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string field value.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string field value.""" - date_end: Optional[str] = field( + date_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateEnd"}, ) """Date enrollment ends.""" - date_start: Optional[str] = field( + date_start: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateStart"}, ) """Date enrollment starts.""" - department: Optional[str] = field( + department: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Department"}, ) """Department entry is enrolled in.""" - enrollment_field: Optional[str] = field( + enrollment_field: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentField"}, ) """Field of enrollment.""" - enrollment_order: Optional[int] = field( + enrollment_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentOrder"}, ) """Enrollment order.""" - enrollment_type_enum: Optional[str] = field( + enrollment_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentTypeEnum"}, ) """Enrollment type.""" - entry_enrollment_id: Optional[int] = field( + entry_enrollment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryEnrollmentID"}, ) """Unique ID for this entry enrollment record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - faculty: Optional[str] = field( + faculty: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Faculty"}, ) """Course faculty.""" - full_time: Optional[bool] = field( + full_time: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FullTime"}, ) """Indicates if the entry is enrolled full time.""" - graduation_date: Optional[str] = field( + graduation_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GraduationDate"}, ) """Date of graduation.""" - institution: Optional[str] = field( + institution: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Institution"}, ) """Course institution.""" - is_enrolled: Optional[bool] = field( + is_enrolled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsEnrolled"}, ) """Indicates if the entry is enrolled.""" - major: Optional[str] = field(default=None, metadata={"wire_name": "Major"}) + major: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Major"}, + ) """Course Major.""" - major_category: Optional[str] = field( + major_category: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MajorCategory"}, ) """Major category.""" - minor: Optional[str] = field(default=None, metadata={"wire_name": "Minor"}) + minor: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Minor"}, + ) """Course Minor.""" - post_grad: Optional[bool] = field( + post_grad: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PostGrad"}, ) """Indicates if this is a post graduate course.""" - sequence: Optional[int] = field( + sequence: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sequence"}, ) """Sequence""" - subjects: Optional[str] = field( + subjects: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subjects"}, ) """The subjects the entry is enrolled in.""" - term_id: Optional[int] = field( + term_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermID"}, ) """Pointer to the term record.""" - years: Optional[str] = field(default=None, metadata={"wire_name": "Years"}) + years: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Years"}, + ) """Years enrolled.""" @@ -5155,166 +6304,209 @@ class UpdateEntryEnrollmentInput: Update Entry Enrollment """ - campus: Optional[str] = field( + campus: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Campus"}, ) """Campus where entry is enrolled.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Enrollment comments.""" - course_id: Optional[int] = field( + course_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CourseID"}, ) """Pointer to the course record.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date field value.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date field value.""" - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string field value.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string field value.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string field value.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string field value.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string field value.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string field value.""" - date_end: Optional[str] = field( + date_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateEnd"}, ) """Date enrollment ends.""" - date_start: Optional[str] = field( + date_start: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateStart"}, ) """Date enrollment starts.""" - department: Optional[str] = field( + department: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Department"}, ) """Department entry is enrolled in.""" - enrollment_field: Optional[str] = field( + enrollment_field: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentField"}, ) """Field of enrollment.""" - enrollment_order: Optional[int] = field( + enrollment_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentOrder"}, ) """Enrollment order.""" - enrollment_type_enum: Optional[str] = field( + enrollment_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentTypeEnum"}, ) """Enrollment type.""" - entry_enrollment_id: Optional[int] = field( + entry_enrollment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryEnrollmentID"}, ) """Unique ID for this entry enrollment record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - faculty: Optional[str] = field( + faculty: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Faculty"}, ) """Course faculty.""" - full_time: Optional[bool] = field( + full_time: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FullTime"}, ) """Indicates if the entry is enrolled full time.""" - graduation_date: Optional[str] = field( + graduation_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GraduationDate"}, ) """Date of graduation.""" - institution: Optional[str] = field( + institution: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Institution"}, ) """Course institution.""" - is_enrolled: Optional[bool] = field( + is_enrolled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsEnrolled"}, ) """Indicates if the entry is enrolled.""" - major: Optional[str] = field(default=None, metadata={"wire_name": "Major"}) + major: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Major"}, + ) """Course Major.""" - major_category: Optional[str] = field( + major_category: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MajorCategory"}, ) """Major category.""" - minor: Optional[str] = field(default=None, metadata={"wire_name": "Minor"}) + minor: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Minor"}, + ) """Course Minor.""" - post_grad: Optional[bool] = field( + post_grad: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PostGrad"}, ) """Indicates if this is a post graduate course.""" - sequence: Optional[int] = field( + sequence: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sequence"}, ) """Sequence""" - subjects: Optional[str] = field( + subjects: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subjects"}, ) """The subjects the entry is enrolled in.""" - term_id: Optional[int] = field( + term_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermID"}, ) """Pointer to the term record.""" - years: Optional[str] = field(default=None, metadata={"wire_name": "Years"}) + years: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Years"}, + ) """Years enrolled.""" @@ -5324,166 +6516,209 @@ class UpdateEntryEnrollmentResponse: Response for Update Entry Enrollment """ - campus: Optional[str] = field( + campus: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Campus"}, ) """Campus where entry is enrolled.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Enrollment comments.""" - course_id: Optional[int] = field( + course_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CourseID"}, ) """Pointer to the course record.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date field value.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date field value.""" - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string field value.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string field value.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string field value.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string field value.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string field value.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string field value.""" - date_end: Optional[str] = field( + date_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateEnd"}, ) """Date enrollment ends.""" - date_start: Optional[str] = field( + date_start: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateStart"}, ) """Date enrollment starts.""" - department: Optional[str] = field( + department: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Department"}, ) """Department entry is enrolled in.""" - enrollment_field: Optional[str] = field( + enrollment_field: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentField"}, ) """Field of enrollment.""" - enrollment_order: Optional[int] = field( + enrollment_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentOrder"}, ) """Enrollment order.""" - enrollment_type_enum: Optional[str] = field( + enrollment_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EnrollmentTypeEnum"}, ) """Enrollment type.""" - entry_enrollment_id: Optional[int] = field( + entry_enrollment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryEnrollmentID"}, ) """Unique ID for this entry enrollment record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - faculty: Optional[str] = field( + faculty: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Faculty"}, ) """Course faculty.""" - full_time: Optional[bool] = field( + full_time: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FullTime"}, ) """Indicates if the entry is enrolled full time.""" - graduation_date: Optional[str] = field( + graduation_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GraduationDate"}, ) """Date of graduation.""" - institution: Optional[str] = field( + institution: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Institution"}, ) """Course institution.""" - is_enrolled: Optional[bool] = field( + is_enrolled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsEnrolled"}, ) """Indicates if the entry is enrolled.""" - major: Optional[str] = field(default=None, metadata={"wire_name": "Major"}) + major: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Major"}, + ) """Course Major.""" - major_category: Optional[str] = field( + major_category: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MajorCategory"}, ) """Major category.""" - minor: Optional[str] = field(default=None, metadata={"wire_name": "Minor"}) + minor: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Minor"}, + ) """Course Minor.""" - post_grad: Optional[bool] = field( + post_grad: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PostGrad"}, ) """Indicates if this is a post graduate course.""" - sequence: Optional[int] = field( + sequence: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sequence"}, ) """Sequence""" - subjects: Optional[str] = field( + subjects: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subjects"}, ) """The subjects the entry is enrolled in.""" - term_id: Optional[int] = field( + term_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermID"}, ) """Pointer to the term record.""" - years: Optional[str] = field(default=None, metadata={"wire_name": "Years"}) + years: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Years"}, + ) """Years enrolled.""" @@ -5493,331 +6728,396 @@ class SelectBookingInput: Get Booking """ - return_empty_array_on_no_result: Optional[bool] = field( + return_empty_array_on_no_result: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_returnEmptyArrayOnNoResult"}, ) """ Determines whether an empty array should be returned when there is no result. """ - page_size: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageSize"}, - ) + page_size: int = dataclass_field(metadata={"wire_name": "_pageSize"}) """Maximum number of records to return.""" - page_index: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageIndex"}, - ) + page_index: int = dataclass_field(metadata={"wire_name": "_pageIndex"}) """Index of the first record to return.""" - orderby: Optional[str] = field( + orderby: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_orderby"}, ) """ Sort by one or more fields in ascending order. Fields must be separated by commas with no spaces (e.g. field1,field2). """ - additional_occupant_count: Optional[int] = field( + additional_occupant_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AdditionalOccupantCount"}, ) """The number of additional human occupants in this booking.""" - auto_allocation_detail: Optional[str] = field( + auto_allocation_detail: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AutoAllocationDetail"}, ) """Details of the auto allocation.""" - booking_id: Optional[int] = field( + booking_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingID"}, ) """Unique ID for this booking record.""" - booking_link_type_enum: Optional[str] = field( + booking_link_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingLinkTypeEnum"}, ) """Booking link type.""" - booking_type_id: Optional[int] = field( + booking_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingTypeID"}, ) """Pointer to the booking type record.""" - check_in_date: Optional[Dict[str, Any]] = field( + check_in_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInDate"}, ) - check_in_date_actual: Optional[Dict[str, Any]] = field( + check_in_date_actual: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInDateActual"}, ) - check_out_date: Optional[Dict[str, Any]] = field( + check_out_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutDate"}, ) - check_out_date_actual: Optional[Dict[str, Any]] = field( + check_out_date_actual: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutDateActual"}, ) - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Comments""" - contract_date_end: Optional[Dict[str, Any]] = field( + contract_date_end: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateEnd"}, ) - contract_date_start: Optional[Dict[str, Any]] = field( + contract_date_start: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateStart"}, ) - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_bit3: Optional[bool] = field( + custom_bit3: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit3"}, ) """Custom boolean field value.""" - custom_bit4: Optional[bool] = field( + custom_bit4: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit4"}, ) """Custom boolean field value.""" - custom_date1: Optional[Dict[str, Any]] = field( + custom_date1: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) - custom_date2: Optional[Dict[str, Any]] = field( + custom_date2: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) - custom_date3: Optional[Dict[str, Any]] = field( + custom_date3: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate3"}, ) - custom_date4: Optional[Dict[str, Any]] = field( + custom_date4: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate4"}, ) - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string field value.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string field value.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string field value.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string field value.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string field value.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string field value.""" - custom_string7: Optional[str] = field( + custom_string7: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString7"}, ) """Custom string field value.""" - custom_string8: Optional[str] = field( + custom_string8: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString8"}, ) """Custom string field value.""" - custom_string9: Optional[str] = field( + custom_string9: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString9"}, ) """Custom string field value.""" - custom_string10: Optional[str] = field( + custom_string10: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString10"}, ) """Custom string field value.""" - date_billed: Optional[Dict[str, Any]] = field( + date_billed: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateBilled"}, ) - date_charged_to: Optional[Dict[str, Any]] = field( + date_charged_to: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateChargedTo"}, ) - date_created: Optional[Dict[str, Any]] = field( + date_created: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateCreated"}, ) - date_modified: Optional[Dict[str, Any]] = field( + date_modified: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) - date_modified_billing: Optional[Dict[str, Any]] = field( + date_modified_billing: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModifiedBilling"}, ) - emotional_support_animal_count: Optional[int] = field( + emotional_support_animal_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmotionalSupportAnimalCount"}, ) """ The number of additional Emotional Support Animal occupants in this booking. """ - end_booking_reason_id: Optional[int] = field( + end_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "End_BookingReasonID"}, ) """The reason this booking finished.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - entry_invitation_id: Optional[int] = field( + entry_invitation_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryInvitationID"}, ) """Identifies the entry invitation that the booking is created for.""" - entry_status_enum: Optional[str] = field( + entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryStatusEnum"}, ) """The status of the booking.""" - e_t_a: Optional[str] = field(default=None, metadata={"wire_name": "ETA"}) + e_t_a: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETA"}, + ) """Minutes since midnight for estimated time of arrival.""" - e_t_d: Optional[str] = field(default=None, metadata={"wire_name": "ETD"}) + e_t_d: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETD"}, + ) """Minutes since midnight for estimated time of departure.""" - excess: Optional[float] = field( + excess: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Excess"}, ) """Amount of excess.""" - group_id: Optional[int] = field( + group_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GroupID"}, ) """Pointer to the group record.""" - housekeeping_id: Optional[int] = field( + housekeeping_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HousekeepingID"}, ) """The housekeeping rules that should be applied to this booking.""" - number_of_children: Optional[int] = field( + number_of_children: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfChildren"}, ) """The number of children in the booking.""" - number_of_children_free: Optional[int] = field( + number_of_children_free: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfChildrenFree"}, ) """The number of children that are free to stay.""" - number_of_guests: Optional[int] = field( + number_of_guests: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfGuests"}, ) """The number of guests in the booking.""" - number_of_guests_free: Optional[int] = field( + number_of_guests_free: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfGuestsFree"}, ) """The number of guests that are free to stay.""" - paid_to: Optional[Dict[str, Any]] = field( + paid_to: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PaidTo"}, ) - pet_count: Optional[int] = field( + pet_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PetCount"}, ) """The number of additional pet occupants in this booking.""" - resv_charge_to_entry: Optional[bool] = field( + resv_charge_to_entry: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResvChargeToEntry"}, ) """ Whether reservation charges are charged to the entry or group master account. """ - room_location_fixed: Optional[bool] = field( + room_location_fixed: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomLocationFixed"}, ) """ Indicates if the location was manually selected, and should not be changed by Auto Room Allocations. """ - room_location_id: Optional[int] = field( + room_location_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomLocationID"}, ) """Pointer to the room location record.""" - room_rate_amount: Optional[float] = field( + room_rate_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateAmount"}, ) """Actual dollar amount of room rate.""" - room_rate_id: Optional[int] = field( + room_rate_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateID"}, ) """Selected room rate.""" - room_space_id: Optional[int] = field( + room_space_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceID"}, ) """Pointer to the room space record.""" - room_type_id: Optional[int] = field( + room_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomTypeID"}, ) """Pointer to the room type record.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - service_animal_count: Optional[int] = field( + service_animal_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ServiceAnimalCount"}, ) """The number of additional Service Animal occupants in this booking.""" - special_requirement: Optional[str] = field( + special_requirement: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SpecialRequirement"}, ) """Special requirements for this booking.""" - start_booking_reason_id: Optional[int] = field( + start_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Start_BookingReasonID"}, ) """Reason for this booking (normal, room change etc.).""" - term_session_id: Optional[int] = field( + term_session_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermSessionID"}, ) """Pointer to the term session record.""" @@ -5829,306 +7129,368 @@ class CreateBookingInput: Create Booking """ - additional_occupant_count: Optional[int] = field( + additional_occupant_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AdditionalOccupantCount"}, ) """The number of additional human occupants in this booking.""" - auto_allocation_detail: Optional[str] = field( + auto_allocation_detail: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AutoAllocationDetail"}, ) """Details of the auto allocation.""" - booking_id: Optional[int] = field( + booking_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingID"}, ) """Unique ID for this booking record.""" - booking_link_type_enum: Optional[str] = field( + booking_link_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingLinkTypeEnum"}, ) """Booking link type.""" - booking_type_id: Optional[int] = field( + booking_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingTypeID"}, ) """Pointer to the booking type record.""" - check_in_date: Optional[str] = field( + check_in_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInDate"}, ) """Main (contract) check-in date.""" - check_in_date_actual: Optional[str] = field( + check_in_date_actual: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInDateActual"}, ) """Actual date the entry arrives.""" - check_out_date: Optional[str] = field( + check_out_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutDate"}, ) """Main (contract) check-out date.""" - check_out_date_actual: Optional[str] = field( + check_out_date_actual: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutDateActual"}, ) """Actual date the entry departs.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Comments""" - contract_date_end: Optional[str] = field( + contract_date_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateEnd"}, ) """Contact chargeable date end.""" - contract_date_start: Optional[str] = field( + contract_date_start: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateStart"}, ) """Contact chargeable date start.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_bit3: Optional[bool] = field( + custom_bit3: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit3"}, ) """Custom boolean field value.""" - custom_bit4: Optional[bool] = field( + custom_bit4: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit4"}, ) """Custom boolean field value.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date field value.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date field value.""" - custom_date3: Optional[str] = field( + custom_date3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate3"}, ) """Custom date field value.""" - custom_date4: Optional[str] = field( + custom_date4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate4"}, ) """Custom date field value.""" - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string field value.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string field value.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string field value.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string field value.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string field value.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string field value.""" - custom_string7: Optional[str] = field( + custom_string7: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString7"}, ) """Custom string field value.""" - custom_string8: Optional[str] = field( + custom_string8: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString8"}, ) """Custom string field value.""" - custom_string9: Optional[str] = field( + custom_string9: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString9"}, ) """Custom string field value.""" - custom_string10: Optional[str] = field( + custom_string10: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString10"}, ) """Custom string field value.""" - date_billed: Optional[str] = field( + date_billed: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateBilled"}, ) """Date when this booking was processed for billing.""" - date_charged_to: Optional[str] = field( + date_charged_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateChargedTo"}, ) """Date this booking has been charged up to (using reservation charges).""" - emotional_support_animal_count: Optional[int] = field( + emotional_support_animal_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmotionalSupportAnimalCount"}, ) """ The number of additional Emotional Support Animal occupants in this booking. """ - end_booking_reason_id: Optional[int] = field( + end_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "End_BookingReasonID"}, ) """The reason this booking finished.""" - entry_id: Optional[int] = field( - default=None, - metadata={"wire_name": "EntryID"}, - ) + entry_id: int = dataclass_field(metadata={"wire_name": "EntryID"}) """Pointer to the entry record.""" - entry_invitation_id: Optional[int] = field( + entry_invitation_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryInvitationID"}, ) """Identifies the entry invitation that the booking is created for.""" - entry_status_enum: Optional[str] = field( + entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryStatusEnum"}, ) """The status of the booking.""" - e_t_a: Optional[str] = field(default=None, metadata={"wire_name": "ETA"}) + e_t_a: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETA"}, + ) """Date and time of estimated arrival.""" - e_t_d: Optional[str] = field(default=None, metadata={"wire_name": "ETD"}) + e_t_d: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETD"}, + ) """Date and time of estimated departure.""" - excess: Optional[float] = field( + excess: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Excess"}, ) """Amount of excess.""" - group_id: Optional[int] = field( + group_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GroupID"}, ) """Pointer to the group record.""" - housekeeping_id: Optional[int] = field( + housekeeping_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HousekeepingID"}, ) """The housekeeping rules that should be applied to this booking.""" - number_of_children: Optional[int] = field( + number_of_children: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfChildren"}, ) """The number of children in the booking.""" - number_of_children_free: Optional[int] = field( + number_of_children_free: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfChildrenFree"}, ) """The number of children that are free to stay.""" - number_of_guests: Optional[int] = field( + number_of_guests: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfGuests"}, ) """The number of guests in the booking.""" - number_of_guests_free: Optional[int] = field( + number_of_guests_free: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfGuestsFree"}, ) """The number of guests that are free to stay.""" - paid_to: Optional[str] = field( + paid_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PaidTo"}, ) """Date the booking is paid to.""" - pet_count: Optional[int] = field( + pet_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PetCount"}, ) """The number of additional pet occupants in this booking.""" - resv_charge_to_entry: Optional[bool] = field( + resv_charge_to_entry: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResvChargeToEntry"}, ) """ Whether reservation charges are charged to the entry or group master account. """ - room_location_fixed: Optional[bool] = field( + room_location_fixed: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomLocationFixed"}, ) """ Indicates if the location was manually selected, and should not be changed by Auto Room Allocations. """ - room_location_id: Optional[int] = field( + room_location_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomLocationID"}, ) """Pointer to the room location record.""" - room_rate_amount: Optional[float] = field( + room_rate_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateAmount"}, ) """Actual dollar amount of room rate.""" - room_rate_id: Optional[int] = field( + room_rate_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateID"}, ) """Selected room rate.""" - room_space_id: Optional[int] = field( + room_space_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceID"}, ) """Pointer to the room space record.""" - room_type_id: Optional[int] = field( + room_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomTypeID"}, ) """Pointer to the room type record.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - service_animal_count: Optional[int] = field( + service_animal_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ServiceAnimalCount"}, ) """The number of additional Service Animal occupants in this booking.""" - special_requirement: Optional[str] = field( + special_requirement: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SpecialRequirement"}, ) """Special requirements for this booking.""" - start_booking_reason_id: Optional[int] = field( + start_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Start_BookingReasonID"}, ) """Reason for this booking (normal, room change etc.).""" - term_session_id: Optional[int] = field( + term_session_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermSessionID"}, ) """Pointer to the term session record.""" @@ -6140,311 +7502,378 @@ class CreateBookingResponse: Response for Create Booking """ - additional_occupant_count: Optional[int] = field( + additional_occupant_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AdditionalOccupantCount"}, ) """The number of additional human occupants in this booking.""" - auto_allocation_detail: Optional[str] = field( + auto_allocation_detail: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AutoAllocationDetail"}, ) """Details of the auto allocation.""" - booking_id: Optional[int] = field( + booking_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingID"}, ) """Unique ID for this booking record.""" - booking_link_type_enum: Optional[str] = field( + booking_link_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingLinkTypeEnum"}, ) """Booking link type.""" - booking_type_id: Optional[int] = field( + booking_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingTypeID"}, ) """Pointer to the booking type record.""" - check_in_date: Optional[str] = field( + check_in_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInDate"}, ) """Main (contract) check-in date.""" - check_in_date_actual: Optional[str] = field( + check_in_date_actual: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInDateActual"}, ) """Actual date the entry arrives.""" - check_out_date: Optional[str] = field( + check_out_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutDate"}, ) """Main (contract) check-out date.""" - check_out_date_actual: Optional[str] = field( + check_out_date_actual: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutDateActual"}, ) """Actual date the entry departs.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Comments""" - contract_date_end: Optional[str] = field( + contract_date_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateEnd"}, ) """Contact chargeable date end.""" - contract_date_start: Optional[str] = field( + contract_date_start: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateStart"}, ) """Contact chargeable date start.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_bit3: Optional[bool] = field( + custom_bit3: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit3"}, ) """Custom boolean field value.""" - custom_bit4: Optional[bool] = field( + custom_bit4: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit4"}, ) """Custom boolean field value.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date field value.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date field value.""" - custom_date3: Optional[str] = field( + custom_date3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate3"}, ) """Custom date field value.""" - custom_date4: Optional[str] = field( + custom_date4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate4"}, ) """Custom date field value.""" - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string field value.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string field value.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string field value.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string field value.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string field value.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string field value.""" - custom_string7: Optional[str] = field( + custom_string7: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString7"}, ) """Custom string field value.""" - custom_string8: Optional[str] = field( + custom_string8: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString8"}, ) """Custom string field value.""" - custom_string9: Optional[str] = field( + custom_string9: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString9"}, ) """Custom string field value.""" - custom_string10: Optional[str] = field( + custom_string10: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString10"}, ) """Custom string field value.""" - date_billed: Optional[str] = field( + date_billed: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateBilled"}, ) """Date when this booking was processed for billing.""" - date_charged_to: Optional[str] = field( + date_charged_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateChargedTo"}, ) """Date this booking has been charged up to (using reservation charges).""" - date_modified_billing: Optional[str] = field( + date_modified_billing: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModifiedBilling"}, ) """Indicates when critical booking fields are modified.""" - emotional_support_animal_count: Optional[int] = field( + emotional_support_animal_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmotionalSupportAnimalCount"}, ) """ The number of additional Emotional Support Animal occupants in this booking. """ - end_booking_reason_id: Optional[int] = field( + end_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "End_BookingReasonID"}, ) """The reason this booking finished.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - entry_invitation_id: Optional[int] = field( + entry_invitation_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryInvitationID"}, ) """Identifies the entry invitation that the booking is created for.""" - entry_status_enum: Optional[str] = field( + entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryStatusEnum"}, ) """The status of the booking.""" - e_t_a: Optional[str] = field(default=None, metadata={"wire_name": "ETA"}) + e_t_a: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETA"}, + ) """Date and time of estimated arrival.""" - e_t_d: Optional[str] = field(default=None, metadata={"wire_name": "ETD"}) + e_t_d: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETD"}, + ) """Date and time of estimated departure.""" - excess: Optional[float] = field( + excess: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Excess"}, ) """Amount of excess.""" - group_id: Optional[int] = field( + group_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GroupID"}, ) """Pointer to the group record.""" - housekeeping_id: Optional[int] = field( + housekeeping_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HousekeepingID"}, ) """The housekeeping rules that should be applied to this booking.""" - number_of_children: Optional[int] = field( + number_of_children: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfChildren"}, ) """The number of children in the booking.""" - number_of_children_free: Optional[int] = field( + number_of_children_free: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfChildrenFree"}, ) """The number of children that are free to stay.""" - number_of_guests: Optional[int] = field( + number_of_guests: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfGuests"}, ) """The number of guests in the booking.""" - number_of_guests_free: Optional[int] = field( + number_of_guests_free: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfGuestsFree"}, ) """The number of guests that are free to stay.""" - paid_to: Optional[str] = field( + paid_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PaidTo"}, ) """Date the booking is paid to.""" - pet_count: Optional[int] = field( + pet_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PetCount"}, ) """The number of additional pet occupants in this booking.""" - resv_charge_to_entry: Optional[bool] = field( + resv_charge_to_entry: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResvChargeToEntry"}, ) """ Whether reservation charges are charged to the entry or group master account. """ - room_location_fixed: Optional[bool] = field( + room_location_fixed: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomLocationFixed"}, ) """ Indicates if the location was manually selected, and should not be changed by Auto Room Allocations. """ - room_location_id: Optional[int] = field( + room_location_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomLocationID"}, ) """Pointer to the room location record.""" - room_rate_amount: Optional[float] = field( + room_rate_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateAmount"}, ) """Actual dollar amount of room rate.""" - room_rate_id: Optional[int] = field( + room_rate_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateID"}, ) """Selected room rate.""" - room_space_id: Optional[int] = field( + room_space_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceID"}, ) """Pointer to the room space record.""" - room_type_id: Optional[int] = field( + room_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomTypeID"}, ) """Pointer to the room type record.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - service_animal_count: Optional[int] = field( + service_animal_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ServiceAnimalCount"}, ) """The number of additional Service Animal occupants in this booking.""" - special_requirement: Optional[str] = field( + special_requirement: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SpecialRequirement"}, ) """Special requirements for this booking.""" - start_booking_reason_id: Optional[int] = field( + start_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Start_BookingReasonID"}, ) """Reason for this booking (normal, room change etc.).""" - term_session_id: Optional[int] = field( + term_session_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermSessionID"}, ) """Pointer to the term session record.""" @@ -6456,306 +7885,372 @@ class UpdateBookingInput: Update Booking """ - additional_occupant_count: Optional[int] = field( + additional_occupant_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AdditionalOccupantCount"}, ) """The number of additional human occupants in this booking.""" - auto_allocation_detail: Optional[str] = field( + auto_allocation_detail: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AutoAllocationDetail"}, ) """Details of the auto allocation.""" - booking_id: Optional[int] = field( + booking_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingID"}, ) """Unique ID for this booking record.""" - booking_link_type_enum: Optional[str] = field( + booking_link_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingLinkTypeEnum"}, ) """Booking link type.""" - booking_type_id: Optional[int] = field( + booking_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingTypeID"}, ) """Pointer to the booking type record.""" - check_in_date: Optional[str] = field( + check_in_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInDate"}, ) """Main (contract) check-in date.""" - check_in_date_actual: Optional[str] = field( + check_in_date_actual: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInDateActual"}, ) """Actual date the entry arrives.""" - check_out_date: Optional[str] = field( + check_out_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutDate"}, ) """Main (contract) check-out date.""" - check_out_date_actual: Optional[str] = field( + check_out_date_actual: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutDateActual"}, ) """Actual date the entry departs.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Comments""" - contract_date_end: Optional[str] = field( + contract_date_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateEnd"}, ) """Contact chargeable date end.""" - contract_date_start: Optional[str] = field( + contract_date_start: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateStart"}, ) """Contact chargeable date start.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_bit3: Optional[bool] = field( + custom_bit3: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit3"}, ) """Custom boolean field value.""" - custom_bit4: Optional[bool] = field( + custom_bit4: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit4"}, ) """Custom boolean field value.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date field value.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date field value.""" - custom_date3: Optional[str] = field( + custom_date3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate3"}, ) """Custom date field value.""" - custom_date4: Optional[str] = field( + custom_date4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate4"}, ) """Custom date field value.""" - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string field value.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string field value.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string field value.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string field value.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string field value.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string field value.""" - custom_string7: Optional[str] = field( + custom_string7: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString7"}, ) """Custom string field value.""" - custom_string8: Optional[str] = field( + custom_string8: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString8"}, ) """Custom string field value.""" - custom_string9: Optional[str] = field( + custom_string9: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString9"}, ) """Custom string field value.""" - custom_string10: Optional[str] = field( + custom_string10: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString10"}, ) """Custom string field value.""" - date_billed: Optional[str] = field( + date_billed: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateBilled"}, ) """Date when this booking was processed for billing.""" - date_charged_to: Optional[str] = field( + date_charged_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateChargedTo"}, ) """Date this booking has been charged up to (using reservation charges).""" - emotional_support_animal_count: Optional[int] = field( + emotional_support_animal_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmotionalSupportAnimalCount"}, ) """ The number of additional Emotional Support Animal occupants in this booking. """ - end_booking_reason_id: Optional[int] = field( + end_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "End_BookingReasonID"}, ) """The reason this booking finished.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - entry_invitation_id: Optional[int] = field( + entry_invitation_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryInvitationID"}, ) """Identifies the entry invitation that the booking is created for.""" - entry_status_enum: Optional[str] = field( + entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryStatusEnum"}, ) """The status of the booking.""" - e_t_a: Optional[str] = field(default=None, metadata={"wire_name": "ETA"}) + e_t_a: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETA"}, + ) """Date and time of estimated arrival.""" - e_t_d: Optional[str] = field(default=None, metadata={"wire_name": "ETD"}) + e_t_d: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETD"}, + ) """Date and time of estimated departure.""" - excess: Optional[float] = field( + excess: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Excess"}, ) """Amount of excess.""" - group_id: Optional[int] = field( + group_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GroupID"}, ) """Pointer to the group record.""" - housekeeping_id: Optional[int] = field( + housekeeping_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HousekeepingID"}, ) """The housekeeping rules that should be applied to this booking.""" - number_of_children: Optional[int] = field( + number_of_children: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfChildren"}, ) """The number of children in the booking.""" - number_of_children_free: Optional[int] = field( + number_of_children_free: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfChildrenFree"}, ) """The number of children that are free to stay.""" - number_of_guests: Optional[int] = field( + number_of_guests: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfGuests"}, ) """The number of guests in the booking.""" - number_of_guests_free: Optional[int] = field( + number_of_guests_free: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfGuestsFree"}, ) """The number of guests that are free to stay.""" - paid_to: Optional[str] = field( + paid_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PaidTo"}, ) """Date the booking is paid to.""" - pet_count: Optional[int] = field( + pet_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PetCount"}, ) """The number of additional pet occupants in this booking.""" - resv_charge_to_entry: Optional[bool] = field( + resv_charge_to_entry: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResvChargeToEntry"}, ) """ Whether reservation charges are charged to the entry or group master account. """ - room_location_fixed: Optional[bool] = field( + room_location_fixed: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomLocationFixed"}, ) """ Indicates if the location was manually selected, and should not be changed by Auto Room Allocations. """ - room_location_id: Optional[int] = field( + room_location_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomLocationID"}, ) """Pointer to the room location record.""" - room_rate_amount: Optional[float] = field( + room_rate_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateAmount"}, ) """Actual dollar amount of room rate.""" - room_rate_id: Optional[int] = field( + room_rate_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateID"}, ) """Selected room rate.""" - room_space_id: Optional[int] = field( + room_space_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceID"}, ) """Pointer to the room space record.""" - room_type_id: Optional[int] = field( + room_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomTypeID"}, ) """Pointer to the room type record.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - service_animal_count: Optional[int] = field( + service_animal_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ServiceAnimalCount"}, ) """The number of additional Service Animal occupants in this booking.""" - special_requirement: Optional[str] = field( + special_requirement: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SpecialRequirement"}, ) """Special requirements for this booking.""" - start_booking_reason_id: Optional[int] = field( + start_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Start_BookingReasonID"}, ) """Reason for this booking (normal, room change etc.).""" - term_session_id: Optional[int] = field( + term_session_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermSessionID"}, ) """Pointer to the term session record.""" @@ -6767,311 +8262,378 @@ class UpdateBookingResponse: Response for Update Booking """ - additional_occupant_count: Optional[int] = field( + additional_occupant_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AdditionalOccupantCount"}, ) """The number of additional human occupants in this booking.""" - auto_allocation_detail: Optional[str] = field( + auto_allocation_detail: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AutoAllocationDetail"}, ) """Details of the auto allocation.""" - booking_id: Optional[int] = field( + booking_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingID"}, ) """Unique ID for this booking record.""" - booking_link_type_enum: Optional[str] = field( + booking_link_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingLinkTypeEnum"}, ) """Booking link type.""" - booking_type_id: Optional[int] = field( + booking_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BookingTypeID"}, ) """Pointer to the booking type record.""" - check_in_date: Optional[str] = field( + check_in_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInDate"}, ) """Main (contract) check-in date.""" - check_in_date_actual: Optional[str] = field( + check_in_date_actual: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckInDateActual"}, ) """Actual date the entry arrives.""" - check_out_date: Optional[str] = field( + check_out_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutDate"}, ) """Main (contract) check-out date.""" - check_out_date_actual: Optional[str] = field( + check_out_date_actual: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckOutDateActual"}, ) """Actual date the entry departs.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Comments""" - contract_date_end: Optional[str] = field( + contract_date_end: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateEnd"}, ) """Contact chargeable date end.""" - contract_date_start: Optional[str] = field( + contract_date_start: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDateStart"}, ) """Contact chargeable date start.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_bit3: Optional[bool] = field( + custom_bit3: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit3"}, ) """Custom boolean field value.""" - custom_bit4: Optional[bool] = field( + custom_bit4: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit4"}, ) """Custom boolean field value.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date field value.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date field value.""" - custom_date3: Optional[str] = field( + custom_date3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate3"}, ) """Custom date field value.""" - custom_date4: Optional[str] = field( + custom_date4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate4"}, ) """Custom date field value.""" - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string field value.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string field value.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string field value.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string field value.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string field value.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string field value.""" - custom_string7: Optional[str] = field( + custom_string7: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString7"}, ) """Custom string field value.""" - custom_string8: Optional[str] = field( + custom_string8: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString8"}, ) """Custom string field value.""" - custom_string9: Optional[str] = field( + custom_string9: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString9"}, ) """Custom string field value.""" - custom_string10: Optional[str] = field( + custom_string10: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString10"}, ) """Custom string field value.""" - date_billed: Optional[str] = field( + date_billed: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateBilled"}, ) """Date when this booking was processed for billing.""" - date_charged_to: Optional[str] = field( + date_charged_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateChargedTo"}, ) """Date this booking has been charged up to (using reservation charges).""" - date_modified_billing: Optional[str] = field( + date_modified_billing: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModifiedBilling"}, ) """Indicates when critical booking fields are modified.""" - emotional_support_animal_count: Optional[int] = field( + emotional_support_animal_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EmotionalSupportAnimalCount"}, ) """ The number of additional Emotional Support Animal occupants in this booking. """ - end_booking_reason_id: Optional[int] = field( + end_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "End_BookingReasonID"}, ) """The reason this booking finished.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - entry_invitation_id: Optional[int] = field( + entry_invitation_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryInvitationID"}, ) """Identifies the entry invitation that the booking is created for.""" - entry_status_enum: Optional[str] = field( + entry_status_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryStatusEnum"}, ) """The status of the booking.""" - e_t_a: Optional[str] = field(default=None, metadata={"wire_name": "ETA"}) + e_t_a: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETA"}, + ) """Date and time of estimated arrival.""" - e_t_d: Optional[str] = field(default=None, metadata={"wire_name": "ETD"}) + e_t_d: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ETD"}, + ) """Date and time of estimated departure.""" - excess: Optional[float] = field( + excess: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Excess"}, ) """Amount of excess.""" - group_id: Optional[int] = field( + group_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GroupID"}, ) """Pointer to the group record.""" - housekeeping_id: Optional[int] = field( + housekeeping_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "HousekeepingID"}, ) """The housekeeping rules that should be applied to this booking.""" - number_of_children: Optional[int] = field( + number_of_children: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfChildren"}, ) """The number of children in the booking.""" - number_of_children_free: Optional[int] = field( + number_of_children_free: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfChildrenFree"}, ) """The number of children that are free to stay.""" - number_of_guests: Optional[int] = field( + number_of_guests: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfGuests"}, ) """The number of guests in the booking.""" - number_of_guests_free: Optional[int] = field( + number_of_guests_free: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NumberOfGuestsFree"}, ) """The number of guests that are free to stay.""" - paid_to: Optional[str] = field( + paid_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PaidTo"}, ) """Date the booking is paid to.""" - pet_count: Optional[int] = field( + pet_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PetCount"}, ) """The number of additional pet occupants in this booking.""" - resv_charge_to_entry: Optional[bool] = field( + resv_charge_to_entry: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ResvChargeToEntry"}, ) """ Whether reservation charges are charged to the entry or group master account. """ - room_location_fixed: Optional[bool] = field( + room_location_fixed: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomLocationFixed"}, ) """ Indicates if the location was manually selected, and should not be changed by Auto Room Allocations. """ - room_location_id: Optional[int] = field( + room_location_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomLocationID"}, ) """Pointer to the room location record.""" - room_rate_amount: Optional[float] = field( + room_rate_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateAmount"}, ) """Actual dollar amount of room rate.""" - room_rate_id: Optional[int] = field( + room_rate_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateID"}, ) """Selected room rate.""" - room_space_id: Optional[int] = field( + room_space_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceID"}, ) """Pointer to the room space record.""" - room_type_id: Optional[int] = field( + room_type_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomTypeID"}, ) """Pointer to the room type record.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - service_animal_count: Optional[int] = field( + service_animal_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ServiceAnimalCount"}, ) """The number of additional Service Animal occupants in this booking.""" - special_requirement: Optional[str] = field( + special_requirement: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SpecialRequirement"}, ) """Special requirements for this booking.""" - start_booking_reason_id: Optional[int] = field( + start_booking_reason_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Start_BookingReasonID"}, ) """Reason for this booking (normal, room change etc.).""" - term_session_id: Optional[int] = field( + term_session_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermSessionID"}, ) """Pointer to the term session record.""" @@ -7083,138 +8645,159 @@ class SelectRoomSpaceInput: Get Room Space """ - return_empty_array_on_no_result: Optional[bool] = field( + return_empty_array_on_no_result: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_returnEmptyArrayOnNoResult"}, ) """ Determines whether an empty array should be returned when there is no result. """ - page_size: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageSize"}, - ) + page_size: int = dataclass_field(metadata={"wire_name": "_pageSize"}) """Maximum number of records to return.""" - page_index: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageIndex"}, - ) + page_index: int = dataclass_field(metadata={"wire_name": "_pageIndex"}) """Index of the first record to return.""" - orderby: Optional[str] = field( + orderby: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_orderby"}, ) """ Sort by one or more fields in ascending order. Fields must be separated by commas with no spaces (e.g. field1,field2). """ - allocate_exclude: Optional[bool] = field( + allocate_exclude: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AllocateExclude"}, ) """Room Allocation - Do not include room in allocations.""" - allocate_sort_order: Optional[int] = field( + allocate_sort_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AllocateSortOrder"}, ) """Room Allocation - Allows allocating nicer rooms first.""" - bathrooms: Optional[int] = field( + bathrooms: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Bathrooms"}, ) """The number of bathrooms available.""" - bed_capacity: Optional[int] = field( + bed_capacity: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BedCapacity"}, ) """The number of beds available.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Room space comments.""" - date_modified: Optional[Dict[str, Any]] = field( + date_modified: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """The actual room name.""" - extension_id: Optional[int] = field( + extension_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExtensionID"}, ) """Link to extension table. 0 means no phone in the room.""" - hold: Optional[bool] = field(default=None, metadata={"wire_name": "Hold"}) + hold: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Hold"}, + ) """ Space is held for any reason. Will warn the user when allocating this space. """ - networked: Optional[bool] = field( + networked: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Networked"}, ) """Indicates if the room space is networked.""" - record_type_enum: Optional[str] = field( + record_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecordTypeEnum"}, ) """Record type.""" - room_base_id: Optional[int] = field( + room_base_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomBaseID"}, ) """Pointer to the room base record.""" - room_id: Optional[int] = field( + room_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomID"}, ) """Pointer to the room record.""" - room_rate_id: Optional[int] = field( + room_rate_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateID"}, ) """Default tariff rate.""" - room_space_id: Optional[int] = field( + room_space_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceID"}, ) """Unique ID for this room space record.""" - room_space_type_enum: Optional[str] = field( + room_space_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceTypeEnum"}, ) """Room space type.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - sort_order: Optional[int] = field( + sort_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SortOrder"}, ) """Use to control where the room space is shown when part of a list.""" - street: Optional[str] = field( + street: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Street"}, ) """Street""" - street2: Optional[str] = field( + street2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Street2"}, ) """Street""" - web_description: Optional[str] = field( + web_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebDescription"}, ) """The room space displayed in the Portal.""" - zip_postcode: Optional[str] = field( + zip_postcode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ZipPostcode"}, ) """Zip/Postcode""" @@ -7226,108 +8809,132 @@ class CreateRoomSpaceInput: Create Room Space """ - allocate_exclude: Optional[bool] = field( + allocate_exclude: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AllocateExclude"}, ) """Room Allocation - Do not include room in allocations.""" - allocate_sort_order: Optional[int] = field( + allocate_sort_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AllocateSortOrder"}, ) """Room Allocation - Allows allocating nicer rooms first.""" - bathrooms: Optional[int] = field( + bathrooms: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Bathrooms"}, ) """The number of bathrooms available.""" - bed_capacity: Optional[int] = field( + bed_capacity: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BedCapacity"}, ) """The number of beds available.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Room space comments.""" - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """The actual room name.""" - extension_id: Optional[int] = field( + extension_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExtensionID"}, ) """Link to extension table. 0 means no phone in the room.""" - hold: Optional[bool] = field(default=None, metadata={"wire_name": "Hold"}) + hold: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Hold"}, + ) """ Space is held for any reason. Will warn the user when allocating this space. """ - networked: Optional[bool] = field( + networked: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Networked"}, ) """Indicates if the room space is networked.""" - record_type_enum: Optional[str] = field( + record_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecordTypeEnum"}, ) """Record type.""" - room_base_id: Optional[int] = field( + room_base_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomBaseID"}, ) """Pointer to the room base record.""" - room_id: Optional[int] = field( + room_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomID"}, ) """Pointer to the room record.""" - room_rate_id: Optional[int] = field( + room_rate_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateID"}, ) """Default tariff rate.""" - room_space_id: Optional[int] = field( + room_space_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceID"}, ) """Unique ID for this room space record.""" - room_space_type_enum: Optional[str] = field( + room_space_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceTypeEnum"}, ) """Room space type.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - sort_order: Optional[int] = field( + sort_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SortOrder"}, ) """Use to control where the room space is shown when part of a list.""" - street: Optional[str] = field( + street: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Street"}, ) """Street""" - street2: Optional[str] = field( + street2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Street2"}, ) """Street""" - web_description: Optional[str] = field( + web_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebDescription"}, ) """The room space displayed in the Portal.""" - zip_postcode: Optional[str] = field( + zip_postcode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ZipPostcode"}, ) """Zip/Postcode""" @@ -7339,108 +8946,132 @@ class CreateRoomSpaceResponse: Response for Create Room Space """ - allocate_exclude: Optional[bool] = field( + allocate_exclude: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AllocateExclude"}, ) """Room Allocation - Do not include room in allocations.""" - allocate_sort_order: Optional[int] = field( + allocate_sort_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AllocateSortOrder"}, ) """Room Allocation - allows allocating nicer rooms first.""" - bathrooms: Optional[int] = field( + bathrooms: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Bathrooms"}, ) """The number of bathrooms available.""" - bed_capacity: Optional[int] = field( + bed_capacity: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "BedCapacity"}, ) """The number of beds available.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Room space comments.""" - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """The actual room name.""" - extension_id: Optional[int] = field( + extension_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExtensionID"}, ) """Link to extension table. 0 means no phone in the room.""" - hold: Optional[bool] = field(default=None, metadata={"wire_name": "Hold"}) + hold: Optional[bool] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Hold"}, + ) """ Space is held for any reason. Will warn the user when allocating this space. """ - networked: Optional[bool] = field( + networked: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Networked"}, ) """Indicates if the room space is networked.""" - record_type_enum: Optional[str] = field( + record_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecordTypeEnum"}, ) """Record type.""" - room_base_id: Optional[int] = field( + room_base_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomBaseID"}, ) """Pointer to the room base record.""" - room_id: Optional[int] = field( + room_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomID"}, ) """Pointer to the room record.""" - room_rate_id: Optional[int] = field( + room_rate_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomRateID"}, ) """Default tariff rate.""" - room_space_id: Optional[int] = field( + room_space_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceID"}, ) """Unique ID for this room space record.""" - room_space_type_enum: Optional[str] = field( + room_space_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceTypeEnum"}, ) """Room space type.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - sort_order: Optional[int] = field( + sort_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SortOrder"}, ) """Use to control where the room space is shown when part of a list.""" - street: Optional[str] = field( + street: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Street"}, ) """Street""" - street2: Optional[str] = field( + street2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Street2"}, ) """Street""" - web_description: Optional[str] = field( + web_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebDescription"}, ) """The room space displayed in the Portal.""" - zip_postcode: Optional[str] = field( + zip_postcode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ZipPostcode"}, ) """Zip/Postcode""" @@ -7452,178 +9083,208 @@ class SelectRoomLocationInput: Get Room Location """ - return_empty_array_on_no_result: Optional[bool] = field( + return_empty_array_on_no_result: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_returnEmptyArrayOnNoResult"}, ) """ Determines whether an empty array should be returned when there is no result. """ - page_size: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageSize"}, - ) + page_size: int = dataclass_field(metadata={"wire_name": "_pageSize"}) """Maximum number of records to return.""" - page_index: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageIndex"}, - ) + page_index: int = dataclass_field(metadata={"wire_name": "_pageIndex"}) """Index of the first record to return.""" - orderby: Optional[str] = field( + orderby: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_orderby"}, ) """ Sort by one or more fields in ascending order. Fields must be separated by commas with no spaces (e.g. field1,field2). """ - allocate_sort_order: Optional[int] = field( + allocate_sort_order: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AllocateSortOrder"}, ) """Allocate sort order.""" - category_id: Optional[int] = field( + category_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CategoryID"}, ) """Pointer to the category record.""" - city: Optional[str] = field(default=None, metadata={"wire_name": "City"}) + city: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "City"}, + ) """City""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Room location comments.""" - country_id: Optional[int] = field( + country_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CountryID"}, ) """Pointer to the country record.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom boolean field value.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom boolean field value.""" - custom_date1: Optional[Dict[str, Any]] = field( + custom_date1: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) - custom_date2: Optional[Dict[str, Any]] = field( + custom_date2: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string field value.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string field value.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string field value.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string field value.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string field value.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string field value.""" - date_modified: Optional[Dict[str, Any]] = field( + date_modified: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """Room location description.""" - gender_type_enum: Optional[str] = field( + gender_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "GenderTypeEnum"}, ) """Gender type suitability.""" - lease: Optional[bool] = field( + lease: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Lease"}, ) """Indicates if the room location is leased.""" - managed_externally: Optional[bool] = field( + managed_externally: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ManagedExternally"}, ) """Indicates if the room location is managed externally.""" - non_residential: Optional[bool] = field( + non_residential: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NonResidential"}, ) """Indicates if the room location is non residential.""" - record_type_enum: Optional[str] = field( + record_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecordTypeEnum"}, ) """Record type.""" - room_location_area_id: Optional[int] = field( + room_location_area_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomLocationAreaID"}, ) """Pointer to the room location area record.""" - room_location_id: Optional[int] = field( + room_location_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomLocationID"}, ) """Unique ID for this room location record.""" - state_province: Optional[str] = field( + state_province: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StateProvince"}, ) """State/Province""" - view_on_web: Optional[bool] = field( + view_on_web: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ViewOnWeb"}, ) """Indicates if the room space is viewable on the web.""" - web_comments: Optional[str] = field( + web_comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebComments"}, ) """Comments to display if visible on the web.""" - web_description: Optional[str] = field( + web_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebDescription"}, ) """Description to display if visible on the web.""" - web_image_alt_text: Optional[str] = field( + web_image_alt_text: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebImageAltText"}, ) """Alternate text to display for the image when displayed on the web.""" - web_image_location: Optional[str] = field( + web_image_location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebImageLocation"}, ) """Path for the web image.""" - zip_postcode: Optional[str] = field( + zip_postcode: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ZipPostcode"}, ) """Zip/Postcode.""" @@ -7635,192 +9296,225 @@ class SelectTransactionInput: Get Transaction """ - return_empty_array_on_no_result: Optional[bool] = field( + return_empty_array_on_no_result: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_returnEmptyArrayOnNoResult"}, ) """ Determines whether an empty array should be returned when there is no result. """ - page_size: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageSize"}, - ) + page_size: int = dataclass_field(metadata={"wire_name": "_pageSize"}) """Maximum number of records to return.""" - page_index: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageIndex"}, - ) + page_index: int = dataclass_field(metadata={"wire_name": "_pageIndex"}) """Index of the first record to return.""" - orderby: Optional[str] = field( + orderby: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_orderby"}, ) """ Sort by one or more fields in ascending order. Fields must be separated by commas with no spaces (e.g. field1,field2). """ - amount: Optional[float] = field( + amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Amount"}, ) """The total amount for this transaction (including tax).""" - call_type_enum: Optional[str] = field( + call_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CallTypeEnum"}, ) """Call type.""" - charge_group_id: Optional[int] = field( + charge_group_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeGroupID"}, ) """Pointer to the charge group record.""" - charge_item_id: Optional[int] = field( + charge_item_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeItemID"}, ) """Pointer to the charge item record.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Transaction comments.""" - created_by_security_user_id: Optional[int] = field( + created_by_security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CreatedBy_SecurityUserID"}, ) """Pointer to the created by security user record.""" - date_modified: Optional[Dict[str, Any]] = field( + date_modified: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """Transaction description.""" - due_date: Optional[Dict[str, Any]] = field( + due_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DueDate"}, ) - duration: Optional[int] = field( + duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Duration"}, ) """Phone call duration in seconds.""" - end_of_session_id: Optional[int] = field( + end_of_session_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EndOfSessionID"}, ) """Pointer to the end of session record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - excess: Optional[float] = field( + excess: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Excess"}, ) """Excess amount.""" - extension: Optional[int] = field( + extension: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Extension"}, ) """Extension qty.""" - external_id: Optional[int] = field( + external_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExternalID"}, ) """ Stores the (unique) ID from an external system - for imported transactions. """ - external_receipt_id: Optional[str] = field( + external_receipt_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExternalReceiptID"}, ) """Pointer to the external receipt record.""" - invoice_id: Optional[int] = field( + invoice_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InvoiceID"}, ) """Pointer to the invoice record.""" - paid_from: Optional[Dict[str, Any]] = field( + paid_from: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PaidFrom"}, ) - paid_to: Optional[Dict[str, Any]] = field( + paid_to: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PaidTo"}, ) - payment_id: Optional[int] = field( + payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PaymentID"}, ) """Pointer to the payment record.""" - processed_date: Optional[Dict[str, Any]] = field( + processed_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ProcessedDate"}, ) - reference_booking_id: Optional[int] = field( + reference_booking_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reference_BookingID"}, ) """The booking (if any) that this transaction relates to.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - table_id: Optional[int] = field( + table_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableID"}, ) """Link to a referencing record (e.g. a BookingID for pro-rating).""" - table_name: Optional[str] = field( + table_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableName"}, ) """Reference link table.""" - tag: Optional[str] = field(default=None, metadata={"wire_name": "Tag"}) + tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Tag"}, + ) """Transaction tag.""" - tag_finance: Optional[str] = field( + tag_finance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TagFinance"}, ) """Finance tag.""" - tax_amount: Optional[float] = field( + tax_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TaxAmount"}, ) """Tax amount""" - tax_amount2: Optional[float] = field( + tax_amount2: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TaxAmount2"}, ) """Tax amount""" - tax_amount3: Optional[float] = field( + tax_amount3: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TaxAmount3"}, ) """Tax amount""" - term_session_id: Optional[int] = field( + term_session_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermSessionID"}, ) """Pointer to the term session record.""" - transaction_date: Optional[Dict[str, Any]] = field( + transaction_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TransactionDate"}, ) - transaction_id: Optional[int] = field( + transaction_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TransactionID"}, ) """Unique ID for this transaction record.""" - transaction_type_enum: Optional[str] = field( + transaction_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TransactionTypeEnum"}, ) """Transaction type.""" @@ -7832,162 +9526,191 @@ class CreateTransactionInput: Create Transaction """ - amount: Optional[float] = field( - default=None, - metadata={"wire_name": "Amount"}, - ) + amount: float = dataclass_field(metadata={"wire_name": "Amount"}) """The total amount for this transaction (including tax).""" - call_type_enum: Optional[str] = field( + call_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CallTypeEnum"}, ) """Call type.""" - charge_group_id: Optional[int] = field( - default=None, + charge_group_id: int = dataclass_field( metadata={"wire_name": "ChargeGroupID"}, ) """Pointer to the charge group record.""" - charge_item_id: Optional[int] = field( + charge_item_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeItemID"}, ) """This is only required for Adjustments and Charges.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Transaction comments.""" - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """Transaction description.""" - due_date: Optional[str] = field( + due_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DueDate"}, ) """Due date.""" - duration: Optional[int] = field( + duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Duration"}, ) """Phone call duration in seconds.""" - end_of_session_id: Optional[int] = field( + end_of_session_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EndOfSessionID"}, ) """Pointer to the end of session record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - excess: Optional[float] = field( + excess: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Excess"}, ) """Excess amount.""" - extension: Optional[int] = field( + extension: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Extension"}, ) """Extension qty.""" - external_id: Optional[int] = field( + external_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExternalID"}, ) """ Stores the (unique) ID from an external system - for imported transactions. """ - external_receipt_id: Optional[str] = field( + external_receipt_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExternalReceiptID"}, ) """Pointer to the external receipt record.""" - invoice_id: Optional[int] = field( + invoice_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InvoiceID"}, ) """Pointer to the invoice record.""" - paid_from: Optional[str] = field( + paid_from: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PaidFrom"}, ) """Paid from date.""" - paid_to: Optional[str] = field( + paid_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PaidTo"}, ) """Paid to date.""" - payment_id: Optional[int] = field( + payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PaymentID"}, ) """Pointer to the payment record.""" - processed_date: Optional[str] = field( + processed_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ProcessedDate"}, ) """Date transaction was processed.""" - reference_booking_id: Optional[int] = field( + reference_booking_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reference_BookingID"}, ) """The booking (if any) that this transaction relates to.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - table_id: Optional[int] = field( + table_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableID"}, ) """Link to a referencing record (e.g. a BookingID for pro-rating).""" - table_name: Optional[str] = field( + table_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableName"}, ) """Reference link table.""" - tag: Optional[str] = field(default=None, metadata={"wire_name": "Tag"}) + tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Tag"}, + ) """Transaction tag.""" - tag_finance: Optional[str] = field( + tag_finance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TagFinance"}, ) """Finance tag.""" - tax_amount: Optional[float] = field( + tax_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TaxAmount"}, ) """Tax amount""" - tax_amount2: Optional[float] = field( + tax_amount2: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TaxAmount2"}, ) """Tax amount""" - tax_amount3: Optional[float] = field( + tax_amount3: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TaxAmount3"}, ) """Tax amount""" - term_session_id: Optional[int] = field( + term_session_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermSessionID"}, ) """Pointer to the term session record.""" - transaction_date: Optional[str] = field( + transaction_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TransactionDate"}, ) """Date of the transaction.""" - transaction_id: Optional[int] = field( + transaction_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TransactionID"}, ) """Unique ID for this transaction record.""" - transaction_type_enum: Optional[str] = field( + transaction_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TransactionTypeEnum"}, ) """Transaction type.""" @@ -7999,162 +9722,197 @@ class CreateTransactionResponse: Response for Create Transaction """ - amount: Optional[float] = field( + amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Amount"}, ) """The total amount for this transaction (including tax).""" - call_type_enum: Optional[str] = field( + call_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CallTypeEnum"}, ) """Call type.""" - charge_group_id: Optional[int] = field( + charge_group_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeGroupID"}, ) """Pointer to the charge group record.""" - charge_item_id: Optional[int] = field( + charge_item_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeItemID"}, ) """Pointer to the charge item record.""" - comments: Optional[str] = field( + comments: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """Transaction comments.""" - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """Transaction description.""" - due_date: Optional[str] = field( + due_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DueDate"}, ) """Due date.""" - duration: Optional[int] = field( + duration: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Duration"}, ) """Phone call duration in seconds.""" - end_of_session_id: Optional[int] = field( + end_of_session_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EndOfSessionID"}, ) """Pointer to the end of session record.""" - entry_id: Optional[int] = field( + entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "EntryID"}, ) """Pointer to the entry record.""" - excess: Optional[float] = field( + excess: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Excess"}, ) """Excess amount.""" - extension: Optional[int] = field( + extension: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Extension"}, ) """Extension qty.""" - external_id: Optional[int] = field( + external_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExternalID"}, ) """ Stores the (unique) ID from an external system - for imported transactions. """ - external_receipt_id: Optional[str] = field( + external_receipt_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ExternalReceiptID"}, ) """Pointer to the external receipt record.""" - invoice_id: Optional[int] = field( + invoice_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "InvoiceID"}, ) """Pointer to the invoice record.""" - paid_from: Optional[str] = field( + paid_from: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PaidFrom"}, ) """Paid from date.""" - paid_to: Optional[str] = field( + paid_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PaidTo"}, ) """Paid to date.""" - payment_id: Optional[int] = field( + payment_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PaymentID"}, ) """Pointer to the payment record.""" - processed_date: Optional[str] = field( + processed_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ProcessedDate"}, ) """Date transaction was processed.""" - reference_booking_id: Optional[int] = field( + reference_booking_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Reference_BookingID"}, ) """The booking (if any) that this transaction relates to.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - table_id: Optional[int] = field( + table_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableID"}, ) """Link to a referencing record (e.g. a BookingID for pro-rating).""" - table_name: Optional[str] = field( + table_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TableName"}, ) """Reference link table.""" - tag: Optional[str] = field(default=None, metadata={"wire_name": "Tag"}) + tag: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Tag"}, + ) """Transaction tag.""" - tag_finance: Optional[str] = field( + tag_finance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TagFinance"}, ) """Finance tag.""" - tax_amount: Optional[float] = field( + tax_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TaxAmount"}, ) """Tax amount""" - tax_amount2: Optional[float] = field( + tax_amount2: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TaxAmount2"}, ) """Tax amount""" - tax_amount3: Optional[float] = field( + tax_amount3: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TaxAmount3"}, ) """Tax amount""" - term_session_id: Optional[int] = field( + term_session_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TermSessionID"}, ) """Pointer to the term session record.""" - transaction_date: Optional[str] = field( + transaction_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TransactionDate"}, ) """Date of the transaction.""" - transaction_id: Optional[int] = field( + transaction_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TransactionID"}, ) """Unique ID for this transaction record.""" - transaction_type_enum: Optional[str] = field( + transaction_type_enum: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TransactionTypeEnum"}, ) """Transaction type.""" @@ -8166,286 +9924,339 @@ class SelectRoomSpaceMaintenanceInput: Get Room Space Maintenance """ - return_empty_array_on_no_result: Optional[bool] = field( + return_empty_array_on_no_result: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_returnEmptyArrayOnNoResult"}, ) """ Determines whether an empty array should be returned when there is no result. """ - page_size: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageSize"}, - ) + page_size: int = dataclass_field(metadata={"wire_name": "_pageSize"}) """Maximum number of records to return.""" - page_index: Optional[int] = field( - default=None, - metadata={"wire_name": "_pageIndex"}, - ) + page_index: int = dataclass_field(metadata={"wire_name": "_pageIndex"}) """Index of the first record to return.""" - orderby: Optional[str] = field( + orderby: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_orderby"}, ) """ Sort by one or more fields in ascending order. Fields must be separated by commas with no spaces (e.g. field1,field2). """ - account_code: Optional[str] = field( + account_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountCode"}, ) """Account code.""" - cause: Optional[str] = field(default=None, metadata={"wire_name": "Cause"}) + cause: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cause"}, + ) """Cause.""" - charge: Optional[bool] = field( + charge: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Charge"}, ) """Indicates if a charge should be applied.""" - charge_entry_id: Optional[int] = field( + charge_entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Charge_EntryID"}, ) """Pointer to the charge entry record.""" - charge_amount: Optional[float] = field( + charge_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeAmount"}, ) """Charge amount.""" - charge_invoiced: Optional[bool] = field( + charge_invoiced: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeInvoiced"}, ) """Indicates if the charge has been invoiced.""" - charge_invoice_number: Optional[str] = field( + charge_invoice_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeInvoiceNumber"}, ) """Charge invoice number.""" - charge_type: Optional[str] = field( + charge_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeType"}, ) """Charge type.""" - complete_date: Optional[Dict[str, Any]] = field( + complete_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CompleteDate"}, ) - contact_id: Optional[int] = field( + contact_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactID"}, ) """Pointer to the contact record.""" - contract_date: Optional[Dict[str, Any]] = field( + contract_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDate"}, ) - contractor_cost: Optional[float] = field( + contractor_cost: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorCost"}, ) """Contractor cost.""" - contractor_cost_estimate: Optional[float] = field( + contractor_cost_estimate: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorCostEstimate"}, ) """Contractor cost estimate.""" - contractor_date: Optional[Dict[str, Any]] = field( + contractor_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorDate"}, ) - contractor_e_t_a: Optional[str] = field( + contractor_e_t_a: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorETA"}, ) """Contractor ETA.""" - contractor_order_number: Optional[str] = field( + contractor_order_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorOrderNumber"}, ) """Contractor order number.""" - created_by_security_user_id: Optional[int] = field( + created_by_security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CreatedBy_SecurityUserID"}, ) """Pointer to the security user record.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom bit 1.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom bit 2.""" - custom_date1: Optional[Dict[str, Any]] = field( + custom_date1: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) - custom_date2: Optional[Dict[str, Any]] = field( + custom_date2: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string 1.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string 2.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string 3.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string 4.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string 5.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string 6.""" - date_created: Optional[Dict[str, Any]] = field( + date_created: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateCreated"}, ) - date_due: Optional[Dict[str, Any]] = field( + date_due: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateDue"}, ) - date_modified: Optional[Dict[str, Any]] = field( + date_modified: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) - date_reported: Optional[Dict[str, Any]] = field( + date_reported: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateReported"}, ) - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """Description.""" - job_sent: Optional[bool] = field( + job_sent: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JobSent"}, ) """Indicates if a job has been sent.""" - job_status: Optional[str] = field( + job_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JobStatus"}, ) """Job status.""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location.""" - occupant_entry_id: Optional[int] = field( + occupant_entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Occupant_EntryID"}, ) """Pointer to the occupant entry record.""" - occupant_entry_name: Optional[str] = field( + occupant_entry_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantEntryName"}, ) """Occupant entry name.""" - occupant_present: Optional[bool] = field( + occupant_present: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantPresent"}, ) """Indicates if an occupant is present.""" - occupant_present_reason: Optional[str] = field( + occupant_present_reason: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantPresentReason"}, ) """Occupant present reason.""" - other_service_number: Optional[str] = field( + other_service_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OtherServiceNumber"}, ) """Other service number.""" - priority_id: Optional[int] = field( + priority_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PriorityID"}, ) """Pointer to the priority record.""" - repair_description: Optional[str] = field( + repair_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RepairDescription"}, ) """Repair description.""" - reported_by_name: Optional[str] = field( + reported_by_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReportedByName"}, ) """Reported by name.""" - reported_by_phone: Optional[str] = field( + reported_by_phone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReportedByPhone"}, ) """Reported by phone.""" - room_space_closed_id: Optional[int] = field( + room_space_closed_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceClosedID"}, ) """Pointer to the room space closed record.""" - room_space_id: Optional[int] = field( + room_space_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceID"}, ) """Pointer to the room space record.""" - room_space_maintenance_category_id: Optional[int] = field( + room_space_maintenance_category_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceCategoryID"}, ) """Pointer to the room space maintenance category record.""" - room_space_maintenance_id: Optional[int] = field( + room_space_maintenance_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceID"}, ) """Unique ID for this room space maintenance record.""" - room_space_maintenance_item_id: Optional[int] = field( + room_space_maintenance_item_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceItemID"}, ) """Pointer to the room space maintenance item record.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - start_date: Optional[Dict[str, Any]] = field( + start_date: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartDate"}, ) - status: Optional[str] = field( + status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Status"}, ) """Status.""" - technician: Optional[str] = field( + technician: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Technician"}, ) """Technician.""" - view_on_web: Optional[bool] = field( + view_on_web: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ViewOnWeb"}, ) """Indicates if the room space maintenance is viewable on the web.""" @@ -8457,255 +10268,305 @@ class CreateRoomSpaceMaintenanceInput: Create Room Space Maintenance """ - account_code: Optional[str] = field( + account_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountCode"}, ) """Account code.""" - cause: Optional[str] = field(default=None, metadata={"wire_name": "Cause"}) + cause: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cause"}, + ) """Cause.""" - charge: Optional[bool] = field( + charge: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Charge"}, ) """Indicates if a charge should be applied.""" - charge_entry_id: Optional[int] = field( + charge_entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Charge_EntryID"}, ) """Pointer to the charge entry record.""" - charge_amount: Optional[float] = field( + charge_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeAmount"}, ) """Charge amount.""" - charge_invoiced: Optional[bool] = field( + charge_invoiced: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeInvoiced"}, ) """Indicates if the charge has been invoiced.""" - charge_invoice_number: Optional[str] = field( + charge_invoice_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeInvoiceNumber"}, ) """Charge invoice number.""" - charge_type: Optional[str] = field( + charge_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeType"}, ) """Charge type.""" - complete_date: Optional[str] = field( + complete_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CompleteDate"}, ) """Complete date.""" - contact_id: Optional[int] = field( + contact_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactID"}, ) """Pointer to the contact record.""" - contract_date: Optional[str] = field( + contract_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDate"}, ) """Contract date.""" - contractor_cost: Optional[float] = field( + contractor_cost: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorCost"}, ) """Contractor cost.""" - contractor_cost_estimate: Optional[float] = field( + contractor_cost_estimate: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorCostEstimate"}, ) """Contractor cost estimate.""" - contractor_date: Optional[str] = field( + contractor_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorDate"}, ) """Contractor date.""" - contractor_e_t_a: Optional[str] = field( + contractor_e_t_a: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorETA"}, ) """Contractor ETA.""" - contractor_order_number: Optional[str] = field( + contractor_order_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorOrderNumber"}, ) """Contractor order number.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom bit 1.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom bit 2.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date 1.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date 2.""" - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string 1.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string 2.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string 3.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string 4.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string 5.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string 6.""" - date_due: Optional[str] = field( + date_due: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateDue"}, ) """Date due.""" - date_reported: Optional[str] = field( + date_reported: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateReported"}, ) """Date reported.""" - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """Description.""" - job_sent: Optional[bool] = field( + job_sent: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JobSent"}, ) """Indicates if a job has been sent.""" - job_status: Optional[str] = field( + job_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JobStatus"}, ) """Job status.""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location.""" - occupant_entry_id: Optional[int] = field( + occupant_entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Occupant_EntryID"}, ) """Pointer to the occupant entry record.""" - occupant_entry_name: Optional[str] = field( + occupant_entry_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantEntryName"}, ) """Occupant entry name.""" - occupant_present: Optional[bool] = field( + occupant_present: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantPresent"}, ) """Indicates if an occupant is present.""" - occupant_present_reason: Optional[str] = field( + occupant_present_reason: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantPresentReason"}, ) """Occupant present reason.""" - other_service_number: Optional[str] = field( + other_service_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OtherServiceNumber"}, ) """Other service number.""" - priority_id: Optional[int] = field( + priority_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PriorityID"}, ) """Pointer to the priority record.""" - repair_description: Optional[str] = field( + repair_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RepairDescription"}, ) """Repair description.""" - reported_by_name: Optional[str] = field( + reported_by_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReportedByName"}, ) """Reported by name.""" - reported_by_phone: Optional[str] = field( + reported_by_phone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReportedByPhone"}, ) """Reported by phone.""" - room_space_closed_id: Optional[int] = field( + room_space_closed_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceClosedID"}, ) """Pointer to the room space closed record.""" - room_space_id: Optional[int] = field( - default=None, - metadata={"wire_name": "RoomSpaceID"}, - ) + room_space_id: int = dataclass_field(metadata={"wire_name": "RoomSpaceID"}) """Pointer to the room space record.""" - room_space_maintenance_category_id: Optional[int] = field( + room_space_maintenance_category_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceCategoryID"}, ) """Pointer to the room space maintenance category record.""" - room_space_maintenance_id: Optional[int] = field( + room_space_maintenance_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceID"}, ) """Unique ID for this room space maintenance record.""" - room_space_maintenance_item_id: Optional[int] = field( + room_space_maintenance_item_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceItemID"}, ) """Pointer to the room space maintenance item record.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartDate"}, ) """Start date.""" - status: Optional[str] = field( + status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Status"}, ) """Status.""" - technician: Optional[str] = field( + technician: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Technician"}, ) """Technician.""" - view_on_web: Optional[bool] = field( + view_on_web: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ViewOnWeb"}, ) """Indicates if the room space maintenance is viewable on the web.""" @@ -8717,270 +10578,327 @@ class CreateRoomSpaceMaintenanceResponse: Response for Create Room Space Maintenance """ - account_code: Optional[str] = field( + account_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountCode"}, ) """Account code.""" - cause: Optional[str] = field(default=None, metadata={"wire_name": "Cause"}) + cause: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cause"}, + ) """Cause.""" - charge: Optional[bool] = field( + charge: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Charge"}, ) """Indicates if a charge should be applied.""" - charge_entry_id: Optional[int] = field( + charge_entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Charge_EntryID"}, ) """Pointer to the charge entry record.""" - charge_amount: Optional[float] = field( + charge_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeAmount"}, ) """Charge amount.""" - charge_invoiced: Optional[bool] = field( + charge_invoiced: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeInvoiced"}, ) """Indicates if the charge has been invoiced.""" - charge_invoice_number: Optional[str] = field( + charge_invoice_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeInvoiceNumber"}, ) """Charge invoice number.""" - charge_type: Optional[str] = field( + charge_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeType"}, ) """Charge type.""" - complete_date: Optional[str] = field( + complete_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CompleteDate"}, ) """Complete date.""" - contact_id: Optional[int] = field( + contact_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactID"}, ) """Pointer to the contact record.""" - contract_date: Optional[str] = field( + contract_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDate"}, ) """Contract date.""" - contractor_cost: Optional[float] = field( + contractor_cost: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorCost"}, ) """Contractor cost.""" - contractor_cost_estimate: Optional[float] = field( + contractor_cost_estimate: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorCostEstimate"}, ) """Contractor cost estimate.""" - contractor_date: Optional[str] = field( + contractor_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorDate"}, ) """Contractor date.""" - contractor_e_t_a: Optional[str] = field( + contractor_e_t_a: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorETA"}, ) """Contractor ETA.""" - contractor_order_number: Optional[str] = field( + contractor_order_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorOrderNumber"}, ) """Contractor order number.""" - created_by_security_user_id: Optional[int] = field( + created_by_security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CreatedBy_SecurityUserID"}, ) """Pointer to the security user record.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom bit 1.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom bit 2.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date 1.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date 2.""" - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string 1.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string 2.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string 3.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string 4.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string 5.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string 6.""" - date_created: Optional[str] = field( + date_created: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateCreated"}, ) """Date created.""" - date_due: Optional[str] = field( + date_due: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateDue"}, ) """Date due.""" - date_modified: Optional[str] = field( + date_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) """Date modified.""" - date_reported: Optional[str] = field( + date_reported: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateReported"}, ) """Date reported.""" - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """Description.""" - job_sent: Optional[bool] = field( + job_sent: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JobSent"}, ) """Indicates if a job has been sent.""" - job_status: Optional[str] = field( + job_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JobStatus"}, ) """Job status.""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location.""" - occupant_entry_id: Optional[int] = field( + occupant_entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Occupant_EntryID"}, ) """Pointer to the occupant entry record.""" - occupant_entry_name: Optional[str] = field( + occupant_entry_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantEntryName"}, ) """Occupant entry name.""" - occupant_present: Optional[bool] = field( + occupant_present: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantPresent"}, ) """Indicates if an occupant is present.""" - occupant_present_reason: Optional[str] = field( + occupant_present_reason: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantPresentReason"}, ) """Occupant present reason.""" - other_service_number: Optional[str] = field( + other_service_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OtherServiceNumber"}, ) """Other service number.""" - priority_id: Optional[int] = field( + priority_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PriorityID"}, ) """Pointer to the priority record.""" - repair_description: Optional[str] = field( + repair_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RepairDescription"}, ) """Repair description.""" - reported_by_name: Optional[str] = field( + reported_by_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReportedByName"}, ) """Reported by name.""" - reported_by_phone: Optional[str] = field( + reported_by_phone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReportedByPhone"}, ) """Reported by phone.""" - room_space_closed_id: Optional[int] = field( + room_space_closed_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceClosedID"}, ) """Pointer to the room space closed record.""" - room_space_id: Optional[int] = field( + room_space_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceID"}, ) """Pointer to the room space record.""" - room_space_maintenance_category_id: Optional[int] = field( + room_space_maintenance_category_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceCategoryID"}, ) """Pointer to the room space maintenance category record.""" - room_space_maintenance_id: Optional[int] = field( + room_space_maintenance_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceID"}, ) """Unique ID for this room space maintenance record.""" - room_space_maintenance_item_id: Optional[int] = field( + room_space_maintenance_item_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceItemID"}, ) """Pointer to the room space maintenance item record.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartDate"}, ) """Start date.""" - status: Optional[str] = field( + status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Status"}, ) """Status.""" - technician: Optional[str] = field( + technician: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Technician"}, ) """Technician.""" - view_on_web: Optional[bool] = field( + view_on_web: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ViewOnWeb"}, ) """Indicates if the room space maintenance is viewable on the web.""" @@ -8992,255 +10910,309 @@ class UpdateRoomSpaceMaintenanceInput: Update Room Space Maintenance """ - account_code: Optional[str] = field( + account_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountCode"}, ) """Account code.""" - cause: Optional[str] = field(default=None, metadata={"wire_name": "Cause"}) + cause: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cause"}, + ) """Cause.""" - charge: Optional[bool] = field( + charge: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Charge"}, ) """Indicates if a charge should be applied.""" - charge_entry_id: Optional[int] = field( + charge_entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Charge_EntryID"}, ) """Pointer to the charge entry record.""" - charge_amount: Optional[float] = field( + charge_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeAmount"}, ) """Charge amount.""" - charge_invoiced: Optional[bool] = field( + charge_invoiced: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeInvoiced"}, ) """Indicates if the charge has been invoiced.""" - charge_invoice_number: Optional[str] = field( + charge_invoice_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeInvoiceNumber"}, ) """Charge invoice number.""" - charge_type: Optional[str] = field( + charge_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeType"}, ) """Charge type.""" - complete_date: Optional[str] = field( + complete_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CompleteDate"}, ) """Complete date.""" - contact_id: Optional[int] = field( + contact_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactID"}, ) """Pointer to the contact record.""" - contract_date: Optional[str] = field( + contract_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDate"}, ) """Contract date.""" - contractor_cost: Optional[float] = field( + contractor_cost: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorCost"}, ) """Contractor cost.""" - contractor_cost_estimate: Optional[float] = field( + contractor_cost_estimate: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorCostEstimate"}, ) """Contractor cost estimate.""" - contractor_date: Optional[str] = field( + contractor_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorDate"}, ) """Contractor date.""" - contractor_e_t_a: Optional[str] = field( + contractor_e_t_a: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorETA"}, ) """Contractor ETA.""" - contractor_order_number: Optional[str] = field( + contractor_order_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorOrderNumber"}, ) """Contractor order number.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom bit 1.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom bit 2.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date 1.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date 2.""" - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string 1.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string 2.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string 3.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string 4.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string 5.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string 6.""" - date_due: Optional[str] = field( + date_due: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateDue"}, ) """Date due.""" - date_reported: Optional[str] = field( + date_reported: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateReported"}, ) """Date reported.""" - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """Description.""" - job_sent: Optional[bool] = field( + job_sent: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JobSent"}, ) """Indicates if a job has been sent.""" - job_status: Optional[str] = field( + job_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JobStatus"}, ) """Job status.""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location.""" - occupant_entry_id: Optional[int] = field( + occupant_entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Occupant_EntryID"}, ) """Pointer to the occupant entry record.""" - occupant_entry_name: Optional[str] = field( + occupant_entry_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantEntryName"}, ) """Occupant entry name.""" - occupant_present: Optional[bool] = field( + occupant_present: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantPresent"}, ) """Indicates if an occupant is present.""" - occupant_present_reason: Optional[str] = field( + occupant_present_reason: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantPresentReason"}, ) """Occupant present reason.""" - other_service_number: Optional[str] = field( + other_service_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OtherServiceNumber"}, ) """Other service number.""" - priority_id: Optional[int] = field( + priority_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PriorityID"}, ) """Pointer to the priority record.""" - repair_description: Optional[str] = field( + repair_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RepairDescription"}, ) """Repair description.""" - reported_by_name: Optional[str] = field( + reported_by_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReportedByName"}, ) """Reported by name.""" - reported_by_phone: Optional[str] = field( + reported_by_phone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReportedByPhone"}, ) """Reported by phone.""" - room_space_closed_id: Optional[int] = field( + room_space_closed_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceClosedID"}, ) """Pointer to the room space closed record.""" - room_space_id: Optional[int] = field( + room_space_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceID"}, ) """Pointer to the room space record.""" - room_space_maintenance_category_id: Optional[int] = field( + room_space_maintenance_category_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceCategoryID"}, ) """Pointer to the room space maintenance category record.""" - room_space_maintenance_id: Optional[int] = field( + room_space_maintenance_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceID"}, ) """Unique ID for this room space maintenance record.""" - room_space_maintenance_item_id: Optional[int] = field( + room_space_maintenance_item_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceItemID"}, ) """Pointer to the room space maintenance item record.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartDate"}, ) """Start date.""" - status: Optional[str] = field( + status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Status"}, ) """Status.""" - technician: Optional[str] = field( + technician: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Technician"}, ) """Technician.""" - view_on_web: Optional[bool] = field( + view_on_web: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ViewOnWeb"}, ) """Indicates if the room space maintenance is viewable on the web.""" @@ -9252,270 +11224,327 @@ class UpdateRoomSpaceMaintenanceResponse: Response for Update Room Space Maintenance """ - account_code: Optional[str] = field( + account_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "AccountCode"}, ) """Account code.""" - cause: Optional[str] = field(default=None, metadata={"wire_name": "Cause"}) + cause: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Cause"}, + ) """Cause.""" - charge: Optional[bool] = field( + charge: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Charge"}, ) """Indicates if a charge should be applied.""" - charge_entry_id: Optional[int] = field( + charge_entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Charge_EntryID"}, ) """Pointer to the charge entry record.""" - charge_amount: Optional[float] = field( + charge_amount: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeAmount"}, ) """Charge amount.""" - charge_invoiced: Optional[bool] = field( + charge_invoiced: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeInvoiced"}, ) """Indicates if the charge has been invoiced.""" - charge_invoice_number: Optional[str] = field( + charge_invoice_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeInvoiceNumber"}, ) """Charge invoice number.""" - charge_type: Optional[str] = field( + charge_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ChargeType"}, ) """Charge type.""" - complete_date: Optional[str] = field( + complete_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CompleteDate"}, ) """Complete date.""" - contact_id: Optional[int] = field( + contact_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContactID"}, ) """Pointer to the contact record.""" - contract_date: Optional[str] = field( + contract_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractDate"}, ) """Contract date.""" - contractor_cost: Optional[float] = field( + contractor_cost: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorCost"}, ) """Contractor cost.""" - contractor_cost_estimate: Optional[float] = field( + contractor_cost_estimate: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorCostEstimate"}, ) """Contractor cost estimate.""" - contractor_date: Optional[str] = field( + contractor_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorDate"}, ) """Contractor date.""" - contractor_e_t_a: Optional[str] = field( + contractor_e_t_a: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorETA"}, ) """Contractor ETA.""" - contractor_order_number: Optional[str] = field( + contractor_order_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ContractorOrderNumber"}, ) """Contractor order number.""" - created_by_security_user_id: Optional[int] = field( + created_by_security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CreatedBy_SecurityUserID"}, ) """Pointer to the security user record.""" - custom_bit1: Optional[bool] = field( + custom_bit1: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit1"}, ) """Custom bit 1.""" - custom_bit2: Optional[bool] = field( + custom_bit2: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomBit2"}, ) """Custom bit 2.""" - custom_date1: Optional[str] = field( + custom_date1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate1"}, ) """Custom date 1.""" - custom_date2: Optional[str] = field( + custom_date2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomDate2"}, ) """Custom date 2.""" - custom_string1: Optional[str] = field( + custom_string1: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString1"}, ) """Custom string 1.""" - custom_string2: Optional[str] = field( + custom_string2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString2"}, ) """Custom string 2.""" - custom_string3: Optional[str] = field( + custom_string3: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString3"}, ) """Custom string 3.""" - custom_string4: Optional[str] = field( + custom_string4: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString4"}, ) """Custom string 4.""" - custom_string5: Optional[str] = field( + custom_string5: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString5"}, ) """Custom string 5.""" - custom_string6: Optional[str] = field( + custom_string6: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CustomString6"}, ) """Custom string 6.""" - date_created: Optional[str] = field( + date_created: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateCreated"}, ) """Date created.""" - date_due: Optional[str] = field( + date_due: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateDue"}, ) """Date due.""" - date_modified: Optional[str] = field( + date_modified: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateModified"}, ) """Date modified.""" - date_reported: Optional[str] = field( + date_reported: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DateReported"}, ) """Date reported.""" - description: Optional[str] = field( + description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """Description.""" - job_sent: Optional[bool] = field( + job_sent: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JobSent"}, ) """Indicates if a job has been sent.""" - job_status: Optional[str] = field( + job_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "JobStatus"}, ) """Job status.""" - location: Optional[str] = field( + location: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Location"}, ) """Location.""" - occupant_entry_id: Optional[int] = field( + occupant_entry_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Occupant_EntryID"}, ) """Pointer to the occupant entry record.""" - occupant_entry_name: Optional[str] = field( + occupant_entry_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantEntryName"}, ) """Occupant entry name.""" - occupant_present: Optional[bool] = field( + occupant_present: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantPresent"}, ) """Indicates if an occupant is present.""" - occupant_present_reason: Optional[str] = field( + occupant_present_reason: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OccupantPresentReason"}, ) """Occupant present reason.""" - other_service_number: Optional[str] = field( + other_service_number: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OtherServiceNumber"}, ) """Other service number.""" - priority_id: Optional[int] = field( + priority_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "PriorityID"}, ) """Pointer to the priority record.""" - repair_description: Optional[str] = field( + repair_description: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RepairDescription"}, ) """Repair description.""" - reported_by_name: Optional[str] = field( + reported_by_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReportedByName"}, ) """Reported by name.""" - reported_by_phone: Optional[str] = field( + reported_by_phone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReportedByPhone"}, ) """Reported by phone.""" - room_space_closed_id: Optional[int] = field( + room_space_closed_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceClosedID"}, ) """Pointer to the room space closed record.""" - room_space_id: Optional[int] = field( + room_space_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceID"}, ) """Pointer to the room space record.""" - room_space_maintenance_category_id: Optional[int] = field( + room_space_maintenance_category_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceCategoryID"}, ) """Pointer to the room space maintenance category record.""" - room_space_maintenance_id: Optional[int] = field( + room_space_maintenance_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceID"}, ) """Unique ID for this room space maintenance record.""" - room_space_maintenance_item_id: Optional[int] = field( + room_space_maintenance_item_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RoomSpaceMaintenanceItemID"}, ) """Pointer to the room space maintenance item record.""" - security_user_id: Optional[int] = field( + security_user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "SecurityUserID"}, ) """Pointer to the security user record.""" - start_date: Optional[str] = field( + start_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartDate"}, ) """Start date.""" - status: Optional[str] = field( + status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Status"}, ) """Status.""" - technician: Optional[str] = field( + technician: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Technician"}, ) """Technician.""" - view_on_web: Optional[bool] = field( + view_on_web: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ViewOnWeb"}, ) """Indicates if the room space maintenance is viewable on the web.""" @@ -9529,16 +11558,16 @@ class Starrezrestv1Client(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -9549,8 +11578,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -9558,8 +11587,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -9571,7 +11600,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -9586,46 +11615,126 @@ def __init__( def connector_name(self) -> str: return "starrezrestv1" - async def select_entry_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_select_entry( self, - input: SelectEntryInput, + input: SelectEntryInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Entry Retrieves one or more records from the Entry table. - """ - request_url = f"{self._connection_runtime_url}/select/entry.json" - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + Returns an Azure Core pager that follows the connector continuation + URL. - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, + Swagger operation ID: `SelectEntry`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. + """ + request_url = f"{self._connection_runtime_url}/select/entry.json" + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def create_entry_async( + def create_entry( self, - input: CreateEntryInput, + input: CreateEntryInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -9636,10 +11745,26 @@ async def create_entry_async( Create Entry Creates a new record in the Entry table. + + Swagger operation ID: `CreateEntry`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/create/entry.json" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -9653,6 +11778,7 @@ async def create_entry_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -9660,9 +11786,9 @@ async def create_entry_async( return json.loads(response.text) - async def update_entry_async( + def update_entry( self, - input: UpdateEntryInput, + input: UpdateEntryInput | Mapping[str, Any], entry_id: int, *, timeout: Optional[float] = None, @@ -9674,13 +11800,30 @@ async def update_entry_async( Update Entry Updates an existing record in the Entry table. + + Swagger operation ID: `UpdateEntry`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entry_id: The ID of the Entry record to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/update/entry.json/{quote(str(entry_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -9694,6 +11837,7 @@ async def update_entry_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -9701,7 +11845,7 @@ async def update_entry_async( return json.loads(response.text) - async def delete_async( + def delete( self, table_name: str, row_id: int, @@ -9715,6 +11859,22 @@ async def delete_async( Delete Deletes a record from the specified table. + + Swagger operation ID: `Delete`. + + Args: + table_name: Name of the table to delete record from. + row_id: Row ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -9723,7 +11883,7 @@ async def delete_async( f"/{quote(str(row_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -9737,6 +11897,7 @@ async def delete_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -9744,48 +11905,89 @@ async def delete_async( return json.loads(response.text) - async def select_entry_custom_field_async( + def list_select_entry_custom_field( self, - input: SelectEntryCustomFieldInput, + input: SelectEntryCustomFieldInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Entry Custom Field Retrieves one or more records from the Entry Custom Field table. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SelectEntryCustomField`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/select/EntryCustomField.json" ) + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def update_entry_custom_field_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def update_entry_custom_field( self, - input: UpdateEntryCustomFieldInput, + input: UpdateEntryCustomFieldInput | Mapping[str, Any], entry_custom_field_id: int, *, timeout: Optional[float] = None, @@ -9797,6 +11999,24 @@ async def update_entry_custom_field_async( Update Entry Custom Field Updates an existing record in the Entry Custom Field table. + + Swagger operation ID: `UpdateEntryCustomField`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entry_custom_field_id: The ID of the Entry Custom Field record to + update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -9805,7 +12025,7 @@ async def update_entry_custom_field_async( f"/{quote(str(entry_custom_field_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -9819,6 +12039,7 @@ async def update_entry_custom_field_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -9826,85 +12047,167 @@ async def update_entry_custom_field_async( return json.loads(response.text) - async def select_term_async( + def list_select_term( self, - input: SelectTermInput, + input: SelectTermInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Term Retrieves one or more records from the Term table. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SelectTerm`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/select/Term.json" + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def select_entry_address_async( + return ItemPaged(get_next, extract_data) + + def list_select_entry_address( self, - input: SelectEntryAddressInput, + input: SelectEntryAddressInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Entry Address Retrieves one or more records from the Entry Address table. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SelectEntryAddress`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/select/EntryAddress.json" ) + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def update_entry_address_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def update_entry_address( self, - input: UpdateEntryAddressInput, + input: UpdateEntryAddressInput | Mapping[str, Any], entry_address_id: int, *, timeout: Optional[float] = None, @@ -9916,6 +12219,23 @@ async def update_entry_address_async( Update Entry Address Updates an existing record in the Entry Address table. + + Swagger operation ID: `UpdateEntryAddress`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entry_address_id: The ID of the Entry Address record to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -9924,7 +12244,7 @@ async def update_entry_address_async( f"/{quote(str(entry_address_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -9938,6 +12258,7 @@ async def update_entry_address_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -9945,48 +12266,89 @@ async def update_entry_address_async( return json.loads(response.text) - async def select_entry_application_async( + def list_select_entry_application( self, - input: SelectEntryApplicationInput, + input: SelectEntryApplicationInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Entry Application Retrieves one or more records from the Entry Application table. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SelectEntryApplication`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/select/EntryApplication.json" ) + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def create_entry_application_async( + return ItemPaged(get_next, extract_data) + + def create_entry_application( self, - input: CreateEntryApplicationInput, + input: CreateEntryApplicationInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -9997,12 +12359,28 @@ async def create_entry_application_async( Create Entry Application Creates a new record in the Entry Application table. + + Swagger operation ID: `CreateEntryApplication`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/create/entryapplication.json" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -10016,6 +12394,7 @@ async def create_entry_application_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -10023,9 +12402,9 @@ async def create_entry_application_async( return json.loads(response.text) - async def update_entry_application_async( + def update_entry_application( self, - input: UpdateEntryApplicationInput, + input: UpdateEntryApplicationInput | Mapping[str, Any], entry_application_id: int, *, timeout: Optional[float] = None, @@ -10037,6 +12416,24 @@ async def update_entry_application_async( Update Entry Application Updates an existing record in the Entry Application table. + + Swagger operation ID: `UpdateEntryApplication`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entry_application_id: The ID of the Entry Application record to + update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -10045,7 +12442,7 @@ async def update_entry_application_async( f"/{quote(str(entry_application_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -10059,6 +12456,7 @@ async def update_entry_application_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -10066,83 +12464,165 @@ async def update_entry_application_async( return json.loads(response.text) - async def select_term_session_async( + def list_select_term_session( self, - input: SelectTermSessionInput, + input: SelectTermSessionInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Term Session Retrieves one or more records from the Term Session table. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SelectTermSession`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/select/TermSession.json" + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def select_entry_detail_async( + def list_select_entry_detail( self, - input: SelectEntryDetailInput, + input: SelectEntryDetailInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Entry Detail Retrieves one or more records from the Entry Detail table. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SelectEntryDetail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/select/EntryDetail.json" + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def update_entry_detail_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def update_entry_detail( self, - input: UpdateEntryDetailInput, + input: UpdateEntryDetailInput | Mapping[str, Any], entry_detail_id: int, *, timeout: Optional[float] = None, @@ -10154,13 +12634,30 @@ async def update_entry_detail_async( Update Entry Detail Updates an existing record in the Entry Detail table. + + Swagger operation ID: `UpdateEntryDetail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entry_detail_id: The ID of the Entry Detail record to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/update/entrydetail.json/{quote(str(entry_detail_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -10174,6 +12671,7 @@ async def update_entry_detail_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -10181,48 +12679,89 @@ async def update_entry_detail_async( return json.loads(response.text) - async def select_entry_enrollment_async( + def list_select_entry_enrollment( self, - input: SelectEntryEnrollmentInput, + input: SelectEntryEnrollmentInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Entry Enrollment Retrieves one or more records from the Entry Enrollment table. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SelectEntryEnrollment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/select/EntryEnrollment.json" ) + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def create_entry_enrollment_async( + return ItemPaged(get_next, extract_data) + + def create_entry_enrollment( self, - input: CreateEntryEnrollmentInput, + input: CreateEntryEnrollmentInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -10233,12 +12772,28 @@ async def create_entry_enrollment_async( Create Entry Enrollment Creates a new record in the Entry Enrollment table. + + Swagger operation ID: `CreateEntryEnrollment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/create/entryenrollment.json" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -10252,6 +12807,7 @@ async def create_entry_enrollment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -10259,9 +12815,9 @@ async def create_entry_enrollment_async( return json.loads(response.text) - async def update_entry_enrollment_async( + def update_entry_enrollment( self, - input: UpdateEntryEnrollmentInput, + input: UpdateEntryEnrollmentInput | Mapping[str, Any], entry_enrollment_id: int, *, timeout: Optional[float] = None, @@ -10273,6 +12829,24 @@ async def update_entry_enrollment_async( Update Entry Enrollment Updates an existing record in the Entry Enrollment table. + + Swagger operation ID: `UpdateEntryEnrollment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + entry_enrollment_id: The ID of the Entry Enrollment record to + update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -10281,7 +12855,7 @@ async def update_entry_enrollment_async( f"/{quote(str(entry_enrollment_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -10295,6 +12869,7 @@ async def update_entry_enrollment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -10302,46 +12877,87 @@ async def update_entry_enrollment_async( return json.loads(response.text) - async def select_booking_async( + def list_select_booking( self, - input: SelectBookingInput, + input: SelectBookingInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Booking Retrieves one or more records from the Booking table. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SelectBooking`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/select/Booking.json" + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def create_booking_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def create_booking( self, - input: CreateBookingInput, + input: CreateBookingInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -10352,10 +12968,26 @@ async def create_booking_async( Create Booking Creates a new record in the Booking table. + + Swagger operation ID: `CreateBooking`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/create/booking.json" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -10369,6 +13001,7 @@ async def create_booking_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -10376,9 +13009,9 @@ async def create_booking_async( return json.loads(response.text) - async def update_booking_async( + def update_booking( self, - input: UpdateBookingInput, + input: UpdateBookingInput | Mapping[str, Any], booking_id: int, *, timeout: Optional[float] = None, @@ -10390,13 +13023,30 @@ async def update_booking_async( Update Booking Updates an existing record in the Booking table. + + Swagger operation ID: `UpdateBooking`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + booking_id: The ID of the Booking record to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/update/booking.json/{quote(str(booking_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -10410,6 +13060,7 @@ async def update_booking_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -10417,46 +13068,87 @@ async def update_booking_async( return json.loads(response.text) - async def select_room_space_async( + def list_select_room_space( self, - input: SelectRoomSpaceInput, + input: SelectRoomSpaceInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Room Space Retrieves one or more records from the Room Space table. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SelectRoomSpace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/select/RoomSpace.json" + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def create_room_space_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def create_room_space( self, - input: CreateRoomSpaceInput, + input: CreateRoomSpaceInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -10467,10 +13159,26 @@ async def create_room_space_async( Create Room Space Creates a new record in the Room Space table. + + Swagger operation ID: `CreateRoomSpace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/create/roomspace.json" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -10484,6 +13192,7 @@ async def create_room_space_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -10491,85 +13200,167 @@ async def create_room_space_async( return json.loads(response.text) - async def select_room_location_async( + def list_select_room_location( self, - input: SelectRoomLocationInput, + input: SelectRoomLocationInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Room Location Retrieves one or more records from the Room Location table. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SelectRoomLocation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/select/RoomLocation.json" ) + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def select_transaction_async( + def list_select_transaction( self, - input: SelectTransactionInput, + input: SelectTransactionInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Transaction Retrieves one or more records from the Transaction table. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SelectTransaction`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/select/Transaction.json" + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def create_transaction_async( + def create_transaction( self, - input: CreateTransactionInput, + input: CreateTransactionInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -10580,10 +13371,26 @@ async def create_transaction_async( Create Transaction Creates a new record in the Transaction table. + + Swagger operation ID: `CreateTransaction`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/create/transaction.json" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -10597,6 +13404,7 @@ async def create_transaction_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -10604,48 +13412,89 @@ async def create_transaction_async( return json.loads(response.text) - async def select_room_space_maintenance_async( + def list_select_room_space_maintenance( self, - input: SelectRoomSpaceMaintenanceInput, + input: SelectRoomSpaceMaintenanceInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Room Space Maintenance Retrieves one or more records from the Room Space Maintenance table. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SelectRoomSpaceMaintenance`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/select/RoomSpaceMaintenance.json" ) + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def create_room_space_maintenance_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def create_room_space_maintenance( self, - input: CreateRoomSpaceMaintenanceInput, + input: CreateRoomSpaceMaintenanceInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -10656,12 +13505,28 @@ async def create_room_space_maintenance_async( Create Room Space Maintenance Creates a new record in the Room Space Maintenance table. + + Swagger operation ID: `CreateRoomSpaceMaintenance`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/create/roomspacemaintenance.json" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -10675,6 +13540,7 @@ async def create_room_space_maintenance_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -10682,9 +13548,9 @@ async def create_room_space_maintenance_async( return json.loads(response.text) - async def update_room_space_maintenance_async( + def update_room_space_maintenance( self, - input: UpdateRoomSpaceMaintenanceInput, + input: UpdateRoomSpaceMaintenanceInput | Mapping[str, Any], room_space_maintenance_id: int, *, timeout: Optional[float] = None, @@ -10696,6 +13562,24 @@ async def update_room_space_maintenance_async( Update Room Space Maintenance Updates an existing record in the Room Space Maintenance table. + + Swagger operation ID: `UpdateRoomSpaceMaintenance`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + room_space_maintenance_id: The ID of the Room Space Maintenance + record to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -10704,7 +13588,7 @@ async def update_room_space_maintenance_async( f"/{quote(str(room_space_maintenance_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -10718,6 +13602,7 @@ async def update_room_space_maintenance_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/tallyfy.py b/src/azure/connectors/tallyfy.py index faba5c6..780f2aa 100644 --- a/src/azure/connectors/tallyfy.py +++ b/src/azure/connectors/tallyfy.py @@ -5,21 +5,134 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "TallyfyClient", + "AccessToken", + "AccountInput", + "AccountsInput", + "AddTagInput", + "Address", + "AlertIssues", + "Asset", + "AssetSubject", + "BillInput", + "Branding", + "BrandingInput", + "Capture", + "CaptureInput", + "CheckUrlInput", + "Checklist", + "ChecklistInput", + "Client", + "Comment", + "CommentOn", + "CommentTaskInput", + "CommentTaskResponse", + "CompletedOneOffTaskInput", + "CompletedOneOffTaskResponse", + "CompletedProcessTask", + "CompletedProcessTaskInput", + "CompletedProcessTaskResponse", + "CreateChecklistInput", + "CreateCommentInput", + "CreateGroupInput", + "CreateGuestsTasksComment", + "CreateRoleInput", + "CreateRunInput", + "CreateRunResponse", + "CreateStandaloneTaskInput", + "CreateStepInput", + "CreateTagInput", + "CreateTaskInput", + "CreateTaskResponse", + "Date", + "DueDateInput", + "EditStepTypeInput", + "EditStepTypeResponse", + "EditTaskDeadlineInput", + "EditTaskDeadlineResponse", + "Error", + "File", + "GenericObject", + "GetOrganizationUsersResponse", + "GetUserOrganizationsResponse", + "GetUserTasksResponse", + "Group", + "IntegrationS3Input", + "InviteInput", + "InviteUserToOrganizationInput", + "InviteUserToOrganizationResponse", + "LoginInput", + "Message", + "Organization", + "OrganizationInput", + "OrganizationSettings", + "OwnerInput", + "Pagination", + "Passwordreset", + "Passwordreseterro", + "PowerbuilderInput", + "Preference", + "PreferenceInput", + "PrerunData", + "RegisterInput", + "RemoveAssigneeResponse", + "RemoveGuestResponse", + "ReopenOneOffTaskResponse", + "ReopenProcessTaskResponse", + "RequestDate", + "ResetPasswordInput", + "Role", + "Run", + "RunAlerts", + "RunCollaborators", + "RunMetaInput", + "RunRatingsInput", + "RunView", + "RunViewInput", + "Section", + "SectionCreateInput", + "SectionInput", + "StandaloneTask", + "Step", + "StepCondition", + "StepConditionTerm", + "StepDeadline", + "StepMeta", + "StepOwner", + "SubcriptionInput", + "Tag", + "TaskGuest", + "TaskMeta", + "TaskMetaInput", + "TaskObject", + "TasksList", + "TasksListMeta", + "Thread", + "ThreadInput", + "ThreadResolveInput", + "UpdateGuestsTasksInput", + "UpdateStandaloneTaskInput", + "UpdateTaskInput", + "User", +] + # Type Definitions @@ -29,9 +142,9 @@ class GetUserTasksResponse: Response for Get a member's tasks """ - data: Optional[List[Dict[str, Any]]] = None + data: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """data""" - meta: Optional[Dict[str, Any]] = None + meta: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """meta""" @@ -41,15 +154,15 @@ class InviteUserToOrganizationInput: Invite a new member to your organization """ - first_name: Optional[str] = None + first_name: str """Invitee's first name""" - last_name: Optional[str] = None + last_name: str """invitee's last name""" - email: Optional[str] = None + email: str """invitee's work email address""" - message: Optional[str] = None + message: str """Message to add""" - role: Optional[str] = None + role: str """Role""" @@ -59,7 +172,7 @@ class InviteUserToOrganizationResponse: Response for Invite a new member to your organization """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -69,11 +182,11 @@ class CreateRunInput: Launch a Process """ - name: Optional[str] = None + name: str """Name to give the new Process""" - checklist_id: Optional[str] = None + checklist_id: str """ID of the Blueprint to start the process""" - summary: Optional[str] = None + summary: Optional[str] = dataclass_field(default=None, kw_only=True) """Summary notes to include with the Process""" @@ -83,7 +196,7 @@ class CreateRunResponse: Response for Launch a Process """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -93,9 +206,9 @@ class CompletedOneOffTaskInput: Complete One Off Task """ - task_id: Optional[str] = None + task_id: str """Task ID""" - is_approved: Optional[bool] = None + is_approved: Optional[bool] = dataclass_field(default=None, kw_only=True) """starred""" @@ -105,7 +218,7 @@ class CompletedOneOffTaskResponse: Response for Complete One Off Task """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -118,7 +231,7 @@ class ReopenOneOffTaskResponse: Response for Reopen One Off Task """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -131,9 +244,9 @@ class CompletedProcessTaskInput: Complete process task """ - task_id: Optional[str] = None + task_id: str """Task ID""" - is_approved: Optional[bool] = None + is_approved: Optional[bool] = dataclass_field(default=None, kw_only=True) """starred""" @@ -143,7 +256,7 @@ class CompletedProcessTaskResponse: Response for Complete process task """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -156,7 +269,7 @@ class ReopenProcessTaskResponse: Response for Reopen process Task """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -169,9 +282,9 @@ class CommentTaskInput: Add comment, report issue, resolve issue on a task """ - content: Optional[str] = None + content: str """Comment content""" - label: Optional[str] = None + label: str """Comment label""" @@ -181,7 +294,7 @@ class CommentTaskResponse: Response for Add comment, report issue, resolve issue on a task """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -194,15 +307,15 @@ class CreateTaskInput: Create a task """ - owners: Optional[Dict[str, Any]] = None + owners: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """owners""" - task_type: Optional[str] = None + task_type: str """Task type""" - deadline: Optional[str] = None + deadline: str """task deadline, in date-time format""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Task's description""" - name: Optional[str] = None + name: str """task name""" @@ -212,7 +325,7 @@ class CreateTaskResponse: Response for Create a task """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" @@ -222,8 +335,9 @@ class EditTaskDeadlineInput: Edit task deadline """ - deadline: Optional[str] = field( + deadline: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Deadline"}, ) """New task deadline""" @@ -235,7 +349,7 @@ class EditTaskDeadlineResponse: Response for Edit task deadline """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -248,7 +362,7 @@ class RemoveGuestResponse: Response for Remove guest assigned """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -261,7 +375,7 @@ class RemoveAssigneeResponse: Response for Remove assignee """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -274,8 +388,9 @@ class EditStepTypeInput: Edit step type """ - step_type: Optional[str] = field( + step_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "stepType"}, ) """New step type""" @@ -287,7 +402,7 @@ class EditStepTypeResponse: Response for Edit step type """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -300,9 +415,9 @@ class GetUserOrganizationsResponse: Response for Get user's organizations """ - data: Optional[List[Dict[str, Any]]] = None + data: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """data""" - meta: Optional[Dict[str, Any]] = None + meta: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """meta""" @@ -312,7 +427,7 @@ class GetOrganizationUsersResponse: Response for Get organization's users """ - data: Optional[List[Dict[str, Any]]] = None + data: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """data""" @@ -322,8 +437,8 @@ class Error: Definition: error """ - error: Optional[bool] = None - message: Optional[str] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) + message: str Date = str @@ -338,13 +453,13 @@ class Address: Definition: Address """ - address1: Optional[str] = None - address2: Optional[str] = None - city: Optional[str] = None - state: Optional[str] = None - zip: Optional[str] = None - country: Optional[str] = None - phone: Optional[str] = None + address1: Optional[str] = dataclass_field(default=None, kw_only=True) + address2: Optional[str] = dataclass_field(default=None, kw_only=True) + city: Optional[str] = dataclass_field(default=None, kw_only=True) + state: Optional[str] = dataclass_field(default=None, kw_only=True) + zip: Optional[str] = dataclass_field(default=None, kw_only=True) + country: Optional[str] = dataclass_field(default=None, kw_only=True) + phone: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -353,8 +468,8 @@ class LoginInput: Definition: loginInput """ - email: Optional[str] = None - password: Optional[str] = None + email: str + password: str @dataclass @@ -363,11 +478,11 @@ class File: Definition: File """ - name: Optional[str] = None - url: Optional[str] = None - extension: Optional[str] = None - size: Optional[int] = None - last_modified: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + url: Optional[str] = dataclass_field(default=None, kw_only=True) + extension: Optional[str] = dataclass_field(default=None, kw_only=True) + size: Optional[int] = dataclass_field(default=None, kw_only=True) + last_modified: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -376,14 +491,14 @@ class RegisterInput: Definition: registerInput """ - first_name: Optional[str] = None - last_name: Optional[str] = None - email: Optional[str] = None - password: Optional[str] = None - company_name: Optional[str] = None - timezone: Optional[str] = None - plan_code: Optional[str] = None - coupon_code: Optional[str] = None + first_name: str + last_name: str + email: str + password: str + company_name: str + timezone: Optional[str] = dataclass_field(default=None, kw_only=True) + plan_code: str + coupon_code: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -392,9 +507,9 @@ class ResetPasswordInput: Definition: resetPasswordInput """ - password: Optional[str] = None - password_confirmation: Optional[str] = None - code: Optional[str] = None + password: Optional[str] = dataclass_field(default=None, kw_only=True) + password_confirmation: Optional[str] = dataclass_field(default=None, kw_only=True) + code: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -403,19 +518,24 @@ class OrganizationInput: Definition: organizationInput """ - name: Optional[str] = None - address1: Optional[str] = None - address2: Optional[str] = None - address3: Optional[str] = None - slug: Optional[str] = None - welcome_title: Optional[str] = None - welcome_description: Optional[str] = None - industry: Optional[str] = None - country: Optional[str] = None - state: Optional[str] = None - city: Optional[str] = None - zipcode: Optional[str] = None - settings: Optional[OrganizationSettings] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + address1: Optional[str] = dataclass_field(default=None, kw_only=True) + address2: Optional[str] = dataclass_field(default=None, kw_only=True) + address3: Optional[str] = dataclass_field(default=None, kw_only=True) + slug: Optional[str] = dataclass_field(default=None, kw_only=True) + welcome_title: Optional[str] = dataclass_field(default=None, kw_only=True) + welcome_description: Optional[str] = dataclass_field(default=None, kw_only=True) + industry: Optional[str] = dataclass_field(default=None, kw_only=True) + country: Optional[str] = dataclass_field(default=None, kw_only=True) + state: Optional[str] = dataclass_field(default=None, kw_only=True) + city: Optional[str] = dataclass_field(default=None, kw_only=True) + zipcode: Optional[str] = dataclass_field(default=None, kw_only=True) + settings: Optional[ + OrganizationSettings | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -424,9 +544,14 @@ class OrganizationSettings: Definition: organizationSettings """ - determine_deadline: Optional[GenericObject] = None - workdays: Optional[List[str]] = None - holidays: Optional[List[str]] = None + determine_deadline: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + workdays: Optional[List[str]] = dataclass_field(default=None, kw_only=True) + holidays: Optional[List[str]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -435,7 +560,7 @@ class BillInput: Definition: billInput """ - token_id: Optional[str] = None + token_id: str @dataclass @@ -444,8 +569,8 @@ class SubcriptionInput: Definition: subcriptionInput """ - plan_code: Optional[str] = None - coupon_code: Optional[str] = None + plan_code: Optional[str] = dataclass_field(default=None, kw_only=True) + coupon_code: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -454,9 +579,9 @@ class AccountInput: Definition: accountInput """ - email: Optional[str] = None - cc_emails: Optional[str] = None - address: Optional[Address] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) + cc_emails: Optional[str] = dataclass_field(default=None, kw_only=True) + address: Optional[Address | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -465,10 +590,10 @@ class RunView: Definition: RunView """ - name: Optional[str] = None - is_active: Optional[int] = None - filter_type: Optional[str] = None - criteria: Optional[List[str]] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + is_active: Optional[int] = dataclass_field(default=None, kw_only=True) + filter_type: Optional[str] = dataclass_field(default=None, kw_only=True) + criteria: Optional[List[str]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -477,10 +602,10 @@ class RunViewInput: Definition: runViewInput """ - name: Optional[str] = None - filter_type: Optional[str] = None - is_active: Optional[int] = None - criteria: Optional[List[Dict[str, Any]]] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + filter_type: Optional[str] = dataclass_field(default=None, kw_only=True) + is_active: Optional[int] = dataclass_field(default=None, kw_only=True) + criteria: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -489,9 +614,14 @@ class PreferenceInput: Definition: preferenceInput """ - slug: Optional[str] = None - value: Optional[str] = None - metadata: Optional[GenericObject] = None + slug: Optional[str] = dataclass_field(default=None, kw_only=True) + value: Optional[str] = dataclass_field(default=None, kw_only=True) + metadata: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -500,15 +630,15 @@ class AccountsInput: Definition: accountsInput """ - email: Optional[str] = None - first_name: Optional[str] = None - last_name: Optional[str] = None - username: Optional[str] = None - phone: Optional[str] = None - job_title: Optional[str] = None - job_description: Optional[str] = None - timezone: Optional[str] = None - country_id: Optional[int] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) + first_name: Optional[str] = dataclass_field(default=None, kw_only=True) + last_name: Optional[str] = dataclass_field(default=None, kw_only=True) + username: Optional[str] = dataclass_field(default=None, kw_only=True) + phone: Optional[str] = dataclass_field(default=None, kw_only=True) + job_title: Optional[str] = dataclass_field(default=None, kw_only=True) + job_description: Optional[str] = dataclass_field(default=None, kw_only=True) + timezone: Optional[str] = dataclass_field(default=None, kw_only=True) + country_id: Optional[int] = dataclass_field(default=None, kw_only=True) @dataclass @@ -517,9 +647,9 @@ class InviteInput: Definition: inviteInput """ - first_name: Optional[str] = None - last_name: Optional[str] = None - email: Optional[str] = None + first_name: Optional[str] = dataclass_field(default=None, kw_only=True) + last_name: Optional[str] = dataclass_field(default=None, kw_only=True) + email: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -528,7 +658,7 @@ class Passwordreset: Definition: passwordreset """ - new_password: Optional[str] = None + new_password: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -537,9 +667,9 @@ class Passwordreseterro: Definition: passwordreseterro """ - error: Optional[bool] = None - message: Optional[str] = None - code: Optional[str] = None + error: Optional[bool] = dataclass_field(default=None, kw_only=True) + message: Optional[str] = dataclass_field(default=None, kw_only=True) + code: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -548,7 +678,7 @@ class CheckUrlInput: Definition: checkUrlInput """ - url: Optional[str] = None + url: str @dataclass @@ -557,8 +687,12 @@ class AssetSubject: Definition: AssetSubject """ - id: Optional[int] = None - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + id: Optional[int] = dataclass_field(default=None, kw_only=True) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) @dataclass @@ -567,12 +701,17 @@ class Asset: Definition: Asset """ - id: Optional[str] = None - filename: Optional[str] = None - version: Optional[int] = None - step_id: Optional[str] = None - uploaded_from: Optional[str] = None - subject: Optional[AssetSubject] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + filename: Optional[str] = dataclass_field(default=None, kw_only=True) + version: Optional[int] = dataclass_field(default=None, kw_only=True) + step_id: Optional[str] = dataclass_field(default=None, kw_only=True) + uploaded_from: Optional[str] = dataclass_field(default=None, kw_only=True) + subject: Optional[ + AssetSubject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -581,13 +720,18 @@ class CaptureInput: Definition: CaptureInput """ - alias: Optional[str] = None - field_type: Optional[str] = None - guidance: Optional[str] = None - label: Optional[str] = None - position: Optional[int] = None - required: Optional[bool] = None - options: Optional[List[GenericObject]] = None + alias: Optional[str] = dataclass_field(default=None, kw_only=True) + field_type: Optional[str] = dataclass_field(default=None, kw_only=True) + guidance: Optional[str] = dataclass_field(default=None, kw_only=True) + label: Optional[str] = dataclass_field(default=None, kw_only=True) + position: Optional[int] = dataclass_field(default=None, kw_only=True) + required: Optional[bool] = dataclass_field(default=None, kw_only=True) + options: Optional[ + List[GenericObject | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -596,18 +740,18 @@ class Capture: Definition: Capture """ - id: Optional[int] = None - step_id: Optional[int] = None - alias: Optional[str] = None - field_type: Optional[str] = None - guidance: Optional[str] = None - label: Optional[str] = None - position: Optional[int] = None - required: Optional[bool] = None - options: Optional[str] = None - created_at: Optional[RequestDate] = None - last_updated: Optional[RequestDate] = None - archived_at: Optional[RequestDate] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) + step_id: Optional[int] = dataclass_field(default=None, kw_only=True) + alias: Optional[str] = dataclass_field(default=None, kw_only=True) + field_type: Optional[str] = dataclass_field(default=None, kw_only=True) + guidance: Optional[str] = dataclass_field(default=None, kw_only=True) + label: Optional[str] = dataclass_field(default=None, kw_only=True) + position: Optional[int] = dataclass_field(default=None, kw_only=True) + required: Optional[bool] = dataclass_field(default=None, kw_only=True) + options: Optional[str] = dataclass_field(default=None, kw_only=True) + created_at: Optional[RequestDate] = dataclass_field(default=None, kw_only=True) + last_updated: Optional[RequestDate] = dataclass_field(default=None, kw_only=True) + archived_at: Optional[RequestDate] = dataclass_field(default=None, kw_only=True) @dataclass @@ -616,11 +760,11 @@ class BrandingInput: Definition: brandingInput """ - bg_color: Optional[str] = None - text_color: Optional[str] = None - alternate_color: Optional[str] = None - bright_shade: Optional[str] = None - dark_shade: Optional[str] = None + bg_color: Optional[str] = dataclass_field(default=None, kw_only=True) + text_color: Optional[str] = dataclass_field(default=None, kw_only=True) + alternate_color: Optional[str] = dataclass_field(default=None, kw_only=True) + bright_shade: Optional[str] = dataclass_field(default=None, kw_only=True) + dark_shade: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -629,12 +773,12 @@ class Branding: Definition: Branding """ - bg_color: Optional[str] = None - text_color: Optional[str] = None - alternate_color: Optional[str] = None - bright_shade: Optional[str] = None - dark_shade: Optional[str] = None - updated_at: Optional[Date] = None + bg_color: Optional[str] = dataclass_field(default=None, kw_only=True) + text_color: Optional[str] = dataclass_field(default=None, kw_only=True) + alternate_color: Optional[str] = dataclass_field(default=None, kw_only=True) + bright_shade: Optional[str] = dataclass_field(default=None, kw_only=True) + dark_shade: Optional[str] = dataclass_field(default=None, kw_only=True) + updated_at: Optional[Date] = dataclass_field(default=None, kw_only=True) @dataclass @@ -643,7 +787,7 @@ class ChecklistInput: Definition: checklistInput """ - checklist: Optional[Checklist] = None + checklist: Optional[Checklist | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -652,8 +796,8 @@ class PowerbuilderInput: Definition: powerbuilderInput """ - id: Optional[str] = None - steps: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + steps: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -662,19 +806,34 @@ class CreateChecklistInput: Definition: createChecklistInput """ - title: Optional[str] = None - summary: Optional[str] = None - privacy: Optional[str] = None - settings: Optional[GenericObject] = None - contributors: Optional[List[int]] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) + summary: Optional[str] = dataclass_field(default=None, kw_only=True) + privacy: Optional[str] = dataclass_field(default=None, kw_only=True) + settings: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + contributors: Optional[List[int]] = dataclass_field(default=None, kw_only=True) """The list of users who can update the checklist.""" - tags: Optional[List[str]] = None - start_run_permissions: Optional[GenericObject] = None + tags: Optional[List[str]] = dataclass_field(default=None, kw_only=True) + start_run_permissions: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of groups and users who can access the run.""" - prerun: Optional[GenericObject] = None - user_id: Optional[int] = None + prerun: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + user_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Template creator ID""" - owner_id: Optional[int] = None + owner_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Template Owner ID""" @@ -684,23 +843,38 @@ class Checklist: Definition: Checklist """ - id: Optional[str] = None - title: Optional[str] = None - summary: Optional[str] = None - privacy: Optional[str] = None - starred: Optional[int] = None - settings: Optional[GenericObject] = None - contributors: Optional[List[int]] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + title: Optional[str] = dataclass_field(default=None, kw_only=True) + summary: Optional[str] = dataclass_field(default=None, kw_only=True) + privacy: Optional[str] = dataclass_field(default=None, kw_only=True) + starred: Optional[int] = dataclass_field(default=None, kw_only=True) + settings: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + contributors: Optional[List[int]] = dataclass_field(default=None, kw_only=True) """The list of users who can update the Blueprint.""" - statistics: Optional[GenericObject] = None - created_by: Optional[int] = None - owner_id: Optional[int] = None + statistics: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + created_by: Optional[int] = dataclass_field(default=None, kw_only=True) + owner_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Template Owner ID""" - created_at: Optional[Date] = None - last_updated: Optional[Date] = None - archived_at: Optional[Date] = None - created_ago: Optional[str] = None - steps: Optional[List[Step]] = None + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + last_updated: Optional[Date] = dataclass_field(default=None, kw_only=True) + archived_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + created_ago: Optional[str] = dataclass_field(default=None, kw_only=True) + steps: Optional[ + List[Step | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -709,8 +883,12 @@ class CommentOn: Definition: comment_on """ - id: Optional[int] = None - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + id: Optional[int] = dataclass_field(default=None, kw_only=True) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) @dataclass @@ -719,8 +897,13 @@ class CreateCommentInput: Definition: createCommentInput """ - comment_on: Optional[CommentOn] = None - content: Optional[str] = None + comment_on: Optional[ + CommentOn | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + content: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -729,13 +912,18 @@ class Comment: Definition: Comment """ - id: Optional[int] = None - comment_on: Optional[CommentOn] = None - content: Optional[str] = None - replies_count: Optional[int] = None - author_id: Optional[int] = None - metadata: Optional[str] = None - archived_at: Optional[str] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) + comment_on: Optional[ + CommentOn | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + content: Optional[str] = dataclass_field(default=None, kw_only=True) + replies_count: Optional[int] = dataclass_field(default=None, kw_only=True) + author_id: Optional[int] = dataclass_field(default=None, kw_only=True) + metadata: Optional[str] = dataclass_field(default=None, kw_only=True) + archived_at: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -744,8 +932,8 @@ class CreateGroupInput: Definition: createGroupInput """ - name: Optional[str] = None - users: Optional[List[int]] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + users: Optional[List[int]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -754,10 +942,10 @@ class Group: Definition: Group """ - id: Optional[int] = None - name: Optional[str] = None - created_at: Optional[Date] = None - updated_at: Optional[Date] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) + name: Optional[str] = dataclass_field(default=None, kw_only=True) + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + updated_at: Optional[Date] = dataclass_field(default=None, kw_only=True) @dataclass @@ -766,11 +954,11 @@ class IntegrationS3Input: Definition: integrationS3Input """ - aws_key: Optional[str] = None - aws_secret: Optional[str] = None - aws_region: Optional[str] = None - aws_bucket: Optional[str] = None - aws_account_id: Optional[str] = None + aws_key: Optional[str] = dataclass_field(default=None, kw_only=True) + aws_secret: Optional[str] = dataclass_field(default=None, kw_only=True) + aws_region: Optional[str] = dataclass_field(default=None, kw_only=True) + aws_bucket: Optional[str] = dataclass_field(default=None, kw_only=True) + aws_account_id: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -779,19 +967,29 @@ class Message: Definition: Message """ - id: Optional[int] = None - thread_id: Optional[str] = None - label: Optional[str] = None - thread_last_updated_at: Optional[str] = None - updated_at: Optional[Date] = None - content: Optional[str] = None - sent_by: Optional[int] = None - sent_at: Optional[Date] = None - created_ago: Optional[str] = None - sent_to: Optional[List[int]] = None - author_name: Optional[str] = None - author: Optional[GenericObject] = None - subject: Optional[GenericObject] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) + thread_id: Optional[str] = dataclass_field(default=None, kw_only=True) + label: Optional[str] = dataclass_field(default=None, kw_only=True) + thread_last_updated_at: Optional[str] = dataclass_field(default=None, kw_only=True) + updated_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + content: Optional[str] = dataclass_field(default=None, kw_only=True) + sent_by: Optional[int] = dataclass_field(default=None, kw_only=True) + sent_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + created_ago: Optional[str] = dataclass_field(default=None, kw_only=True) + sent_to: Optional[List[int]] = dataclass_field(default=None, kw_only=True) + author_name: Optional[str] = dataclass_field(default=None, kw_only=True) + author: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + subject: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -800,20 +998,20 @@ class Organization: Definition: Organization """ - id: Optional[int] = None - name: Optional[str] = None - address1: Optional[str] = None - address2: Optional[str] = None - address3: Optional[str] = None - slug: Optional[str] = None - welcome_title: Optional[str] = None - welcome_description: Optional[str] = None - created_on: Optional[Date] = None - last_updated: Optional[Date] = None - user_status: Optional[str] = None - joined_on: Optional[Date] = None - disabled_on: Optional[Date] = None - last_accessed: Optional[Date] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) + name: Optional[str] = dataclass_field(default=None, kw_only=True) + address1: Optional[str] = dataclass_field(default=None, kw_only=True) + address2: Optional[str] = dataclass_field(default=None, kw_only=True) + address3: Optional[str] = dataclass_field(default=None, kw_only=True) + slug: Optional[str] = dataclass_field(default=None, kw_only=True) + welcome_title: Optional[str] = dataclass_field(default=None, kw_only=True) + welcome_description: Optional[str] = dataclass_field(default=None, kw_only=True) + created_on: Optional[Date] = dataclass_field(default=None, kw_only=True) + last_updated: Optional[Date] = dataclass_field(default=None, kw_only=True) + user_status: Optional[str] = dataclass_field(default=None, kw_only=True) + joined_on: Optional[Date] = dataclass_field(default=None, kw_only=True) + disabled_on: Optional[Date] = dataclass_field(default=None, kw_only=True) + last_accessed: Optional[Date] = dataclass_field(default=None, kw_only=True) @dataclass @@ -822,10 +1020,15 @@ class Preference: Definition: Preference """ - slug: Optional[str] = None - value: Optional[str] = None - metadata: Optional[GenericObject] = None - last_updated: Optional[Date] = None + slug: Optional[str] = dataclass_field(default=None, kw_only=True) + value: Optional[str] = dataclass_field(default=None, kw_only=True) + metadata: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + last_updated: Optional[Date] = dataclass_field(default=None, kw_only=True) @dataclass @@ -834,8 +1037,8 @@ class RunRatingsInput: Definition: runRatingsInput """ - rating: Optional[float] = None - comment: Optional[str] = None + rating: Optional[float] = dataclass_field(default=None, kw_only=True) + comment: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -844,8 +1047,8 @@ class CreateRoleInput: Definition: createRoleInput """ - name: Optional[str] = None - permissions: Optional[List[str]] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + permissions: Optional[List[str]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -854,11 +1057,16 @@ class Role: Definition: Role """ - id: Optional[int] = None - name: Optional[str] = None - permissions: Optional[GenericObject] = None - created_at: Optional[Date] = None - updated_at: Optional[Date] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) + name: Optional[str] = dataclass_field(default=None, kw_only=True) + permissions: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + updated_at: Optional[Date] = dataclass_field(default=None, kw_only=True) @dataclass @@ -867,8 +1075,8 @@ class RunCollaborators: Definition: runCollaborators """ - members: Optional[List[int]] = None - guests: Optional[List[str]] = None + members: Optional[List[int]] = dataclass_field(default=None, kw_only=True) + guests: Optional[List[str]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -877,7 +1085,7 @@ class OwnerInput: Definition: ownerInput """ - owners: Optional[Any] = None + owners: Optional[Any] = dataclass_field(default=None, kw_only=True) @dataclass @@ -886,7 +1094,7 @@ class DueDateInput: Definition: dueDateInput """ - deadline: Optional[str] = None + deadline: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -895,17 +1103,17 @@ class PrerunData: Definition: PrerunData """ - id: Optional[str] = None - alias: Optional[str] = None - created_at: Optional[Date] = None - field_type: Optional[str] = None - field_value: Optional[str] = None - label: Optional[str] = None - updated_at: Optional[Date] = None - options: Optional[str] = None - position: Optional[int] = None - required: Optional[bool] = None - value: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + alias: Optional[str] = dataclass_field(default=None, kw_only=True) + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + field_type: Optional[str] = dataclass_field(default=None, kw_only=True) + field_value: Optional[str] = dataclass_field(default=None, kw_only=True) + label: Optional[str] = dataclass_field(default=None, kw_only=True) + updated_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + options: Optional[str] = dataclass_field(default=None, kw_only=True) + position: Optional[int] = dataclass_field(default=None, kw_only=True) + required: Optional[bool] = dataclass_field(default=None, kw_only=True) + value: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -914,17 +1122,27 @@ class AlertIssues: Definition: AlertIssues """ - id: Optional[str] = None - task_id: Optional[str] = None - label: Optional[str] = None - content: Optional[str] = None - sent_to: Optional[GenericObject] = None - sent_by: Optional[int] = None - created_at: Optional[Date] = None - created_ago: Optional[str] = None - recent_updated_at: Optional[Date] = None - author: Optional[GenericObject] = None - resolve_id: Optional[int] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + task_id: Optional[str] = dataclass_field(default=None, kw_only=True) + label: Optional[str] = dataclass_field(default=None, kw_only=True) + content: Optional[str] = dataclass_field(default=None, kw_only=True) + sent_to: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + sent_by: Optional[int] = dataclass_field(default=None, kw_only=True) + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + created_ago: Optional[str] = dataclass_field(default=None, kw_only=True) + recent_updated_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + author: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + resolve_id: Optional[int] = dataclass_field(default=None, kw_only=True) @dataclass @@ -933,7 +1151,12 @@ class RunAlerts: Definition: RunAlerts """ - issues: Optional[List[AlertIssues]] = None + issues: Optional[ + List[AlertIssues | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -942,27 +1165,37 @@ class Run: Definition: Run """ - id: Optional[str] = None - checklist_id: Optional[str] = None - name: Optional[str] = None - summary: Optional[str] = None - status: Optional[str] = None - progress: Optional[GenericObject] = None - started_by: Optional[int] = None - owner_id: Optional[int] = None - prerun: Optional[List[PrerunData]] = None - alerts: Optional[RunAlerts] = None - starred: Optional[bool] = None - created_at: Optional[Date] = None - started_at: Optional[Date] = None - last_updated: Optional[Date] = None - last_synced: Optional[Date] = None - completed_at: Optional[Date] = None - archived_at: Optional[Date] = None - due_date_passed: Optional[bool] = None - collaborators: Optional[List[int]] = None - due_soon: Optional[bool] = None - max_task_deadline: Optional[Date] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + checklist_id: Optional[str] = dataclass_field(default=None, kw_only=True) + name: Optional[str] = dataclass_field(default=None, kw_only=True) + summary: Optional[str] = dataclass_field(default=None, kw_only=True) + status: Optional[str] = dataclass_field(default=None, kw_only=True) + progress: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + started_by: Optional[int] = dataclass_field(default=None, kw_only=True) + owner_id: Optional[int] = dataclass_field(default=None, kw_only=True) + prerun: Optional[ + List[PrerunData | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + alerts: Optional[RunAlerts | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + starred: Optional[bool] = dataclass_field(default=None, kw_only=True) + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + started_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + last_updated: Optional[Date] = dataclass_field(default=None, kw_only=True) + last_synced: Optional[Date] = dataclass_field(default=None, kw_only=True) + completed_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + archived_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + due_date_passed: Optional[bool] = dataclass_field(default=None, kw_only=True) + collaborators: Optional[List[int]] = dataclass_field(default=None, kw_only=True) + due_soon: Optional[bool] = dataclass_field(default=None, kw_only=True) + max_task_deadline: Optional[Date] = dataclass_field(default=None, kw_only=True) @dataclass @@ -971,10 +1204,10 @@ class RunMetaInput: Definition: runMetaInput """ - run_id: Optional[str] = None - category: Optional[str] = None - slug: Optional[str] = None - value: Optional[str] = None + run_id: Optional[str] = dataclass_field(default=None, kw_only=True) + category: Optional[str] = dataclass_field(default=None, kw_only=True) + slug: Optional[str] = dataclass_field(default=None, kw_only=True) + value: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -983,11 +1216,16 @@ class Section: Definition: Section """ - id: Optional[str] = None - checklist_id: Optional[str] = None - name: Optional[str] = None - position: Optional[int] = None - condition: Optional[GenericObject] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + checklist_id: Optional[str] = dataclass_field(default=None, kw_only=True) + name: Optional[str] = dataclass_field(default=None, kw_only=True) + position: Optional[int] = dataclass_field(default=None, kw_only=True) + condition: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -996,9 +1234,14 @@ class SectionInput: Definition: SectionInput """ - name: Optional[str] = None - position: Optional[int] = None - condition: Optional[StepCondition] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + position: Optional[int] = dataclass_field(default=None, kw_only=True) + condition: Optional[ + StepCondition | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1007,8 +1250,8 @@ class SectionCreateInput: Definition: SectionCreateInput """ - name: Optional[str] = None - position: Optional[int] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + position: Optional[int] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1017,28 +1260,33 @@ class StandaloneTask: Definition: StandaloneTask """ - id: Optional[str] = None - title: Optional[str] = None - run_id: Optional[str] = None - step_id: Optional[str] = None - alias: Optional[str] = None - taskdata: Optional[GenericObject] = None - owners: Optional[StepOwner] = None - is_completable: Optional[int] = None - status: Optional[str] = None - position: Optional[int] = None - deadline: Optional[Date] = None - created_at: Optional[Date] = None - last_updated: Optional[Date] = None - archived_at: Optional[Date] = None - completed_at: Optional[Date] = None - starter_id: Optional[int] = None - completer_id: Optional[int] = None - name: Optional[str] = None - description: Optional[str] = None - owner_id: Optional[int] = None - task_type: Optional[str] = None - is_accepted: Optional[int] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + title: Optional[str] = dataclass_field(default=None, kw_only=True) + run_id: Optional[str] = dataclass_field(default=None, kw_only=True) + step_id: Optional[str] = dataclass_field(default=None, kw_only=True) + alias: Optional[str] = dataclass_field(default=None, kw_only=True) + taskdata: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + owners: Optional[StepOwner | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + is_completable: Optional[int] = dataclass_field(default=None, kw_only=True) + status: Optional[str] = dataclass_field(default=None, kw_only=True) + position: Optional[int] = dataclass_field(default=None, kw_only=True) + deadline: Optional[Date] = dataclass_field(default=None, kw_only=True) + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + last_updated: Optional[Date] = dataclass_field(default=None, kw_only=True) + archived_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + completed_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + starter_id: Optional[int] = dataclass_field(default=None, kw_only=True) + completer_id: Optional[int] = dataclass_field(default=None, kw_only=True) + name: Optional[str] = dataclass_field(default=None, kw_only=True) + description: Optional[str] = dataclass_field(default=None, kw_only=True) + owner_id: Optional[int] = dataclass_field(default=None, kw_only=True) + task_type: Optional[str] = dataclass_field(default=None, kw_only=True) + is_accepted: Optional[int] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1047,11 +1295,11 @@ class CreateStandaloneTaskInput: Definition: createStandaloneTaskInput """ - owners: Optional[StepOwner] = None - task_type: Optional[str] = None - deadline: Optional[RequestDate] = None - description: Optional[str] = None - name: Optional[str] = None + owners: Optional[StepOwner | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + task_type: Optional[str] = dataclass_field(default=None, kw_only=True) + deadline: Optional[RequestDate] = dataclass_field(default=None, kw_only=True) + description: Optional[str] = dataclass_field(default=None, kw_only=True) + name: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1060,13 +1308,18 @@ class UpdateStandaloneTaskInput: Definition: updateStandaloneTaskInput """ - taskdata: Optional[GenericObject] = None - owners: Optional[StepOwner] = None - name: Optional[str] = None - description: Optional[str] = None - task_type: Optional[str] = None - status: Optional[str] = None - deadline: Optional[RequestDate] = None + taskdata: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + owners: Optional[StepOwner | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + name: Optional[str] = dataclass_field(default=None, kw_only=True) + description: Optional[str] = dataclass_field(default=None, kw_only=True) + task_type: Optional[str] = dataclass_field(default=None, kw_only=True) + status: Optional[str] = dataclass_field(default=None, kw_only=True) + deadline: Optional[RequestDate] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1075,8 +1328,8 @@ class StepOwner: Definition: stepOwner """ - users: Optional[List[int]] = None - guests: Optional[List[str]] = None + users: Optional[List[int]] = dataclass_field(default=None, kw_only=True) + guests: Optional[List[str]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1085,10 +1338,10 @@ class StepDeadline: Definition: stepDeadline """ - value: Optional[int] = None - unit: Optional[str] = None - option: Optional[str] = None - step: Optional[str] = None + value: Optional[int] = dataclass_field(default=None, kw_only=True) + unit: Optional[str] = dataclass_field(default=None, kw_only=True) + option: Optional[str] = dataclass_field(default=None, kw_only=True) + step: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1097,11 +1350,11 @@ class StepConditionTerm: Definition: StepConditionTerm """ - subject_id: Optional[str] = None - subject_type: Optional[str] = None - operation: Optional[str] = None - statement: Optional[str] = None - logic: Optional[str] = None + subject_id: Optional[str] = dataclass_field(default=None, kw_only=True) + subject_type: Optional[str] = dataclass_field(default=None, kw_only=True) + operation: Optional[str] = dataclass_field(default=None, kw_only=True) + statement: Optional[str] = dataclass_field(default=None, kw_only=True) + logic: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1110,8 +1363,13 @@ class StepCondition: Definition: StepCondition """ - terms: Optional[List[StepConditionTerm]] = None - flag: Optional[str] = None + terms: Optional[ + List[StepConditionTerm | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + flag: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1120,18 +1378,43 @@ class CreateStepInput: Definition: createStepInput """ - title: Optional[str] = None - checklist_id: Optional[str] = None - summary: Optional[str] = None - rationale: Optional[str] = None - position: Optional[int] = None - owners: Optional[StepOwner] = None - invisibility: Optional[GenericObject] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) + checklist_id: Optional[str] = dataclass_field(default=None, kw_only=True) + summary: Optional[str] = dataclass_field(default=None, kw_only=True) + rationale: Optional[str] = dataclass_field(default=None, kw_only=True) + position: Optional[int] = dataclass_field(default=None, kw_only=True) + owners: Optional[StepOwner | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + invisibility: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of groups the step is invisible to.""" - settings: Optional[GenericObject] = None - metadata: Optional[GenericObject] = None - condition: Optional[StepCondition] = None - captures: Optional[List[CaptureInput]] = None + settings: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + metadata: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + condition: Optional[ + StepCondition | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + captures: Optional[ + List[CaptureInput | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1140,23 +1423,53 @@ class Step: Definition: Step """ - id: Optional[int] = None - checklist_id: Optional[str] = None - summary: Optional[str] = None - title: Optional[str] = None - rationale: Optional[str] = None - position: Optional[int] = None - owners: Optional[StepOwner] = None - invisibility: Optional[GenericObject] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) + checklist_id: Optional[str] = dataclass_field(default=None, kw_only=True) + summary: Optional[str] = dataclass_field(default=None, kw_only=True) + title: Optional[str] = dataclass_field(default=None, kw_only=True) + rationale: Optional[str] = dataclass_field(default=None, kw_only=True) + position: Optional[int] = dataclass_field(default=None, kw_only=True) + owners: Optional[StepOwner | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + invisibility: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of groups the step is invisible to.""" - settings: Optional[GenericObject] = None - metadata: Optional[GenericObject] = None - deadline: Optional[StepDeadline] = None - captures: Optional[GenericObject] = None - condition: Optional[GenericObject] = None - created_at: Optional[RequestDate] = None - last_updated: Optional[RequestDate] = None - archived_at: Optional[RequestDate] = None + settings: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + metadata: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + deadline: Optional[ + StepDeadline | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + captures: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + condition: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + created_at: Optional[RequestDate] = dataclass_field(default=None, kw_only=True) + last_updated: Optional[RequestDate] = dataclass_field(default=None, kw_only=True) + archived_at: Optional[RequestDate] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1165,13 +1478,13 @@ class StepMeta: Definition: StepMeta """ - step_id: Optional[str] = None - category: Optional[str] = None - slug: Optional[str] = None - value: Optional[str] = None - created_at: Optional[Date] = None - last_updated: Optional[Date] = None - archived_at: Optional[Date] = None + step_id: Optional[str] = dataclass_field(default=None, kw_only=True) + category: Optional[str] = dataclass_field(default=None, kw_only=True) + slug: Optional[str] = dataclass_field(default=None, kw_only=True) + value: Optional[str] = dataclass_field(default=None, kw_only=True) + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + last_updated: Optional[Date] = dataclass_field(default=None, kw_only=True) + archived_at: Optional[Date] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1180,11 +1493,11 @@ class Tag: Definition: Tag """ - id: Optional[str] = None - title: Optional[str] = None - items: Optional[int] = None - created_at: Optional[Date] = None - deleted_at: Optional[Date] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + title: Optional[str] = dataclass_field(default=None, kw_only=True) + items: Optional[int] = dataclass_field(default=None, kw_only=True) + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + deleted_at: Optional[Date] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1193,7 +1506,7 @@ class CreateTagInput: Definition: createTagInput """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1202,9 +1515,9 @@ class AddTagInput: Definition: addTagInput """ - tag_id: Optional[str] = None - subject_id: Optional[str] = None - subject_type: Optional[str] = None + tag_id: Optional[str] = dataclass_field(default=None, kw_only=True) + subject_id: Optional[str] = dataclass_field(default=None, kw_only=True) + subject_type: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1213,24 +1526,29 @@ class TaskObject: Definition: Task """ - id: Optional[str] = None - title: Optional[str] = None - run_id: Optional[str] = None - step_id: Optional[str] = None - alias: Optional[str] = None - taskdata: Optional[GenericObject] = None - owners: Optional[StepOwner] = None - is_completable: Optional[bool] = None - status: Optional[str] = None - position: Optional[int] = None - deadline: Optional[Date] = None - created_at: Optional[Date] = None - last_updated: Optional[Date] = None - archived_at: Optional[Date] = None - completed_at: Optional[Date] = None - starter_id: Optional[int] = None - completer_id: Optional[int] = None - run_status: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + title: Optional[str] = dataclass_field(default=None, kw_only=True) + run_id: Optional[str] = dataclass_field(default=None, kw_only=True) + step_id: Optional[str] = dataclass_field(default=None, kw_only=True) + alias: Optional[str] = dataclass_field(default=None, kw_only=True) + taskdata: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + owners: Optional[StepOwner | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + is_completable: Optional[bool] = dataclass_field(default=None, kw_only=True) + status: Optional[str] = dataclass_field(default=None, kw_only=True) + position: Optional[int] = dataclass_field(default=None, kw_only=True) + deadline: Optional[Date] = dataclass_field(default=None, kw_only=True) + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + last_updated: Optional[Date] = dataclass_field(default=None, kw_only=True) + archived_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + completed_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + starter_id: Optional[int] = dataclass_field(default=None, kw_only=True) + completer_id: Optional[int] = dataclass_field(default=None, kw_only=True) + run_status: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1239,12 +1557,12 @@ class Pagination: Definition: Pagination """ - total: Optional[int] = None - count: Optional[int] = None - per_page: Optional[int] = None - current_page: Optional[int] = None - total_pages: Optional[int] = None - links: Optional[GenericObject] = None + total: Optional[int] = dataclass_field(default=None, kw_only=True) + count: Optional[int] = dataclass_field(default=None, kw_only=True) + per_page: Optional[int] = dataclass_field(default=None, kw_only=True) + current_page: Optional[int] = dataclass_field(default=None, kw_only=True) + total_pages: Optional[int] = dataclass_field(default=None, kw_only=True) + links: Optional[GenericObject | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1253,9 +1571,14 @@ class TasksListMeta: Definition: TasksListMeta """ - overdue_tasks: Optional[int] = None - tasks_due_soon: Optional[int] = None - pagination: Optional[Pagination] = None + overdue_tasks: Optional[int] = dataclass_field(default=None, kw_only=True) + tasks_due_soon: Optional[int] = dataclass_field(default=None, kw_only=True) + pagination: Optional[ + Pagination | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1264,8 +1587,13 @@ class TasksList: Definition: TasksList """ - data: Optional[List[TaskObject]] = None - meta: Optional[TasksListMeta] = None + data: Optional[ + List[TaskObject | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + meta: Optional[TasksListMeta | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1274,25 +1602,35 @@ class CompletedProcessTask: Definition: CompletedProcessTask """ - id: Optional[str] = None - title: Optional[str] = None - run_id: Optional[str] = None - step_id: Optional[str] = None - alias: Optional[str] = None - taskdata: Optional[GenericObject] = None - owners: Optional[StepOwner] = None - is_completable: Optional[bool] = None - status: Optional[str] = None - position: Optional[int] = None - deadline: Optional[Date] = None - created_at: Optional[Date] = None - last_updated: Optional[Date] = None - archived_at: Optional[Date] = None - completed_at: Optional[Date] = None - starter_id: Optional[int] = None - completer_id: Optional[int] = None - run_status: Optional[str] = None - tasks_changed_by_rules: Optional[GenericObject] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) + title: Optional[str] = dataclass_field(default=None, kw_only=True) + run_id: Optional[str] = dataclass_field(default=None, kw_only=True) + step_id: Optional[str] = dataclass_field(default=None, kw_only=True) + alias: Optional[str] = dataclass_field(default=None, kw_only=True) + taskdata: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + owners: Optional[StepOwner | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + is_completable: Optional[bool] = dataclass_field(default=None, kw_only=True) + status: Optional[str] = dataclass_field(default=None, kw_only=True) + position: Optional[int] = dataclass_field(default=None, kw_only=True) + deadline: Optional[Date] = dataclass_field(default=None, kw_only=True) + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + last_updated: Optional[Date] = dataclass_field(default=None, kw_only=True) + archived_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + completed_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + starter_id: Optional[int] = dataclass_field(default=None, kw_only=True) + completer_id: Optional[int] = dataclass_field(default=None, kw_only=True) + run_status: Optional[str] = dataclass_field(default=None, kw_only=True) + tasks_changed_by_rules: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1301,12 +1639,17 @@ class UpdateTaskInput: Definition: updateTaskInput """ - taskdata: Optional[GenericObject] = None - threads: Optional[Dict[str, Any]] = None - owners: Optional[StepOwner] = None - status: Optional[str] = None - position: Optional[int] = None - deadline: Optional[Date] = None + taskdata: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + threads: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + owners: Optional[StepOwner | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + status: Optional[str] = dataclass_field(default=None, kw_only=True) + position: Optional[int] = dataclass_field(default=None, kw_only=True) + deadline: Optional[Date] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1315,19 +1658,34 @@ class TaskGuest: Definition: TaskGuest """ - alias: Optional[str] = None - organization: Optional[GenericObject] = None - taskdata: Optional[GenericObject] = None - threads: Optional[GenericObject] = None - status: Optional[str] = None - is_completable: Optional[bool] = None - deadline: Optional[Date] = None - created_at: Optional[Date] = None - last_updated: Optional[Date] = None - completed_at: Optional[Date] = None - step: Optional[Step] = None - step_id: Optional[int] = None - guest_email: Optional[str] = None + alias: Optional[str] = dataclass_field(default=None, kw_only=True) + organization: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + taskdata: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + threads: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + status: Optional[str] = dataclass_field(default=None, kw_only=True) + is_completable: Optional[bool] = dataclass_field(default=None, kw_only=True) + deadline: Optional[Date] = dataclass_field(default=None, kw_only=True) + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + last_updated: Optional[Date] = dataclass_field(default=None, kw_only=True) + completed_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + step: Optional[Step | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + step_id: Optional[int] = dataclass_field(default=None, kw_only=True) + guest_email: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1336,8 +1694,13 @@ class UpdateGuestsTasksInput: Definition: updateGuestsTasksInput """ - taskdata: Optional[GenericObject] = None - status: Optional[str] = None + taskdata: Optional[ + GenericObject | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + status: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1346,7 +1709,7 @@ class CreateGuestsTasksComment: Definition: createGuestsTasksComment """ - content: Optional[str] = None + content: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1355,8 +1718,8 @@ class TaskMetaInput: Definition: TaskMetaInput """ - slug: Optional[str] = None - value: Optional[GenericObject] = None + slug: Optional[str] = dataclass_field(default=None, kw_only=True) + value: Optional[GenericObject | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1365,12 +1728,12 @@ class TaskMeta: Definition: TaskMeta """ - task_id: Optional[str] = None - slug: Optional[str] = None - value: Optional[str] = None - created_at: Optional[Date] = None - last_updated: Optional[Date] = None - archived_at: Optional[Date] = None + task_id: Optional[str] = dataclass_field(default=None, kw_only=True) + slug: Optional[str] = dataclass_field(default=None, kw_only=True) + value: Optional[str] = dataclass_field(default=None, kw_only=True) + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + last_updated: Optional[Date] = dataclass_field(default=None, kw_only=True) + archived_at: Optional[Date] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1379,7 +1742,7 @@ class ThreadInput: Definition: threadInput """ - content: Optional[str] = None + content: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1388,8 +1751,8 @@ class ThreadResolveInput: Definition: threadResolveInput """ - thread_id: Optional[str] = None - content: Optional[str] = None + thread_id: Optional[str] = dataclass_field(default=None, kw_only=True) + content: Optional[str] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1398,14 +1761,14 @@ class Thread: Definition: Thread """ - id: Optional[int] = None - label: Optional[str] = None - sent_by: Optional[int] = None - content: Optional[str] = None - created_at: Optional[Date] = None - sent_to: Optional[List[int]] = None - last_updated_at: Optional[Date] = None - archived_at: Optional[Date] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) + label: Optional[str] = dataclass_field(default=None, kw_only=True) + sent_by: Optional[int] = dataclass_field(default=None, kw_only=True) + content: Optional[str] = dataclass_field(default=None, kw_only=True) + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + sent_to: Optional[List[int]] = dataclass_field(default=None, kw_only=True) + last_updated_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + archived_at: Optional[Date] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1414,23 +1777,23 @@ class User: Definition: User """ - id: Optional[int] = None - email: Optional[str] = None - username: Optional[str] = None - first_name: Optional[str] = None - last_name: Optional[str] = None - full_name: Optional[str] = None - phone: Optional[str] = None - job_title: Optional[str] = None - job_description: Optional[str] = None - profile_pic: Optional[str] = None - locale: Optional[str] = None - active: Optional[bool] = None - is_suspended: Optional[bool] = None - country: Optional[str] = None - created_at: Optional[Date] = None - last_updated: Optional[Date] = None - last_login_at: Optional[Date] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) + email: Optional[str] = dataclass_field(default=None, kw_only=True) + username: Optional[str] = dataclass_field(default=None, kw_only=True) + first_name: Optional[str] = dataclass_field(default=None, kw_only=True) + last_name: Optional[str] = dataclass_field(default=None, kw_only=True) + full_name: Optional[str] = dataclass_field(default=None, kw_only=True) + phone: Optional[str] = dataclass_field(default=None, kw_only=True) + job_title: Optional[str] = dataclass_field(default=None, kw_only=True) + job_description: Optional[str] = dataclass_field(default=None, kw_only=True) + profile_pic: Optional[str] = dataclass_field(default=None, kw_only=True) + locale: Optional[str] = dataclass_field(default=None, kw_only=True) + active: Optional[bool] = dataclass_field(default=None, kw_only=True) + is_suspended: Optional[bool] = dataclass_field(default=None, kw_only=True) + country: Optional[str] = dataclass_field(default=None, kw_only=True) + created_at: Optional[Date] = dataclass_field(default=None, kw_only=True) + last_updated: Optional[Date] = dataclass_field(default=None, kw_only=True) + last_login_at: Optional[Date] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1439,10 +1802,10 @@ class AccessToken: Definition: AccessToken """ - access_token: Optional[str] = None - token_type: Optional[str] = None - expire: Optional[int] = None - expires_in: Optional[int] = None + access_token: Optional[str] = dataclass_field(default=None, kw_only=True) + token_type: Optional[str] = dataclass_field(default=None, kw_only=True) + expire: Optional[int] = dataclass_field(default=None, kw_only=True) + expires_in: Optional[int] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1451,7 +1814,7 @@ class GenericObject: Definition: GenericObject """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1464,8 +1827,8 @@ class Client: Definition: Client """ - name: Optional[str] = None - redirect: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) + redirect: Optional[str] = dataclass_field(default=None, kw_only=True) # Client Class @@ -1476,16 +1839,16 @@ class TallyfyClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -1496,8 +1859,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -1505,8 +1868,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -1518,7 +1881,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -1533,17 +1896,56 @@ def __init__( def connector_name(self) -> str: return "tallyfy" - async def get_user_tasks_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def get_user_tasks( self, org: str, user_id: int, + *, q: Optional[str] = None, status: Optional[str] = None, sort: Optional[str] = None, tag: Optional[str] = None, page: Optional[int] = None, per_page: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1553,6 +1955,29 @@ async def get_user_tasks_async( Get a member's tasks Get all tasks that belong to a specific member + + Swagger operation ID: `Get_User_Tasks`. + + Args: + org: Organization Id. + user_id: Member Id. + q: Search Tasks by their Process name. + status: You can search all Tasks by status. + sort: Add minus sign (-) before sort value if you want to sort + records in descending order. Ex: sort=-improvements. + tag: Search Tasks by Tag name. + page: Which results page to retrieve. Default is 1. + per_page: How many Tasks per page. Default is 10. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1596,7 +2021,7 @@ async def get_user_tasks_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1610,6 +2035,7 @@ async def get_user_tasks_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1617,9 +2043,9 @@ async def get_user_tasks_async( return json.loads(response.text) - async def invite_user_to_organization_async( + def invite_user_to_organization( self, - input: InviteUserToOrganizationInput, + input: InviteUserToOrganizationInput | Mapping[str, Any], org: str, *, timeout: Optional[float] = None, @@ -1631,13 +2057,30 @@ async def invite_user_to_organization_async( Invite a new member to your organization Invite a new member to your organization + + Swagger operation ID: `Invite_User_To_Organization`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/organizations/{quote(str(org), safe='')}/users/invite" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1651,6 +2094,7 @@ async def invite_user_to_organization_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1658,9 +2102,9 @@ async def invite_user_to_organization_async( return json.loads(response.text) - async def create_run_async( + def create_run( self, - input: CreateRunInput, + input: CreateRunInput | Mapping[str, Any], org: str, *, timeout: Optional[float] = None, @@ -1672,13 +2116,30 @@ async def create_run_async( Launch a Process Launch a process using a blueprint + + Swagger operation ID: `Create_Run`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/organizations/{quote(str(org), safe='')}/runs" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1692,6 +2153,7 @@ async def create_run_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1699,9 +2161,9 @@ async def create_run_async( return json.loads(response.text) - async def completed_one_off_task_async( + def completed_one_off_task( self, - input: CompletedOneOffTaskInput, + input: CompletedOneOffTaskInput | Mapping[str, Any], org: str, *, timeout: Optional[float] = None, @@ -1713,13 +2175,30 @@ async def completed_one_off_task_async( Complete One Off Task Complete one off task + + Swagger operation ID: `Completed_One_Off_Task`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/organizations/{quote(str(org), safe='')}/completed-tasks" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1733,6 +2212,7 @@ async def completed_one_off_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1740,7 +2220,7 @@ async def completed_one_off_task_async( return json.loads(response.text) - async def reopen_one_off_task_async( + def reopen_one_off_task( self, org: str, task: str, @@ -1754,6 +2234,22 @@ async def reopen_one_off_task_async( Reopen One Off Task Reopen one off task + + Swagger operation ID: `Reopen_One_Off_Task`. + + Args: + org: Organization Id. + task: Task Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1763,7 +2259,7 @@ async def reopen_one_off_task_async( f"/{quote(str(task), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1777,6 +2273,7 @@ async def reopen_one_off_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1784,9 +2281,9 @@ async def reopen_one_off_task_async( return json.loads(response.text) - async def completed_process_task_async( + def completed_process_task( self, - input: CompletedProcessTaskInput, + input: CompletedProcessTaskInput | Mapping[str, Any], org: str, run: str, *, @@ -1799,6 +2296,24 @@ async def completed_process_task_async( Complete process task Complete process task + + Swagger operation ID: `Completed_Process_Task`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + run: Run Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1809,7 +2324,7 @@ async def completed_process_task_async( f"/completed-tasks" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1823,6 +2338,7 @@ async def completed_process_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1830,7 +2346,7 @@ async def completed_process_task_async( return json.loads(response.text) - async def reopen_process_task_async( + def reopen_process_task( self, org: str, run: str, @@ -1845,6 +2361,23 @@ async def reopen_process_task_async( Reopen process Task Reopen process task + + Swagger operation ID: `Reopen_Process_Task`. + + Args: + org: Organization Id. + run: Run Id. + task: Task Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1856,7 +2389,7 @@ async def reopen_process_task_async( f"/{quote(str(task), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1870,6 +2403,7 @@ async def reopen_process_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1877,9 +2411,9 @@ async def reopen_process_task_async( return json.loads(response.text) - async def comment_task_async( + def comment_task( self, - input: CommentTaskInput, + input: CommentTaskInput | Mapping[str, Any], org: str, task: str, *, @@ -1892,6 +2426,24 @@ async def comment_task_async( Add comment, report issue, resolve issue on a task task deadline, in date-time format + + Swagger operation ID: `Comment_Task`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + task: Task Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1902,7 +2454,7 @@ async def comment_task_async( f"/comment" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1916,6 +2468,7 @@ async def comment_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1923,9 +2476,9 @@ async def comment_task_async( return json.loads(response.text) - async def create_task_async( + def create_task( self, - input: CreateTaskInput, + input: CreateTaskInput | Mapping[str, Any], org: str, *, timeout: Optional[float] = None, @@ -1937,6 +2490,23 @@ async def create_task_async( Create a task Create Task + + Swagger operation ID: `Create_Task`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1947,7 +2517,7 @@ async def create_task_async( f"/tasks" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1961,6 +2531,7 @@ async def create_task_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1968,9 +2539,9 @@ async def create_task_async( return json.loads(response.text) - async def edit_task_deadline_async( + def edit_task_deadline( self, - input: EditTaskDeadlineInput, + input: EditTaskDeadlineInput | Mapping[str, Any], org: str, task: str, *, @@ -1983,6 +2554,24 @@ async def edit_task_deadline_async( Edit task deadline Edit deadline of a task + + Swagger operation ID: `Edit_Task_Deadline`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + task: Task id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1995,7 +2584,7 @@ async def edit_task_deadline_async( f"/edit-deadline" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -2009,6 +2598,7 @@ async def edit_task_deadline_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2016,7 +2606,7 @@ async def edit_task_deadline_async( return json.loads(response.text) - async def remove_guest_async( + def remove_guest( self, org: str, task: str, @@ -2031,6 +2621,23 @@ async def remove_guest_async( Remove guest assigned Remove guest of a task + + Swagger operation ID: `Remove_Guest`. + + Args: + org: Organization Id. + task: Task id. + guest: Guest email. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2044,7 +2651,7 @@ async def remove_guest_async( f"/{quote(str(guest), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -2058,6 +2665,7 @@ async def remove_guest_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2065,7 +2673,7 @@ async def remove_guest_async( return json.loads(response.text) - async def remove_assignee_async( + def remove_assignee( self, org: str, task: str, @@ -2080,6 +2688,23 @@ async def remove_assignee_async( Remove assignee Remove assignee of a task + + Swagger operation ID: `Remove_Assignee`. + + Args: + org: Organization Id. + task: Task id. + member: Member id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2093,7 +2718,7 @@ async def remove_assignee_async( f"/{quote(str(member), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -2107,6 +2732,7 @@ async def remove_assignee_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2114,9 +2740,9 @@ async def remove_assignee_async( return json.loads(response.text) - async def edit_step_type_async( + def edit_step_type( self, - input: EditStepTypeInput, + input: EditStepTypeInput | Mapping[str, Any], org: str, blueprint: str, step: str, @@ -2130,6 +2756,25 @@ async def edit_step_type_async( Edit step type Edit step type + + Swagger operation ID: `Edit_Step_Type`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + org: Organization Id. + blueprint: Blueprint id. + step: Step id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2144,7 +2789,7 @@ async def edit_step_type_async( f"/edit-step-type" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -2158,6 +2803,7 @@ async def edit_step_type_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2165,7 +2811,7 @@ async def edit_step_type_async( return json.loads(response.text) - async def get_user_organizations_async( + def get_user_organizations( self, *, timeout: Optional[float] = None, @@ -2177,10 +2823,24 @@ async def get_user_organizations_async( Get user's organizations Get user's organizations + + Swagger operation ID: `Get_User_Organizations`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/me/organizations" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2194,6 +2854,7 @@ async def get_user_organizations_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2201,7 +2862,7 @@ async def get_user_organizations_async( return json.loads(response.text) - async def get_organization_users_async( + def list_organization_users( self, org: str, *, @@ -2209,34 +2870,74 @@ async def get_organization_users_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get organization's users Get all users belonging to an organization + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Get_Organization_Users`. + + Args: + org: Organization Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/organizations/{quote(str(org), safe='')}/users" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("data", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/teams.py b/src/azure/connectors/teams.py index fd50fd3..520cf25 100644 --- a/src/azure/connectors/teams.py +++ b/src/azure/connectors/teams.py @@ -5,21 +5,184 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Literal, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Literal, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core import MatchConditions +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "TeamsClient", + "Activities", + "AddMemberToChannelInput", + "AddMemberToChatInput", + "AddMemberToTagInput", + "AddMemberToTagResponseSchema", + "AddMemberToTeamInput", + "AddSectionItemInput", + "AiInsightActionItem", + "AiInsightCollectionResponse", + "AiInsightDetailResponse", + "AiInsightMeetingNote", + "AiInsightMeetingNoteSubpoint", + "AiInsightMentionEvent", + "AiInsightResponse", + "AiInsightViewpoint", + "AiInsightWebhookResponseSchema", + "ArchiveChannelInput", + "AssociatedTeamInfo", + "AsyncOperationResponse", + "AtMentionBotResponse", + "AtMentionTagResponse", + "AtMentionUser", + "BotIdForChat", + "BotMentionRequest", + "CallEventWebhookResponseSchema", + "CallRecordingCollectionResponse", + "CallRecordingResponse", + "CallTranscriptCollectionResponse", + "CallTranscriptResponse", + "CardResponseTriggerMetadata", + "ChannelIdForTeam", + "ChannelIds", + "ChannelWithOwnerTeamId", + "ChatId", + "ChatMessage", + "ChatMessageList", + "ChatMessageWebhookResponseSchema", + "ComposeMessageTriggerMetadata", + "ConnectorMetadata", + "CreateATeamInput", + "CreateATeamResponse", + "CreateChannelInput", + "CreateChannelResponse", + "CreateSectionInput", + "CreateTagInput", + "CreateTagResponseSchema", + "DiscoverySettings", + "DraftOpenShift", + "DraftShift", + "DynamicAiInsightTriggerRequest", + "DynamicAtMentionWebhookTriggerResponseSchema", + "DynamicCallEventTriggerRequest", + "DynamicCardResponseTriggerResult", + "DynamicChannelAdaptiveCardRequest", + "DynamicChannelFlowContinuationSubscriptionResult", + "DynamicChannelNotificationRequest", + "DynamicComposeMessageTriggerResult", + "DynamicGatherInputSubscriptionResult", + "DynamicGetMessageDetailsResponseSchema", + "DynamicGetMessageDetailsSchema", + "DynamicKeywordWebhookTriggerResponseSchema", + "DynamicListMembersSchema", + "DynamicNewMessageWebhookTriggerResponseSchema", + "DynamicPostCardAndWaitRequest", + "DynamicPostCardRequest", + "DynamicPostConversationNotificationRequest", + "DynamicPostFeedNotificationRequest", + "DynamicPostGatherInputToConversationResponse", + "DynamicPostMessageRequest", + "DynamicPostToConversationResponse", + "DynamicRecordingTriggerRequest", + "DynamicReplyCardRequest", + "DynamicReplyMessageRequest", + "DynamicResponseSchema", + "DynamicSelectedMessageTriggerResult", + "DynamicTranscriptTriggerRequest", + "DynamicUpdateCardRequest", + "DynamicUserAdaptiveCardRequest", + "DynamicUserFlowContinuationSubscriptionResult", + "DynamicUserMessageWithOptionsSubscriptionRequest", + "DynamicUserMessageWithOptionsSubscriptionResult", + "DynamicUserNotificationRequest", + "DynamicWebhookTriggerRequestSchema", + "EditOpenShiftRequest", + "FunSettings", + "GetAllAssociatedTeamsResponse", + "GetAllChannelsForTeamResponse", + "GetAllTeamsResponse", + "GetChannelResponse", + "GetChannelsForGroupResponse", + "GetChatsResponse", + "GetFlowContinuationSubscriptionWithPosterOutputMetadataInput", + "GetMessageDetailsSchema", + "GetMessageLocationsResponse", + "GetMessagesFromConversationResponse", + "GetOnlineMeetingResponse", + "GetTagMembersResponseSchema", + "GetTagsResponseSchema", + "GetTeamResponse", + "GetTimeOffReasonsResponse", + "GuestSettings", + "LastModifiedBy", + "ListMembersResponseSchema", + "ListMembersSchema", + "ListRepliesResponseSchema", + "ListSectionItemsResponse", + "ListSectionsResponse", + "MemberSettings", + "MessageId", + "MessageReactionWebhookResponseSchema", + "MessagingSettings", + "MoveSectionItemInput", + "NewChat", + "NewChatResponse", + "NewMeeting", + "NewMeetingResponse", + "ObjectEntity", + "ObjectWithoutType", + "OfferShiftRequestResponse", + "OnGroupMemberChangeResponse", + "OpenShiftChangeRequestResponse", + "OpenShiftResponse", + "PostCardAndWaitForResponseInput", + "PostCardAndWaitSchema", + "PostCardSchema", + "PostFeedSchema", + "PostMessageSchema", + "PostMessageToSelfRequest", + "PostToConversationResponse", + "RecordingWebhookResponseSchema", + "ScheduleResponse", + "SchedulingGroupResponse", + "SectionItemConflictError", + "SectionItemResponse", + "SectionResponse", + "SelectedMessageTriggerMetadata", + "SharedOpenShift", + "SharedShift", + "ShiftResponse", + "SingleTagMemberTriggerRequest", + "SingleTagTriggerRequest", + "SwapShiftsChangeRequestResponse", + "TagMemberWebhookResponseSchema", + "TagWebhookResponseSchema", + "TeamsIdentitySet", + "ThemeEditor", + "TimeOffRequestResponse", + "TranscriptWebhookResponseSchema", + "UnifiedActionSchema", + "UpdateChannelPropertiesInput", + "UpdateSectionInput", + "UpdateTagInput", + "VirtualAgentBots", + "WebhookChatMessageTriggerInput", + "WebhookRequest", + "WebhookTriggerSchema", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,128 +192,149 @@ class NewMeetingResponse: Response for Create a Teams meeting """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier for the event""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """Timestamp the event was created""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """Timestamp the event was last modified""" - categories: Optional[List[Any]] = None + categories: Optional[List[Any]] = dataclass_field(default=None, kw_only=True) """The categories associated with the event""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "timeZone"}, ) """Time zone of the event""" - reminder_minutes_before_start: Optional[int] = field( + reminder_minutes_before_start: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reminderMinutesBeforeStart"}, ) """ The number of minutes before the event start time that the reminder alert occurs """ - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isReminderOn"}, ) """Set to true if an alert is set to remind the user of the event""" - has_attachments: Optional[bool] = field( + has_attachments: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "hasAttachments"}, ) """Set to true if the event has attachments""" - subject: Optional[str] = None + subject: Optional[str] = dataclass_field(default=None, kw_only=True) """The text of the event's subject line""" - body_preview: Optional[str] = field( + body_preview: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "bodyPreview"}, ) """The preview of the message associated with the event""" - importance: Optional[str] = None + importance: Optional[str] = dataclass_field(default=None, kw_only=True) """ The importance of the event. The possible values are: low, normal, high """ - sensitivity: Optional[str] = None + sensitivity: Optional[str] = dataclass_field(default=None, kw_only=True) """Sensitivity of the event""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAllDay"}, ) """Set to true if the event lasts all day""" - is_cancelled: Optional[bool] = field( + is_cancelled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isCancelled"}, ) """Set to true if the event has been canceled""" - is_organizer: Optional[bool] = field( + is_organizer: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isOrganizer"}, ) """Set to true if the calendar owner is the organizer of the event""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseRequested"}, ) """The organizer would like an invitee to send a response to the event""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showAs"}, ) """ The status to show. Possible values are: free, tentative, busy, oof, workingElsewhere, unknown. """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """ The event type. Possible values are: singleInstance, occurrence, exception, seriesMaster """ - web_link: Optional[str] = field( + web_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webLink"}, ) """The URL to open the event in Outlook on the web.""" - online_meeting_url: Optional[str] = field( + online_meeting_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onlineMeetingUrl"}, ) """A URL for an online meeting""" - allow_new_time_proposals: Optional[bool] = field( + allow_new_time_proposals: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowNewTimeProposals"}, ) """ True if the meeting organizer allows invitees to propose a new time when responding """ - recurrence: Optional[Dict[str, Any]] = None + recurrence: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The recurrence pattern for the event""" - response_status: Optional[Dict[str, Any]] = field( + response_status: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseStatus"}, ) """Indicates the type of response sent in response to an event message""" - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The body of the message associated with the event""" - start: Optional[Dict[str, Any]] = None + start: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The start date, time, and time zone of the event""" - end: Optional[Dict[str, Any]] = None + end: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The date, time, and time zone that the event ends""" - location: Optional[Dict[str, Any]] = None + location: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The location of the event""" - attendees: Optional[List[Dict[str, Any]]] = None + attendees: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """The collection of attendees for the event""" - organizer: Optional[Dict[str, Any]] = None + organizer: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Organizer""" - online_meeting: Optional[Dict[str, Any]] = field( + online_meeting: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "onlineMeeting"}, ) """Details for an attendee to join the meeting online.""" @@ -162,11 +346,12 @@ class GetAllTeamsResponse: Response for List joined teams """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of the teams you are a member of""" @@ -176,11 +361,17 @@ class GetAllAssociatedTeamsResponse: Response for List associated teams """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[AssociatedTeamInfo]] = None + value: Optional[ + List[AssociatedTeamInfo | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of the teams you are associated with""" @@ -190,11 +381,17 @@ class GetChannelsForGroupResponse: Response for List channels """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[GetChannelResponse]] = None + value: Optional[ + List[GetChannelResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of one or more channels for a specific team""" @@ -204,15 +401,13 @@ class CreateChannelInput: Create a channel """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Optional textual description for the channel""" - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """Channel name as it appears in Microsoft Teams""" - membership_type: Optional[str] = field( + membership_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "membershipType"}, ) """ @@ -228,17 +423,19 @@ class CreateChannelResponse: Response for Create a channel """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Optional textual description for the channel""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Channel name as it appears in Microsoft Teams""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The channel's unique identifier""" - membership_type: Optional[str] = field( + membership_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "membershipType"}, ) """The type of channel membership""" @@ -250,39 +447,45 @@ class GetChannelResponse: Response for Get details for a specific channel in a team """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique identifier of the channel""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The name of the channel""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the channel, optional""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """The email address for sending messages to the channel""" - tenant_id: Optional[str] = field( + tenant_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tenantId"}, ) """The ID of the Microsoft Entra tenant.""" - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webUrl"}, ) """A hyperlink for the channel in Microsoft Teams""" - files_folder_web_url: Optional[str] = field( + files_folder_web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filesFolderWebUrl"}, ) """The SharePoint folder URL of the channel""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """Timestamp at which the channel was created. Read only""" - membership_type: Optional[str] = field( + membership_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "membershipType"}, ) """The channel membership type""" @@ -294,12 +497,13 @@ class UpdateChannelPropertiesInput: Update channel """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The new display name for the channel.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """The new description for the channel.""" @@ -309,8 +513,9 @@ class ArchiveChannelInput: Archive a channel """ - should_set_spo_site_read_only_for_members: Optional[bool] = field( + should_set_spo_site_read_only_for_members: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shouldSetSpoSiteReadOnlyForMembers"}, ) """ @@ -325,7 +530,7 @@ class AsyncOperationResponse: Response for Archive a channel """ - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status of the asynchronous operation""" @@ -335,11 +540,17 @@ class GetAllChannelsForTeamResponse: Response for List all channels """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[ChannelWithOwnerTeamId]] = None + value: Optional[ + List[ChannelWithOwnerTeamId | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of one or more channels for a specific team""" @@ -349,11 +560,12 @@ class GetChatsResponse: Response for List chats """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of one or more chats you are a part of""" @@ -363,8 +575,9 @@ class AtMentionTagResponse: Response for Get an @mention token for a team tag """ - at_mention: Optional[str] = field( + at_mention: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "atMention"}, ) """ @@ -379,22 +592,25 @@ class GetMessagesFromConversationResponse: Response for Get messages in a channel """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) """@odata.context""" - count: Optional[int] = field( + count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.count"}, ) """@odata.count""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """@odata.nextLink""" - value: Optional[ChatMessageList] = None + value: Optional[ChatMessageList] = dataclass_field(default=None, kw_only=True) @dataclass @@ -403,7 +619,7 @@ class DynamicGetMessageDetailsResponseSchema: Response for Get message details """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -416,7 +632,7 @@ class ListRepliesResponseSchema: Response for List replies of a channel message """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List replies response""" @@ -426,11 +642,11 @@ class ListMembersResponseSchema: Response for List chat or channel members """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List members response""" -ChatMessageList = List["ChatMessage"] +ChatMessageList = List["ChatMessage | Mapping[str, Any]"] @dataclass @@ -439,8 +655,9 @@ class WebhookChatMessageTriggerInput: When a new chat message is added """ - notification_url: Optional[str] = field( + notification_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notificationUrl"}, ) @@ -451,48 +668,57 @@ class GetTeamResponse: Response for Get a team """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique identifier of the team""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The name of the team""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the team, optional""" - internal_id: Optional[str] = field( + internal_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "internalId"}, ) """The internal ID of the team""" - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webUrl"}, ) """A hyperlink that will go to the team in the Microsoft Teams client""" - is_archived: Optional[bool] = field( + is_archived: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isArchived"}, ) """Whether this team is in read-only mode""" - member_settings: Optional[MemberSettings] = field( + member_settings: Optional[MemberSettings | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "memberSettings"}, ) - guest_settings: Optional[GuestSettings] = field( + guest_settings: Optional[GuestSettings | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "guestSettings"}, ) - messaging_settings: Optional[MessagingSettings] = field( + messaging_settings: Optional[MessagingSettings | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "messagingSettings"}, ) - fun_settings: Optional[FunSettings] = field( + fun_settings: Optional[FunSettings | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "funSettings"}, ) - discovery_settings: Optional[DiscoverySettings] = field( + discovery_settings: Optional[DiscoverySettings | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "discoverySettings"}, ) @@ -503,8 +729,9 @@ class AtMentionUser: Response for Get an @mention token for a user """ - at_mention: Optional[str] = field( + at_mention: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "atMention"}, ) """ @@ -521,7 +748,7 @@ class NewChatResponse: Response for Create a chat """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The chat's unique identifier""" @@ -531,61 +758,66 @@ class ChatMessage: Response for Post a message to myself """ - attachments: Optional[List[Dict[str, Any]]] = None + attachments: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """attachments""" - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Plaintext representation of the content of the message""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """Timestamp of when the chat message was created""" - deleted: Optional[bool] = None + deleted: Optional[bool] = dataclass_field(default=None, kw_only=True) """deleted""" - etag: Optional[str] = None + etag: Optional[str] = dataclass_field(default=None, kw_only=True) """Version number of the chat message.""" - from_: Optional[Dict[str, Any]] = field( + from_: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "from"}, ) """The message sender""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the message""" - importance: Optional[str] = None + importance: Optional[str] = dataclass_field(default=None, kw_only=True) """ The importance of the message. The possible values are: normal, high, urgent. """ - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """ Timestamp when the chat message is created (initial setting) or modified, including when a reaction is added or removed """ - locale: Optional[str] = None + locale: Optional[str] = dataclass_field(default=None, kw_only=True) """Locale of the chat message set by the client.""" - mentions: Optional[List[Dict[str, Any]]] = None + mentions: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """ List of entities mentioned in the chat message. Supported entities are: user, bot, team, and channel. """ - message_type: Optional[str] = field( + message_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "messageType"}, ) """The type of chat message""" - reactions: Optional[List[Dict[str, Any]]] = None + reactions: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Reactions for this chat message (for example, Like)""" - reply_to_id: Optional[str] = field( + reply_to_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "replyToId"}, ) """ID of the parent message of the thread""" - subject: Optional[str] = None + subject: Optional[str] = dataclass_field(default=None, kw_only=True) """The subject of the chat message, optional""" - summary: Optional[str] = None + summary: Optional[str] = dataclass_field(default=None, kw_only=True) """ Summary text of the message that could be used for push notifications and summary views or fall back views @@ -598,14 +830,11 @@ class CreateATeamInput: Create a team """ - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """The name of the team""" - description: Optional[str] = None + description: str """An optional description for the team""" - visibility: Optional[str] = None + visibility: Optional[str] = dataclass_field(default=None, kw_only=True) """The visibility of the the team""" @@ -615,8 +844,9 @@ class CreateATeamResponse: Response for Create a team """ - new_team_id: Optional[str] = field( + new_team_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "newTeamId"}, ) """Team ID of the team that was just created""" @@ -628,12 +858,9 @@ class AddMemberToTeamInput: Add a member to a team """ - user_id: Optional[str] = field( - default=None, - metadata={"wire_name": "userId"}, - ) + user_id: str = dataclass_field(metadata={"wire_name": "userId"}) """User principal name or Microsoft Entra ID to add""" - owner: Optional[bool] = None + owner: Optional[bool] = dataclass_field(default=None, kw_only=True) """True, if the user should be a team owner""" @@ -643,12 +870,9 @@ class AddMemberToChannelInput: Add a member to a channel """ - user_id: Optional[str] = field( - default=None, - metadata={"wire_name": "userId"}, - ) + user_id: str = dataclass_field(metadata={"wire_name": "userId"}) """User principal name or Microsoft Entra ID to add""" - owner: Optional[bool] = None + owner: Optional[bool] = dataclass_field(default=None, kw_only=True) """True, if the user should be a channel owner""" @@ -658,15 +882,17 @@ class PostToConversationResponse: Response for Post message in a chat or channel """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique message ID""" - message_link: Optional[str] = field( + message_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "messageLink"}, ) """Link to the message in Microsoft Teams""" - conversation_id: Optional[str] = field( + conversation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "conversationId"}, ) """The chat's unique identifier""" @@ -678,11 +904,10 @@ class PostCardAndWaitForResponseInput: Post adaptive card and wait for a response """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "notificationUrl"}, ) - body: Optional[Dict[str, Any]] = None + body: Dict[str, Any] @dataclass @@ -691,7 +916,7 @@ class DynamicPostGatherInputToConversationResponse: Response for Post adaptive card and wait for a response """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -704,7 +929,7 @@ class ObjectWithoutType: Response for Send a Microsoft Graph HTTP request """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -717,15 +942,13 @@ class AddMemberToChatInput: Add a user to a chat """ - user_id: Optional[str] = field( - default=None, - metadata={"wire_name": "userId"}, - ) + user_id: str = dataclass_field(metadata={"wire_name": "userId"}) """User principal name or Microsoft Entra ID to add""" - owner: Optional[bool] = None + owner: Optional[bool] = dataclass_field(default=None, kw_only=True) """True, if the user should be a chat owner""" - visible_history_start_date_time: Optional[str] = field( + visible_history_start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "visibleHistoryStartDateTime"}, ) """ @@ -740,72 +963,84 @@ class GetOnlineMeetingResponse: Response for Get an online meeting """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique identifier of the online meeting""" - subject: Optional[str] = None + subject: Optional[str] = dataclass_field(default=None, kw_only=True) """The subject of the online meeting""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """The start time of the meeting in UTC""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """The end time of the meeting in UTC""" - creation_date_time: Optional[str] = field( + creation_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "creationDateTime"}, ) """The creation time of the meeting in UTC""" - join_web_url: Optional[str] = field( + join_web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "joinWebUrl"}, ) """The URL used to join the meeting online""" - join_meeting_id_settings: Optional[Dict[str, Any]] = field( + join_meeting_id_settings: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "joinMeetingIdSettings"}, ) """Settings related to the join meeting ID""" - participants: Optional[Dict[str, Any]] = None + participants: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The participants of the meeting""" - audio_conferencing: Optional[Dict[str, Any]] = field( + audio_conferencing: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "audioConferencing"}, ) """Phone call-in information for the meeting""" - is_entry_exit_announced: Optional[bool] = field( + is_entry_exit_announced: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isEntryExitAnnounced"}, ) """ Whether announce notifications are enabled for callers joining or leaving the meeting """ - allowed_presenters: Optional[str] = field( + allowed_presenters: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowedPresenters"}, ) """Specifies who can be a presenter in the meeting""" - lobby_bypass_settings: Optional[Dict[str, Any]] = field( + lobby_bypass_settings: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lobbyBypassSettings"}, ) """Specifies which participants can bypass the meeting lobby""" - record_automatically: Optional[bool] = field( + record_automatically: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordAutomatically"}, ) """Indicates whether to record the meeting automatically""" - allow_meeting_chat: Optional[str] = field( + allow_meeting_chat: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowMeetingChat"}, ) """Specifies the mode of meeting chat""" - meeting_options_web_url: Optional[str] = field( + meeting_options_web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "meetingOptionsWebUrl"}, ) """A URL for the organizer to change settings for the meeting""" @@ -817,11 +1052,17 @@ class CallTranscriptCollectionResponse: Response for List meeting transcripts """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[CallTranscriptResponse]] = None + value: Optional[ + List[CallTranscriptResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of transcripts""" @@ -831,30 +1072,35 @@ class CallTranscriptResponse: Response for Get meeting transcript """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The transcript ID""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """The date and time when the transcript was created""" - transcript_content_url: Optional[str] = field( + transcript_content_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "transcriptContentUrl"}, ) """The URL to access the transcript content""" - meeting_id: Optional[str] = field( + meeting_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "meetingId"}, ) """The meeting ID""" - meeting_organizer_id: Optional[str] = field( + meeting_organizer_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "meetingOrganizerId"}, ) """The meeting organizer's user ID""" - call_id: Optional[str] = field( + call_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "callId"}, ) """The call ID""" @@ -866,11 +1112,17 @@ class CallRecordingCollectionResponse: Response for List meeting recordings """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[CallRecordingResponse]] = None + value: Optional[ + List[CallRecordingResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of recordings""" @@ -880,30 +1132,35 @@ class CallRecordingResponse: Response for Get meeting recording """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The recording ID""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """The date and time when the recording was created""" - recording_content_url: Optional[str] = field( + recording_content_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordingContentUrl"}, ) """The URL to access the recording content""" - meeting_id: Optional[str] = field( + meeting_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "meetingId"}, ) """The meeting ID""" - meeting_organizer_id: Optional[str] = field( + meeting_organizer_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "meetingOrganizerId"}, ) """The meeting organizer's user ID""" - call_id: Optional[str] = field( + call_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "callId"}, ) """The call ID""" @@ -915,19 +1172,26 @@ class ListSectionsResponse: Response for List sections """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - microsoft_graph_sections_version: Optional[str] = field( + microsoft_graph_sections_version: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@microsoft.graph.sectionsVersion"}, ) """ Version identifier for the sections hierarchy. Pass as If-Match on Create, Update, Delete, Add Item, Remove Item, and Move Item operations. """ - value: Optional[List[SectionResponse]] = None + value: Optional[ + List[SectionResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of sections""" @@ -937,26 +1201,26 @@ class CreateSectionInput: Create a section """ - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """The display name of the section""" - display_icon: Optional[Dict[str, Any]] = field( + display_icon: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayIcon"}, ) """ The display icon for the section. Only iconType is writable; other fields are populated by the service. """ - is_expanded: Optional[bool] = field( + is_expanded: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isExpanded"}, ) """Whether the section is expanded""" - sort_type: Optional[str] = field( + sort_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sortType"}, ) """The sort type for the section""" @@ -968,48 +1232,56 @@ class SectionResponse: Response for Create a section """ - etag: Optional[str] = field( + etag: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.etag"}, ) """ ETag for the sections collection. Pass as If-Match on Create, Update, and Delete. """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The section ID""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The display name of the section""" - display_icon: Optional[Dict[str, Any]] = field( + display_icon: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayIcon"}, ) """The display icon for the section""" - is_expanded: Optional[bool] = field( + is_expanded: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isExpanded"}, ) """Whether the section is expanded""" - sort_type: Optional[str] = field( + sort_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sortType"}, ) """The sort type for the section""" - section_type: Optional[str] = field( + section_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sectionType"}, ) """The type of section""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """The date and time when the section was created""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """The date and time when the section was last modified""" @@ -1021,26 +1293,30 @@ class UpdateSectionInput: Update a section """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The display name of the section""" - display_icon: Optional[Dict[str, Any]] = field( + display_icon: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayIcon"}, ) """ The display icon for the section. Only iconType is writable; other fields are populated by the service. """ - is_expanded: Optional[bool] = field( + is_expanded: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isExpanded"}, ) """Whether the section is expanded""" - sort_type: Optional[str] = field( + sort_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sortType"}, ) """The sort type for the section""" @@ -1052,11 +1328,17 @@ class ListSectionItemsResponse: Response for List section items """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[SectionItemResponse]] = None + value: Optional[ + List[SectionItemResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of section items""" @@ -1066,7 +1348,7 @@ class AddSectionItemInput: Add an item to a section """ - id: Optional[str] = None + id: str """ The conversation ID of the chat, channel, meeting, or community to add to the section. For community items, the service automatically normalizes the @@ -1080,31 +1362,35 @@ class SectionItemResponse: Response for Add an item to a section """ - etag: Optional[str] = field( + etag: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.etag"}, ) """ ETag for the section items collection. Pass as If-Match on Add, Remove, and Move. """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """ The unique identifier of the item. Corresponds to the conversation ID of the underlying chat, channel, meeting, or community. """ - item_type: Optional[str] = field( + item_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "itemType"}, ) """The type of the item""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """The date and time when the item was added to the section""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """The date and time when the item was last modified""" @@ -1116,8 +1402,7 @@ class MoveSectionItemInput: Move a section item """ - target_section_id: Optional[str] = field( - default=None, + target_section_id: str = dataclass_field( metadata={"wire_name": "targetSectionId"}, ) """The ID of the section to move the item to""" @@ -1129,11 +1414,12 @@ class GetTagsResponseSchema: Response for List all tags for a team """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1142,12 +1428,9 @@ class CreateTagInput: Create a tag for a team """ - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """The name of the tag as it appears to the user in Microsoft Teams.""" - members: Optional[str] = None + members: str """ List of users' IDs separated by semi-colons, identifier must be in a format like '550e8400-e29b-41d4-a716-446655440000'. @@ -1160,24 +1443,28 @@ class CreateTagResponseSchema: Response for Create a tag for a team """ - type_: Optional[str] = field( + type_: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.type"}, ) - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the tag""" - team_id: Optional[str] = field( + team_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "teamId"}, ) """ID of the team in which the tag is defined""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The name of the tag as it appears to the user in Microsoft Teams.""" - member_count: Optional[int] = field( + member_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "memberCount"}, ) """The number of users assigned to the tag""" @@ -1189,10 +1476,7 @@ class UpdateTagInput: Update a team tag """ - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """The new name of the tag as it appears to the user in Microsoft Teams.""" @@ -1202,10 +1486,7 @@ class AddMemberToTagInput: Add a member to a team tag """ - user_id: Optional[str] = field( - default=None, - metadata={"wire_name": "userId"}, - ) + user_id: str = dataclass_field(metadata={"wire_name": "userId"}) """ The user's ID of the member to add to the tag, must be in a format like '550e8400-e29b-41d4-a716-446655440000'. @@ -1218,8 +1499,9 @@ class AddMemberToTagResponseSchema: Response for Add a member to a team tag """ - user_id: Optional[str] = field( + user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userId"}, ) """User ID of the member added to the tag""" @@ -1231,7 +1513,7 @@ class GetTagMembersResponseSchema: Response for List the members of a team tag """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1240,11 +1522,17 @@ class AiInsightCollectionResponse: Response for List AI insights """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[AiInsightResponse]] = None + value: Optional[ + List[AiInsightResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of AI insights""" @@ -1254,34 +1542,40 @@ class AiInsightDetailResponse: Response for Get AI insight """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The AI insight ID""" - call_id: Optional[str] = field( + call_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "callId"}, ) """The call ID""" - content_correlation_id: Optional[str] = field( + content_correlation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentCorrelationId"}, ) """The content correlation ID""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """The date and time when the AI insight was created""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """The date and time when the AI insight ended""" - recap_url: Optional[str] = field( + recap_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recapUrl"}, ) """ @@ -1289,20 +1583,27 @@ class AiInsightDetailResponse: the underlying callAiInsight resource returned by the fetch. Present when the underlying resource provides it; otherwise absent. """ - meeting_notes: Optional[List[AiInsightMeetingNote]] = field( + meeting_notes: Optional[List[AiInsightMeetingNote | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "meetingNotes"}, ) """ Detailed notes of the meeting discussion generated by Microsoft Teams Copilot. """ - action_items: Optional[List[AiInsightActionItem]] = field( + action_items: Optional[List[AiInsightActionItem | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "actionItems"}, ) """Action items generated from the meeting conversation.""" - viewpoint: Optional[AiInsightViewpoint] = None + viewpoint: Optional[ + AiInsightViewpoint | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -1311,7 +1612,7 @@ class GetMessageLocationsResponse: Response for Conversation location for where to post """ - locations: Optional[List[Dict[str, Any]]] = None + locations: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """valid locations to post a message or reply, make verbose""" @@ -1321,7 +1622,7 @@ class GetMessageDetailsSchema: Response for Get message details response schema """ - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1330,7 +1631,7 @@ class ListMembersSchema: Response for List members input schema """ - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1339,7 +1640,7 @@ class PostFeedSchema: Response for Get feed notification input metadata """ - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1348,7 +1649,7 @@ class UnifiedActionSchema: Response for Get unified action input metadata """ - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1357,9 +1658,9 @@ class ConnectorMetadata: Response for Get message with options subscription input metadata """ - metadatatype: Optional[str] = None - activitytype: Optional[str] = None - schema: Optional[ObjectEntity] = None + metadatatype: Optional[str] = dataclass_field(default=None, kw_only=True) + activitytype: Optional[str] = dataclass_field(default=None, kw_only=True) + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1368,7 +1669,7 @@ class WebhookTriggerSchema: Response for Input schema for webhook trigger """ - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1377,7 +1678,7 @@ class DynamicResponseSchema: Response for Get response schema """ - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) GetFlowContinuationSubscriptionWithPosterOutputMetadataInput = str @@ -1389,7 +1690,7 @@ class ObjectEntity: Response for Get subscription scope input schema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1402,7 +1703,7 @@ class PostMessageSchema: Definition: PostMessageSchema """ - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1411,7 +1712,7 @@ class PostCardSchema: Definition: PostCardSchema """ - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1420,7 +1721,7 @@ class PostCardAndWaitSchema: Definition: PostCardAndWaitSchema """ - schema: Optional[ObjectEntity] = None + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -1429,7 +1730,7 @@ class DynamicGetMessageDetailsSchema: Definition: DynamicGetMessageDetailsSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1442,7 +1743,7 @@ class DynamicListMembersSchema: Definition: DynamicListMembersSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1455,7 +1756,7 @@ class DynamicUserNotificationRequest: Definition: DynamicUserNotificationRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1468,7 +1769,7 @@ class DynamicPostConversationNotificationRequest: Definition: DynamicPostConversationNotificationRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1481,7 +1782,7 @@ class DynamicChannelNotificationRequest: Definition: DynamicChannelNotificationRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1494,7 +1795,7 @@ class DynamicPostFeedNotificationRequest: Definition: DynamicPostFeedNotificationRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1507,7 +1808,7 @@ class DynamicPostMessageRequest: Definition: DynamicPostMessageRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1520,7 +1821,7 @@ class DynamicReplyMessageRequest: Definition: DynamicReplyMessageRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1533,7 +1834,7 @@ class DynamicPostCardRequest: Definition: DynamicPostCardRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1546,7 +1847,7 @@ class DynamicPostCardAndWaitRequest: Definition: DynamicPostCardAndWaitRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1559,7 +1860,7 @@ class DynamicReplyCardRequest: Definition: DynamicReplyCardRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1572,7 +1873,7 @@ class DynamicUpdateCardRequest: Definition: DynamicUpdateCardRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1585,7 +1886,7 @@ class DynamicUserAdaptiveCardRequest: Definition: DynamicUserAdaptiveCardRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1598,7 +1899,7 @@ class DynamicChannelAdaptiveCardRequest: Definition: DynamicChannelAdaptiveCardRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1611,7 +1912,7 @@ class DynamicUserMessageWithOptionsSubscriptionRequest: Definition: DynamicUserMessageWithOptionsSubscriptionRequest """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1624,7 +1925,7 @@ class DynamicUserMessageWithOptionsSubscriptionResult: Definition: DynamicUserMessageWithOptionsSubscriptionResult """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1637,7 +1938,7 @@ class DynamicSelectedMessageTriggerResult: Definition: DynamicSelectedMessageTriggerResult """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1650,7 +1951,7 @@ class DynamicComposeMessageTriggerResult: Definition: DynamicComposeMessageTriggerResult """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1663,7 +1964,7 @@ class DynamicCardResponseTriggerResult: Definition: DynamicCardResponseTriggerResult """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1676,47 +1977,56 @@ class MessageReactionWebhookResponseSchema: Definition: MessageReactionWebhookResponseSchema """ - thread_type: Optional[str] = field( + thread_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "threadType"}, ) - chat_id: Optional[str] = field( + chat_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "chatId"}, ) """The chat's unique identifier""" - team_id: Optional[str] = field( + team_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "teamId"}, ) """The team's unique identifier""" - channel_id: Optional[str] = field( + channel_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "channelId"}, ) """The channel's unique identifier""" - message_id: Optional[str] = field( + message_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "messageId"}, ) """Id of the message which was reacted""" - reply_to_id: Optional[str] = field( + reply_to_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "replyToId"}, ) """ID of the parent message of the thread""" - message_link: Optional[str] = field( + message_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "messageLink"}, ) """Link to the message which was reacted""" - user_id: Optional[str] = field( + user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userId"}, ) """Reacting user's Id""" - message_reaction: Optional[str] = field( + message_reaction: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "messageReaction"}, ) """Message reaction used""" @@ -1728,11 +2038,11 @@ class TeamsIdentitySet: Definition: TeamsIdentitySet """ - application: Optional[Dict[str, Any]] = None + application: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Application identity (bot or service)""" - device: Optional[Dict[str, Any]] = None + device: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Device identity""" - user: Optional[Dict[str, Any]] = None + user: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """User identity""" @@ -1742,15 +2052,17 @@ class CallEventWebhookResponseSchema: Definition: CallEventWebhookResponseSchema """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Event identifier""" - id_2: Optional[str] = field( + id_2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.id"}, ) """OData identifier""" - type_: Optional[str] = field( + type_: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.type"}, ) """ @@ -1758,56 +2070,64 @@ class CallEventWebhookResponseSchema: meeting-specific fields are flattened onto the base type by notification delivery). """ - call_event_type: Optional[str] = field( + call_event_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "callEventType"}, ) """Type of call event""" - event_date_time: Optional[str] = field( + event_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventDateTime"}, ) """When the event occurred""" - call_conversation_id: Optional[str] = field( + call_conversation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "callConversationId"}, ) """Call conversation identifier""" - join_web_url: Optional[str] = field( + join_web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "joinWebUrl"}, ) """ Meeting join URL (populated when the call is associated with an online meeting) """ - chat_info: Optional[Dict[str, Any]] = field( + chat_info: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "chatInfo"}, ) """ Chat information for the meeting (populated when the call is associated with an online meeting) """ - organizer_meeting_info: Optional[Dict[str, Any]] = field( + organizer_meeting_info: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "organizerMeetingInfo"}, ) """ Organizer info (populated when the call is associated with an online meeting) """ - transcription_state: Optional[Dict[str, Any]] = field( + transcription_state: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "transcriptionState"}, ) """Transcription state (set on transcriptionStateUpdated events)""" - recording_state: Optional[Dict[str, Any]] = field( + recording_state: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordingState"}, ) """Recording state (set on recordingStateUpdated events)""" - participants: Optional[List[Dict[str, Any]]] = None + participants: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Participants (set on rosterUpdated events)""" @@ -1817,44 +2137,52 @@ class TranscriptWebhookResponseSchema: Definition: TranscriptWebhookResponseSchema """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Transcript identifier""" - id_2: Optional[str] = field( + id_2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.id"}, ) """OData identifier""" - meeting_id: Optional[str] = field( + meeting_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "meetingId"}, ) """Online meeting identifier (empty for ad-hoc call transcripts)""" - call_id: Optional[str] = field( + call_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "callId"}, ) """Call identifier (set for ad-hoc call transcripts)""" - content_correlation_id: Optional[str] = field( + content_correlation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentCorrelationId"}, ) """Content correlation identifier""" - meeting_organizer: Optional[TeamsIdentitySet] = field( + meeting_organizer: Optional[TeamsIdentitySet | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "meetingOrganizer"}, ) - transcript_content_url: Optional[str] = field( + transcript_content_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "transcriptContentUrl"}, ) """URL to download the transcript content""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """When the transcript was created (UTC)""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """When the transcript ended (UTC)""" @@ -1866,20 +2194,23 @@ class AiInsightWebhookResponseSchema: Definition: AiInsightWebhookResponseSchema """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """AI insight identifier""" - id_2: Optional[str] = field( + id_2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.id"}, ) """OData identifier""" - meeting_id: Optional[str] = field( + meeting_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "meetingId"}, ) """Online meeting identifier (empty for ad-hoc call AI insights)""" - call_id: Optional[str] = field( + call_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "callId"}, ) """Call identifier (set for ad-hoc call AI insights)""" @@ -1891,44 +2222,52 @@ class RecordingWebhookResponseSchema: Definition: RecordingWebhookResponseSchema """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Recording identifier""" - id_2: Optional[str] = field( + id_2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.id"}, ) """OData identifier""" - meeting_id: Optional[str] = field( + meeting_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "meetingId"}, ) """Online meeting identifier (empty for ad-hoc call recordings)""" - call_id: Optional[str] = field( + call_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "callId"}, ) """Call identifier (set for ad-hoc call recordings)""" - content_correlation_id: Optional[str] = field( + content_correlation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentCorrelationId"}, ) """Content correlation identifier""" - meeting_organizer: Optional[TeamsIdentitySet] = field( + meeting_organizer: Optional[TeamsIdentitySet | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "meetingOrganizer"}, ) - recording_content_url: Optional[str] = field( + recording_content_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recordingContentUrl"}, ) """URL to download the recording content""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """When the recording was created (UTC)""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """When the recording ended (UTC)""" @@ -1940,7 +2279,7 @@ class ChatMessageWebhookResponseSchema: Definition: ChatMessageWebhookResponseSchema """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Message details response""" @@ -1950,7 +2289,7 @@ class DynamicWebhookTriggerRequestSchema: Definition: DynamicWebhookTriggerRequestSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1963,7 +2302,7 @@ class DynamicKeywordWebhookTriggerResponseSchema: Definition: DynamicKeywordWebhookTriggerResponseSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1976,7 +2315,7 @@ class DynamicAtMentionWebhookTriggerResponseSchema: Definition: DynamicAtMentionWebhookTriggerResponseSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -1989,7 +2328,7 @@ class DynamicNewMessageWebhookTriggerResponseSchema: Definition: DynamicNewMessageWebhookTriggerResponseSchema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -2002,7 +2341,7 @@ class DynamicPostToConversationResponse: Definition: DynamicPostToConversationResponse """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -2015,7 +2354,7 @@ class MessageId: Definition: MessageId """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique message identifier""" @@ -2025,7 +2364,7 @@ class DynamicUserFlowContinuationSubscriptionResult: Definition: DynamicUserFlowContinuationSubscriptionResult """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -2038,7 +2377,7 @@ class DynamicChannelFlowContinuationSubscriptionResult: Definition: DynamicChannelFlowContinuationSubscriptionResult """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -2051,7 +2390,7 @@ class DynamicGatherInputSubscriptionResult: Definition: DynamicGatherInputSubscriptionResult """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -2064,15 +2403,17 @@ class AssociatedTeamInfo: Definition: AssociatedTeamInfo """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique identifier of the team""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The name of the team""" - tenant_id: Optional[str] = field( + tenant_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tenantId"}, ) """The ID of the Microsoft Entra tenant this team belongs to""" @@ -2084,44 +2425,51 @@ class ChannelWithOwnerTeamId: Definition: ChannelWithOwnerTeamId """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique identifier of the channel""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The name of the channel""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the channel, optional""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """The email address for sending messages to the channel""" - tenant_id: Optional[str] = field( + tenant_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tenantId"}, ) """The ID of the Microsoft Entra tenant.""" - web_url: Optional[str] = field( + web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webUrl"}, ) """A hyperlink for the channel in Microsoft Teams""" - files_folder_web_url: Optional[str] = field( + files_folder_web_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filesFolderWebUrl"}, ) """The SharePoint folder URL of the channel""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """Timestamp at which the channel was created. Read only""" - membership_type: Optional[str] = field( + membership_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "membershipType"}, ) """The channel membership type""" - owner_team_id: Optional[str] = field( + owner_team_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ownerTeamId"}, ) """The ID of the team that owns the channel""" @@ -2133,8 +2481,7 @@ class WebhookRequest: Definition: WebhookRequest """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "notificationUrl"}, ) """ @@ -2148,11 +2495,12 @@ class GetTimeOffReasonsResponse: Definition: GetTimeOffReasonsResponse """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """The list of time off reasons.""" @@ -2162,67 +2510,79 @@ class TimeOffRequestResponse: Definition: TimeOffRequestResponse """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the TimeOff request.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - assigned_to: Optional[str] = field( + assigned_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignedTo"}, ) """The person the request is assigned to: 'manager' or 'recipient'""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """'approved', 'pending' or 'declined'""" - sender_date_time: Optional[str] = field( + sender_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderDateTime"}, ) """Time when the request was sent""" - sender_message: Optional[str] = field( + sender_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderMessage"}, ) """The message from the request sender""" - sender_user_id: Optional[str] = field( + sender_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderUserId"}, ) """The ID of the user that sent the request""" - manager_action_date_time: Optional[str] = field( + manager_action_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionDateTime"}, ) """Time when the manager responded""" - manager_action_message: Optional[str] = field( + manager_action_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionMessage"}, ) """The message from the manager""" - manager_user_id: Optional[str] = field( + manager_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerUserId"}, ) """The ID of the manager that responded""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """Start of time requested off""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """End of time requested off""" - time_off_reason_id: Optional[str] = field( + time_off_reason_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "timeOffReasonId"}, ) """The ID of the TimeOff Reason""" @@ -2234,72 +2594,85 @@ class OfferShiftRequestResponse: Definition: OfferShiftRequestResponse """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the Offer Shift request.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - assigned_to: Optional[str] = field( + assigned_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignedTo"}, ) """The person the request is assigned to: 'manager' or 'recipient'""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """'approved', 'pending' or 'declined'""" - sender_date_time: Optional[str] = field( + sender_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderDateTime"}, ) """Time when the request was sent""" - sender_message: Optional[str] = field( + sender_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderMessage"}, ) """The message from the request sender""" - sender_user_id: Optional[str] = field( + sender_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderUserId"}, ) """The ID of the user that sent the request""" - sender_shift_id: Optional[str] = field( + sender_shift_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderShiftId"}, ) """The ID of the shift from the sender""" - recipient_action_date_time: Optional[str] = field( + recipient_action_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientActionDateTime"}, ) """Time when the recipient responded""" - recipient_action_message: Optional[str] = field( + recipient_action_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientActionMessage"}, ) """The message from the recipient""" - recipient_user_id: Optional[str] = field( + recipient_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientUserId"}, ) """The ID of the recipient of the request""" - manager_action_date_time: Optional[str] = field( + manager_action_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionDateTime"}, ) """Time when the manager responded""" - manager_action_message: Optional[str] = field( + manager_action_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionMessage"}, ) """The message from the manager""" - manager_user_id: Optional[str] = field( + manager_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerUserId"}, ) """The ID of the manager that responded""" @@ -2311,77 +2684,91 @@ class SwapShiftsChangeRequestResponse: Definition: SwapShiftsChangeRequestResponse """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the Swap Shift request.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - assigned_to: Optional[str] = field( + assigned_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignedTo"}, ) """The person the request is assigned to: 'manager' or 'recipient'""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """'approved', 'pending' or 'declined'""" - sender_date_time: Optional[str] = field( + sender_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderDateTime"}, ) """Time when the request was sent""" - sender_message: Optional[str] = field( + sender_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderMessage"}, ) """The message from the request sender""" - sender_user_id: Optional[str] = field( + sender_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderUserId"}, ) """The ID of the user that sent the request""" - sender_shift_id: Optional[str] = field( + sender_shift_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderShiftId"}, ) """The ID of the shift from the sender""" - recipient_action_date_time: Optional[str] = field( + recipient_action_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientActionDateTime"}, ) """Time when the recipient responded""" - recipient_action_message: Optional[str] = field( + recipient_action_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientActionMessage"}, ) """The message from the recipient""" - recipient_user_id: Optional[str] = field( + recipient_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientUserId"}, ) """The ID of the recipient of the request""" - recipient_shift_id: Optional[str] = field( + recipient_shift_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recipientShiftId"}, ) """The ID of the shift from the recipient""" - manager_action_date_time: Optional[str] = field( + manager_action_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionDateTime"}, ) """Time when the manager responded""" - manager_action_message: Optional[str] = field( + manager_action_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionMessage"}, ) """The message from the manager""" - manager_user_id: Optional[str] = field( + manager_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerUserId"}, ) """The ID of the manager that responded""" @@ -2393,57 +2780,67 @@ class OpenShiftChangeRequestResponse: Definition: OpenShiftChangeRequestResponse """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the Open Shift Change request.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - assigned_to: Optional[str] = field( + assigned_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignedTo"}, ) """The person the request is assigned to: 'manager' or 'recipient'""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """'approved', 'pending' or 'declined'""" - sender_date_time: Optional[str] = field( + sender_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderDateTime"}, ) """Time when the request was sent""" - sender_message: Optional[str] = field( + sender_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderMessage"}, ) """The message from the request sender""" - sender_user_id: Optional[str] = field( + sender_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "senderUserId"}, ) """The ID of the user that sent the request""" - manager_action_date_time: Optional[str] = field( + manager_action_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionDateTime"}, ) """Time when the manager responded""" - manager_action_message: Optional[str] = field( + manager_action_message: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerActionMessage"}, ) """The message from the manager""" - manager_user_id: Optional[str] = field( + manager_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "managerUserId"}, ) """The ID of the manager that responded""" - open_shift_id: Optional[str] = field( + open_shift_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "openShiftId"}, ) """The ID of the open shift being requested""" @@ -2455,13 +2852,15 @@ class EditOpenShiftRequest: Definition: EditOpenShiftRequest """ - scheduling_group_id: Optional[str] = field( + scheduling_group_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "schedulingGroupId"}, ) """Scheduling Group ID""" - shared_open_shift: Optional[Dict[str, Any]] = field( + shared_open_shift: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sharedOpenShift"}, ) @@ -2472,33 +2871,39 @@ class OpenShiftResponse: Definition: OpenShiftResponse """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the open shift.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - scheduling_group_id: Optional[str] = field( + scheduling_group_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "schedulingGroupId"}, ) """Scheduling Group ID""" - last_modified_by: Optional[LastModifiedBy] = field( + last_modified_by: Optional[LastModifiedBy | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedBy"}, ) - shared_open_shift: Optional[SharedOpenShift] = field( + shared_open_shift: Optional[SharedOpenShift | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sharedOpenShift"}, ) - draft_open_shift: Optional[DraftOpenShift] = field( + draft_open_shift: Optional[DraftOpenShift | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "draftOpenShift"}, ) @@ -2509,31 +2914,35 @@ class SharedOpenShift: Definition: SharedOpenShift """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display Name""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """Notes""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - theme: Optional[str] = None + theme: Optional[str] = dataclass_field(default=None, kw_only=True) """Theme""" - open_slot_count: Optional[int] = field( + open_slot_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "openSlotCount"}, ) """Open Slot Count""" - activities: Optional[Activities] = None + activities: Optional[Activities] = dataclass_field(default=None, kw_only=True) @dataclass @@ -2542,31 +2951,35 @@ class DraftOpenShift: Definition: DraftOpenShift """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display Name""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """Notes""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - theme: Optional[str] = None + theme: Optional[str] = dataclass_field(default=None, kw_only=True) """Theme""" - open_slot_count: Optional[int] = field( + open_slot_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "openSlotCount"}, ) """Open Slot Count""" - activities: Optional[Activities] = None + activities: Optional[Activities] = dataclass_field(default=None, kw_only=True) @dataclass @@ -2575,38 +2988,45 @@ class ShiftResponse: Definition: ShiftResponse """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the shift.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - user_id: Optional[str] = field( + user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userId"}, ) """Assigned To User ID""" - scheduling_group_id: Optional[str] = field( + scheduling_group_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "schedulingGroupId"}, ) """Scheduling Group ID""" - last_modified_by: Optional[LastModifiedBy] = field( + last_modified_by: Optional[LastModifiedBy | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedBy"}, ) - shared_shift: Optional[SharedShift] = field( + shared_shift: Optional[SharedShift | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sharedShift"}, ) - draft_shift: Optional[DraftShift] = field( + draft_shift: Optional[DraftShift | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "draftShift"}, ) @@ -2617,26 +3037,29 @@ class SharedShift: Definition: SharedShift """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display Name""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """Notes""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - theme: Optional[str] = None + theme: Optional[str] = dataclass_field(default=None, kw_only=True) """Theme""" - activities: Optional[Activities] = None + activities: Optional[Activities] = dataclass_field(default=None, kw_only=True) @dataclass @@ -2645,26 +3068,29 @@ class DraftShift: Definition: DraftShift """ - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display Name""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """Notes""" - start_date_time: Optional[str] = field( + start_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """yyyy-MM-ddTHH:mm:ss.fffZ (UTC format)""" - theme: Optional[str] = None + theme: Optional[str] = dataclass_field(default=None, kw_only=True) """Theme""" - activities: Optional[Activities] = None + activities: Optional[Activities] = dataclass_field(default=None, kw_only=True) @dataclass @@ -2673,20 +3099,23 @@ class ScheduleResponse: Definition: ScheduleResponse """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the schedule.""" - time_zone: Optional[str] = field( + time_zone: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "timeZone"}, ) """The Time Zone of the schedule.""" - provision_status: Optional[str] = field( + provision_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "provisionStatus"}, ) """The Provision Status of the schedule.""" - provision_status_code: Optional[str] = field( + provision_status_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "provisionStatusCode"}, ) """The Provision Status Code of the schedule.""" @@ -2698,7 +3127,7 @@ class PostMessageToSelfRequest: Definition: PostMessageToSelfRequest """ - body: Optional[Dict[str, Any]] = None + body: Dict[str, Any] ThemeEditor = Literal[ @@ -2726,23 +3155,26 @@ class SchedulingGroupResponse: Definition: SchedulingGroupResponse """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the scheduling group.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The display name for the scheduling group.""" - is_active: Optional[bool] = field( + is_active: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isActive"}, ) """ Indicates whether the scheduling group can be used when creating new entities or updating existing ones. """ - user_ids: Optional[List[str]] = field( + user_ids: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userIds"}, ) """List of IDs of users in the scheduling group.""" @@ -2754,17 +3186,11 @@ class BotMentionRequest: Definition: BotMentionRequest """ - bot_id: Optional[str] = field( - default=None, - metadata={"wire_name": "botId"}, - ) + bot_id: str = dataclass_field(metadata={"wire_name": "botId"}) """The bot's unique identifier (GUID)""" - app_id: Optional[str] = field( - default=None, - metadata={"wire_name": "appId"}, - ) + app_id: str = dataclass_field(metadata={"wire_name": "appId"}) """The bot's app identifier (GUID)""" - name: Optional[str] = None + name: str """The bot's display name""" @@ -2774,8 +3200,9 @@ class AtMentionBotResponse: Definition: AtMentionBotResponse """ - at_mention: Optional[str] = field( + at_mention: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "atMention"}, ) """ @@ -2793,7 +3220,7 @@ class ChannelIds: Definition: ChannelIds """ - channel: Optional[ChannelIdForTeam] = None + channel: ChannelIdForTeam ChatId = str @@ -2808,9 +3235,9 @@ class NewChat: Definition: NewChat """ - topic: Optional[str] = None + topic: Optional[str] = dataclass_field(default=None, kw_only=True) """Title, displayed only in group chats""" - members: Optional[str] = None + members: str """User's IDs, separated by semicolons""" @@ -2820,70 +3247,72 @@ class NewMeeting: Definition: NewMeeting """ - subject: Optional[str] = None + subject: str """The text of the event's subject line""" - body: Optional[Dict[str, Any]] = None + body: Dict[str, Any] """The body of the message associated with the event""" - time_zone: Optional[str] = field( - default=None, - metadata={"wire_name": "timeZone"}, - ) + time_zone: str = dataclass_field(metadata={"wire_name": "timeZone"}) """Time zone of the event""" - start: Optional[Dict[str, Any]] = None - end: Optional[Dict[str, Any]] = None - required_attendees: Optional[str] = field( + start: Dict[str, Any] + end: Dict[str, Any] + required_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredAttendees"}, ) """Required attendees for the event separated by semicolons""" - optional_attendees: Optional[str] = field( + optional_attendees: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "optionalAttendees"}, ) """Optional attendees for the event separated by semicolons""" - location: Optional[Dict[str, Any]] = None + location: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The location of the event""" - importance: Optional[str] = None + importance: Optional[str] = dataclass_field(default=None, kw_only=True) """The importance of the event: low, normal or high""" - recurrence: Optional[Dict[str, Any]] = None + recurrence: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The recurrence pattern for the meeting""" - is_all_day: Optional[bool] = field( + is_all_day: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAllDay"}, ) """Set to true if the event lasts all day""" - reminder_minutes_before_start: Optional[int] = field( + reminder_minutes_before_start: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reminderMinutesBeforeStart"}, ) """ The number of minutes before the event start time that the reminder alert occurs """ - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isReminderOn"}, ) """Set to true if an alert is set to remind the user of the event""" - show_as: Optional[str] = field( + show_as: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showAs"}, ) """Status to show during the event""" - response_requested: Optional[bool] = field( + response_requested: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "responseRequested"}, ) """ Set to true if the sender would like a response when the event is accepted """ - is_online_meeting: Optional[bool] = field( - default=None, + is_online_meeting: bool = dataclass_field( metadata={"wire_name": "isOnlineMeeting"}, ) """Set to true, if the meeting should have an online meeting provider""" - online_meeting_provider: Optional[str] = field( - default=None, + online_meeting_provider: str = dataclass_field( metadata={"wire_name": "onlineMeetingProvider"}, ) """Represents the online meeting service provider""" @@ -2895,13 +3324,13 @@ class LastModifiedBy: Definition: LastModifiedBy """ - application: Optional[str] = None + application: Optional[str] = dataclass_field(default=None, kw_only=True) """Application""" - device: Optional[str] = None + device: Optional[str] = dataclass_field(default=None, kw_only=True) """Device""" - conversation: Optional[str] = None + conversation: Optional[str] = dataclass_field(default=None, kw_only=True) """Conversation""" - user: Optional[Dict[str, Any]] = None + user: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """User""" @@ -2911,28 +3340,33 @@ class MemberSettings: Definition: MemberSettings """ - allow_create_update_channels: Optional[bool] = field( + allow_create_update_channels: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowCreateUpdateChannels"}, ) """If set to true, members can add and update channels""" - allow_delete_channels: Optional[bool] = field( + allow_delete_channels: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowDeleteChannels"}, ) """If set to true, members can delete channels""" - allow_add_remove_apps: Optional[bool] = field( + allow_add_remove_apps: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowAddRemoveApps"}, ) """If set to true, members can add and remove apps""" - allow_create_update_remove_tabs: Optional[bool] = field( + allow_create_update_remove_tabs: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowCreateUpdateRemoveTabs"}, ) """If set to true, members can add, update, and remove tabs""" - allow_create_update_remove_connectors: Optional[bool] = field( + allow_create_update_remove_connectors: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowCreateUpdateRemoveConnectors"}, ) """If set to true, members can add, update, and remove connectors""" @@ -2944,13 +3378,15 @@ class GuestSettings: Definition: GuestSettings """ - allow_create_update_channels: Optional[bool] = field( + allow_create_update_channels: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowCreateUpdateChannels"}, ) """If set to true, guests can add and update channels""" - allow_delete_channels: Optional[bool] = field( + allow_delete_channels: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowDeleteChannels"}, ) """If set to true, guests can delete channels""" @@ -2962,28 +3398,33 @@ class MessagingSettings: Definition: MessagingSettings """ - allow_user_edit_messages: Optional[bool] = field( + allow_user_edit_messages: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowUserEditMessages"}, ) """If set to true, users can edit their messages""" - allow_user_delete_messages: Optional[bool] = field( + allow_user_delete_messages: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowUserDeleteMessages"}, ) """If set to true, users can delete their messages""" - allow_owner_delete_messages: Optional[bool] = field( + allow_owner_delete_messages: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowOwnerDeleteMessages"}, ) """If set to true, owners can delete any message""" - allow_team_mentions: Optional[bool] = field( + allow_team_mentions: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowTeamMentions"}, ) """If set to true, @team mentions are allowed""" - allow_channel_mentions: Optional[bool] = field( + allow_channel_mentions: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowChannelMentions"}, ) """If set to true, @channel mentions are allowed""" @@ -2995,23 +3436,27 @@ class FunSettings: Definition: FunSettings """ - allow_giphy: Optional[bool] = field( + allow_giphy: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowGiphy"}, ) """If set to true, enables Giphy use""" - giphy_content_rating: Optional[str] = field( + giphy_content_rating: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "giphyContentRating"}, ) """Giphy content rating. Possible values are: moderate, strict""" - allow_stickers_and_memes: Optional[bool] = field( + allow_stickers_and_memes: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowStickersAndMemes"}, ) """If set to true, enables users to include stickers and memes""" - allow_custom_memes: Optional[bool] = field( + allow_custom_memes: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "allowCustomMemes"}, ) """If set to true, enables users to include custom memes""" @@ -3023,8 +3468,9 @@ class DiscoverySettings: Definition: DiscoverySettings """ - show_in_teams_search_and_suggestions: Optional[bool] = field( + show_in_teams_search_and_suggestions: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "showInTeamsSearchAndSuggestions"}, ) """ @@ -3039,12 +3485,14 @@ class SelectedMessageTriggerMetadata: Definition: SelectedMessageTriggerMetadata """ - teams_flow_run_context: Optional[ObjectEntity] = field( + teams_flow_run_context: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TeamsFlowRunContext"}, ) - card_outputs: Optional[ObjectEntity] = field( + card_outputs: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CardOutputs"}, ) @@ -3055,12 +3503,14 @@ class ComposeMessageTriggerMetadata: Definition: ComposeMessageTriggerMetadata """ - teams_flow_run_context: Optional[ObjectEntity] = field( + teams_flow_run_context: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TeamsFlowRunContext"}, ) - card_outputs: Optional[ObjectEntity] = field( + card_outputs: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CardOutputs"}, ) @@ -3071,12 +3521,14 @@ class CardResponseTriggerMetadata: Definition: CardResponseTriggerMetadata """ - teams_flow_run_context: Optional[ObjectEntity] = field( + teams_flow_run_context: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TeamsFlowRunContext"}, ) - card_outputs: Optional[ObjectEntity] = field( + card_outputs: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CardOutputs"}, ) @@ -3087,11 +3539,12 @@ class VirtualAgentBots: Definition: VirtualAgentBots """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of the Microsoft Copilot Studio agents""" @@ -3101,7 +3554,7 @@ class SectionItemConflictError: Definition: SectionItemConflictError """ - error: Optional[Dict[str, Any]] = None + error: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -3110,12 +3563,11 @@ class DynamicCallEventTriggerRequest: Definition: DynamicCallEventTriggerRequest """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "notificationUrl"}, ) """Webhook callback URL""" - scope: Optional[Dict[str, Any]] = None + scope: Dict[str, Any] @dataclass @@ -3124,12 +3576,11 @@ class DynamicTranscriptTriggerRequest: Definition: DynamicTranscriptTriggerRequest """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "notificationUrl"}, ) """Webhook callback URL""" - scope: Optional[Dict[str, Any]] = None + scope: Dict[str, Any] @dataclass @@ -3138,12 +3589,11 @@ class DynamicAiInsightTriggerRequest: Definition: DynamicAiInsightTriggerRequest """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "notificationUrl"}, ) """Webhook callback URL""" - scope: Optional[Dict[str, Any]] = None + scope: Dict[str, Any] @dataclass @@ -3152,12 +3602,11 @@ class DynamicRecordingTriggerRequest: Definition: DynamicRecordingTriggerRequest """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "notificationUrl"}, ) """Webhook callback URL""" - scope: Optional[Dict[str, Any]] = None + scope: Dict[str, Any] @dataclass @@ -3166,20 +3615,13 @@ class SingleTagTriggerRequest: Definition: SingleTagTriggerRequest """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "notificationUrl"}, ) """Webhook callback URL""" - group_id: Optional[str] = field( - default=None, - metadata={"wire_name": "groupId"}, - ) + group_id: str = dataclass_field(metadata={"wire_name": "groupId"}) """The team that owns the tag to monitor""" - tag_id: Optional[str] = field( - default=None, - metadata={"wire_name": "tagId"}, - ) + tag_id: str = dataclass_field(metadata={"wire_name": "tagId"}) """The specific tag to monitor""" @@ -3189,20 +3631,13 @@ class SingleTagMemberTriggerRequest: Definition: SingleTagMemberTriggerRequest """ - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "notificationUrl"}, ) """Webhook callback URL""" - group_id: Optional[str] = field( - default=None, - metadata={"wire_name": "groupId"}, - ) + group_id: str = dataclass_field(metadata={"wire_name": "groupId"}) """The team that owns the tag whose membership to monitor""" - tag_id: Optional[str] = field( - default=None, - metadata={"wire_name": "tagId"}, - ) + tag_id: str = dataclass_field(metadata={"wire_name": "tagId"}) """The specific tag whose membership to monitor""" @@ -3212,42 +3647,49 @@ class TagWebhookResponseSchema: Definition: TagWebhookResponseSchema """ - change_type: Optional[str] = field( + change_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "changeType"}, ) """The tag lifecycle change: 'created', 'updated', or 'deleted'.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The tag identifier.""" - team_id: Optional[str] = field( + team_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "teamId"}, ) """The team (group) ID that owns the tag.""" - tag_id: Optional[str] = field( + tag_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tagId"}, ) """The tag ID.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Display name of the tag.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the tag.""" - member_count: Optional[int] = field( + member_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "memberCount"}, ) """Number of members in the tag.""" - tag_type: Optional[str] = field( + tag_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tagType"}, ) """Tag type.""" - event_id: Optional[str] = field( + event_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventId"}, ) """ @@ -3262,38 +3704,44 @@ class TagMemberWebhookResponseSchema: Definition: TagMemberWebhookResponseSchema """ - change_type: Optional[str] = field( + change_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "changeType"}, ) """ The membership change: 'created' (member added) or 'deleted' (member removed). """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The tag member identifier.""" - team_id: Optional[str] = field( + team_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "teamId"}, ) """The team (group) ID that owns the tag.""" - tag_id: Optional[str] = field( + tag_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tagId"}, ) """The tag ID whose membership changed.""" - tenant_id: Optional[str] = field( + tenant_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tenantId"}, ) """Tenant ID of the tag member.""" - user_id: Optional[str] = field( + user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userId"}, ) """User ID of the tag member.""" - event_id: Optional[str] = field( + event_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventId"}, ) """ @@ -3308,25 +3756,29 @@ class AiInsightResponse: Definition: AiInsightResponse """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The AI insight ID""" - call_id: Optional[str] = field( + call_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "callId"}, ) """The call ID""" - content_correlation_id: Optional[str] = field( + content_correlation_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "contentCorrelationId"}, ) """The content correlation ID""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """The date and time when the AI insight was created""" - end_date_time: Optional[str] = field( + end_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endDateTime"}, ) """The date and time when the AI insight ended""" @@ -3338,11 +3790,16 @@ class AiInsightMeetingNote: Definition: AiInsightMeetingNote """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of the meeting note.""" - text: Optional[str] = None + text: Optional[str] = dataclass_field(default=None, kw_only=True) """Summary text of the meeting note.""" - subpoints: Optional[List[AiInsightMeetingNoteSubpoint]] = None + subpoints: Optional[ + List[AiInsightMeetingNoteSubpoint | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Detailed subpoints of the discussion.""" @@ -3352,9 +3809,9 @@ class AiInsightMeetingNoteSubpoint: Definition: AiInsightMeetingNoteSubpoint """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of the subpoint.""" - text: Optional[str] = None + text: Optional[str] = dataclass_field(default=None, kw_only=True) """Text of the subpoint.""" @@ -3364,12 +3821,13 @@ class AiInsightActionItem: Definition: AiInsightActionItem """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of the action item.""" - text: Optional[str] = None + text: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the action item.""" - owner_display_name: Optional[str] = field( + owner_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ownerDisplayName"}, ) """Display name of the person assigned the action item.""" @@ -3381,8 +3839,11 @@ class AiInsightViewpoint: Definition: AiInsightViewpoint """ - mention_events: Optional[List[AiInsightMentionEvent]] = field( + mention_events: Optional[ + List[AiInsightMentionEvent | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mentionEvents"}, ) """ @@ -3397,17 +3858,19 @@ class AiInsightMentionEvent: Definition: AiInsightMentionEvent """ - event_date_time: Optional[str] = field( + event_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "eventDateTime"}, ) """The time during the meeting when the mention occurred (UTC).""" - transcript_utterance: Optional[str] = field( + transcript_utterance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "transcriptUtterance"}, ) """The transcript utterance containing the mention.""" - speaker: Optional[Dict[str, Any]] = None + speaker: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """The speaker who made the utterance.""" @@ -3419,16 +3882,16 @@ class TeamsClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -3439,8 +3902,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -3448,8 +3911,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -3461,7 +3924,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -3476,6 +3939,43 @@ def __init__( def connector_name(self) -> str: return "teams" + @staticmethod + def _prepare_match_headers( + headers: Optional[Mapping[str, str]], + etag: Optional[str], + match_condition: Optional[MatchConditions], + *, + if_match_required: bool, + ) -> Optional[Mapping[str, str]]: + request_headers = dict(headers) if headers is not None else {} + existing_if_match = next( + (name for name in request_headers if name.lower() == "if-match"), + None, + ) + if etag is None and match_condition is None: + if if_match_required and existing_if_match is None: + request_headers["If-Match"] = "*" + return request_headers or None + + if existing_if_match is not None: + del request_headers[existing_if_match] + if match_condition is None: + assert etag is not None + request_headers["If-Match"] = etag + elif match_condition == MatchConditions.IfNotModified: + if etag is None: + raise ValueError( + "etag is required for MatchConditions.IfNotModified." + ) + request_headers["If-Match"] = etag + elif match_condition == MatchConditions.Unconditionally: + request_headers["If-Match"] = "*" + else: + raise ValueError( + "If-Match operations support only IfNotModified or Unconditionally." + ) + return request_headers or None + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: parsed_next_link = urlsplit(next_link) if not parsed_next_link.scheme or not parsed_next_link.netloc: @@ -3483,7 +3983,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -3515,9 +4015,9 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def create_teams_meeting_async( + def create_teams_meeting( self, - input: NewMeeting, + input: NewMeeting | Mapping[str, Any], calendarid: str, *, timeout: Optional[float] = None, @@ -3530,13 +4030,30 @@ async def create_teams_meeting_async( Create a meeting with a link at the bottom of the invite to join the meeting online on Microsoft Teams. + + Swagger operation ID: `CreateTeamsMeeting`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + calendarid: Select a value. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/me/calendars/{quote(str(calendarid), safe='')}/events" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3550,6 +4067,7 @@ async def create_teams_meeting_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3557,96 +4075,197 @@ async def create_teams_meeting_async( return json.loads(response.text) - async def get_all_teams_async( + def list_all_teams( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List joined teams Lists all the teams in Microsoft Teams that you are a member of + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAllTeams`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/beta/me/joinedTeams" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def get_all_associated_teams_async( + return ItemPaged(get_next, extract_data) + + def list_all_associated_teams( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List associated teams Lists all the teams you are a direct member of, or are a member of a shared channel that is hosted inside the team. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAllAssociatedTeams`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1.0/me/teamwork/associatedTeams" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_channels_for_group_async( + def list_channels_for_group( self, group_id: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List channels Lists all the channels for a specific team + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetChannelsForGroup`. + + Args: + group_id: Select team. + filter: An OData filter query to restrict the entries returned + (e.g. membershipType eq 'standard'). + orderby: An OData orderBy query option for specifying the order of + entries (e.g., displayName asc). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3665,31 +4284,52 @@ async def get_channels_for_group_async( query_params.append(f"$orderby={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - async def create_channel_async( + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def create_channel( self, - input: CreateChannelInput, + input: CreateChannelInput | Mapping[str, Any], group_id: str, *, timeout: Optional[float] = None, @@ -3701,13 +4341,30 @@ async def create_channel_async( Create a channel Create a new channel within a specified team + + Swagger operation ID: `CreateChannel`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Select team. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/beta/groups/{quote(str(group_id), safe='')}/channels" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3721,6 +4378,7 @@ async def create_channel_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3728,7 +4386,7 @@ async def create_channel_async( return json.loads(response.text) - async def get_channel_async( + def get_channel( self, group_id: str, channel_id: str, @@ -3742,6 +4400,22 @@ async def get_channel_async( Get details for a specific channel in a team Get the channel details + + Swagger operation ID: `GetChannel`. + + Args: + group_id: Select team. + channel_id: Channel ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3752,7 +4426,7 @@ async def get_channel_async( f"/{quote(str(channel_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -3766,6 +4440,7 @@ async def get_channel_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3773,9 +4448,9 @@ async def get_channel_async( return json.loads(response.text) - async def update_channel_properties_async( + def update_channel_properties( self, - input: UpdateChannelPropertiesInput, + input: UpdateChannelPropertiesInput | Mapping[str, Any], group_id: str, channel_id: str, *, @@ -3791,6 +4466,24 @@ async def update_channel_properties_async( properties you provide are changed; omitted properties are left unchanged. For shared channels, the team ID must refer to the host team, which is the team that owns the shared channel. + + Swagger operation ID: `UpdateChannelProperties`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Select team. + channel_id: Channel ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3801,7 +4494,7 @@ async def update_channel_properties_async( f"/{quote(str(channel_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -3815,11 +4508,12 @@ async def update_channel_properties_async( request_url, response.status, response.text, + response=response, ) - async def archive_channel_async( + def archive_channel( self, - input: ArchiveChannelInput, + input: ArchiveChannelInput | Mapping[str, Any], group_id: str, channel_id: str, *, @@ -3835,6 +4529,24 @@ async def archive_channel_async( send new messages or react to existing messages in the channel, edit the channel settings, or make other changes to the channel. Archiving is an asynchronous operation. + + Swagger operation ID: `ArchiveChannel`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Select team. + channel_id: Channel ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3846,7 +4558,7 @@ async def archive_channel_async( f"/archive" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -3860,6 +4572,7 @@ async def archive_channel_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -3867,22 +4580,45 @@ async def archive_channel_async( return json.loads(response.text) - async def get_all_channels_for_team_async( + def list_all_channels_for_team( self, group_id: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List all channels Lists all the channels for a specific team, including channels that are shared with the team + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAllChannelsForTeam`. + + Args: + group_id: Select team. + filter: An OData filter query to restrict the entries returned + (e.g. membershipType eq 'standard'). + orderby: An OData orderBy query option for specifying the order of + entries (e.g., displayName asc). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3901,29 +4637,50 @@ async def get_all_channels_for_team_async( query_params.append(f"$orderby={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None - - return json.loads(response.text) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url - async def get_chats_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_chats( self, chat_type: str, topic: str, @@ -3932,11 +4689,31 @@ async def get_chats_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List chats Lists recent chats you are a part of + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetChats`. + + Args: + chat_type: Filter by type. + topic: Filter by whether or not the topic name is defined. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3950,31 +4727,52 @@ async def get_chats_async( f"/expandmembers" f"/false" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - async def post_feed_notification_async( + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def post_feed_notification( self, - input: DynamicPostFeedNotificationRequest, + input: DynamicPostFeedNotificationRequest | Mapping[str, Any], poster: str, notification_type: str, *, @@ -3988,6 +4786,24 @@ async def post_feed_notification_async( Posts a notification to a user's activity feed linking to a chat or team. + + Swagger operation ID: `PostFeedNotification`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + poster: Select an option. + notification_type: Choose notification type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -3999,7 +4815,7 @@ async def post_feed_notification_async( f"/{quote(str(notification_type), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4013,9 +4829,10 @@ async def post_feed_notification_async( request_url, response.status, response.text, + response=response, ) - async def at_mention_tag_async( + def at_mention_tag( self, group_id: str, tag_id: str, @@ -4030,6 +4847,22 @@ async def at_mention_tag_async( Creates a token that can be inserted into a message or adaptive card sent as a user in a channel to @mention a team tag. + + Swagger operation ID: `AtMentionTag`. + + Args: + group_id: Select team. + tag_id: Select tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4040,7 +4873,7 @@ async def at_mention_tag_async( f"/{quote(str(tag_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4054,6 +4887,7 @@ async def at_mention_tag_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4061,7 +4895,7 @@ async def at_mention_tag_async( return json.loads(response.text) - async def get_messages_from_channel_async( + def list_messages_from_channel( self, group_id: str, channel_id: str, @@ -4070,7 +4904,7 @@ async def get_messages_from_channel_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get messages in a channel @@ -4078,8 +4912,25 @@ async def get_messages_from_channel_async( the team ID must refer to the host team, which is the team that owns the shared channel. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMessagesFromChannel`. + + Args: + group_id: Select team. + channel_id: Channel ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4090,11 +4941,18 @@ async def get_messages_from_channel_async( f"/{quote(str(channel_id), safe='')}" f"/messages" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -4107,25 +4965,34 @@ async def get_messages_from_channel_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_message_details_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def get_message_details( self, - input: DynamicGetMessageDetailsSchema, + input: DynamicGetMessageDetailsSchema | Mapping[str, Any], message_id: str, thread_type: str, *, @@ -4138,6 +5005,24 @@ async def get_message_details_async( Get message details Gets the details of a message in a chat or a channel. + + Swagger operation ID: `GetMessageDetails`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + message_id: Message ID. + thread_type: Choose message type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4149,7 +5034,7 @@ async def get_message_details_async( f"/{quote(str(thread_type), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4163,6 +5048,7 @@ async def get_message_details_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4170,24 +5056,47 @@ async def get_message_details_async( return json.loads(response.text) - async def list_replies_to_message_async( + def list_replies_to_message( self, group_id: str, channel_id: str, message_id: str, - top: Optional[int] = None, *, + top: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List replies of a channel message List replies to a message in a channel in a specific team. For shared channels, the team ID must refer to the host team, which is the team that owns the shared channel. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListRepliesToMessage`. + + Args: + group_id: Select team. + channel_id: Channel ID. + message_id: Message ID. + top: The number of latest replies to return. The default value is + 20. The supported value is between 1 and 50. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4208,43 +5117,87 @@ async def list_replies_to_message_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def list_members_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_members( self, - input: DynamicListMembersSchema, + input: DynamicListMembersSchema | Mapping[str, Any], thread_type: str, - filter: Optional[str] = None, *, + filter: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List chat or channel members List direct members of a group chat or a channel + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListMembers`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + thread_type: Choose message type. + filter: An OData filter query to restrict the entries returned + (e.g. membershipType eq 'standard'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4262,31 +5215,52 @@ async def list_members_async( query_params.append(f"$filter={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = input + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "POST", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "POST", request_url, body=input, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "POST", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "POST", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def subscribe_user_message_with_options_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def subscribe_user_message_with_options( self, - input: DynamicUserMessageWithOptionsSubscriptionRequest, + input: DynamicUserMessageWithOptionsSubscriptionRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -4299,6 +5273,22 @@ async def subscribe_user_message_with_options_async( Send a set of options to a Microsoft Teams user, that they must respond to before the flow will continue. This action will pause the flow until the user response to the options + + Swagger operation ID: `SubscribeUserMessageWithOptions`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4310,7 +5300,7 @@ async def subscribe_user_message_with_options_async( f"/$subscriptions" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4324,9 +5314,10 @@ async def subscribe_user_message_with_options_async( request_url, response.status, response.text, + response=response, ) - async def get_team_async( + def get_team( self, team_id: str, *, @@ -4339,13 +5330,28 @@ async def get_team_async( Get a team Gets the details for a team in Microsoft Teams. + + Swagger operation ID: `GetTeam`. + + Args: + team_id: Select team. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/beta/teams/{quote(str(team_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4359,6 +5365,7 @@ async def get_team_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4366,7 +5373,7 @@ async def get_team_async( return json.loads(response.text) - async def at_mention_user_async( + def at_mention_user( self, user_id: str, *, @@ -4380,13 +5387,28 @@ async def at_mention_user_async( Creates a token that can be inserted into a message or adaptive card to @mention a user. + + Swagger operation ID: `AtMentionUser`. + + Args: + user_id: Specify a user principal or user ID to @mention. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/users/{quote(str(user_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -4400,6 +5422,7 @@ async def at_mention_user_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4407,9 +5430,9 @@ async def at_mention_user_async( return json.loads(response.text) - async def create_chat_async( + def create_chat( self, - input: NewChat, + input: NewChat | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -4420,10 +5443,26 @@ async def create_chat_async( Create a chat Creates a one on one or group chat + + Swagger operation ID: `CreateChat`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/beta/chats" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4437,6 +5476,7 @@ async def create_chat_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4444,25 +5484,47 @@ async def create_chat_async( return json.loads(response.text) - async def get_messages_from_chat_async( + def list_messages_from_chat( self, chat_id: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, top: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get messages in a chat Retrieves messages from a one on one or group chat - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMessagesFromChat`. + + Args: + chat_id: The chat's unique identifier. + filter: An OData filter query to restrict the entries returned + (e.g. membershipType eq 'standard'). + orderby: An OData orderBy query option for specifying the order of + entries (e.g., displayName asc). + top: An OData top query option for specifying the maximum number of + entries returned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4486,11 +5548,18 @@ async def get_messages_from_chat_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -4503,25 +5572,34 @@ async def get_messages_from_chat_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def post_message_to_self_async( + return ItemPaged(get_next, extract_data) + + def post_message_to_self( self, - input: PostMessageToSelfRequest, + input: PostMessageToSelfRequest | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -4533,12 +5611,28 @@ async def post_message_to_self_async( Sends a message to the signed-in user's own Notes chat in Microsoft Teams. + + Swagger operation ID: `PostMessageToSelf`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1.0/chats/48:notes/messages" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4552,6 +5646,7 @@ async def post_message_to_self_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4559,9 +5654,9 @@ async def post_message_to_self_async( return json.loads(response.text) - async def create_a_team_async( + def create_a_team( self, - input: CreateATeamInput, + input: CreateATeamInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -4572,10 +5667,26 @@ async def create_a_team_async( Create a team Creates a new team in Microsoft Teams + + Swagger operation ID: `CreateATeam`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/beta/teams" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4589,6 +5700,7 @@ async def create_a_team_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4596,21 +5708,44 @@ async def create_a_team_async( return json.loads(response.text) - async def list_team_members_async( + def list_team_members( self, team_id: str, + *, filter: Optional[str] = None, top: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List team members Lists the members of a team in Microsoft Teams + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTeamMembers`. + + Args: + team_id: Select team. + filter: An OData filter query to restrict the entries returned + (e.g. membershipType eq 'standard'). + top: An OData top query option for specifying the maximum number of + entries returned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4629,31 +5764,52 @@ async def list_team_members_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def add_member_to_team_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def add_member_to_team( self, - input: AddMemberToTeamInput, + input: AddMemberToTeamInput | Mapping[str, Any], team_id: str, *, timeout: Optional[float] = None, @@ -4665,13 +5821,30 @@ async def add_member_to_team_async( Add a member to a team Adds a member to a team in Microsoft Teams + + Swagger operation ID: `AddMemberToTeam`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + team_id: Select team. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/teams/{quote(str(team_id), safe='')}/members" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4685,9 +5858,10 @@ async def add_member_to_team_async( request_url, response.status, response.text, + response=response, ) - async def remove_member_from_team_async( + def remove_member_from_team( self, team_id: str, membership_id: str, @@ -4701,6 +5875,24 @@ async def remove_member_from_team_async( Remove a member from a team Removes a member from a team in Microsoft Teams + + Swagger operation ID: `RemoveMemberFromTeam`. + + Args: + team_id: Select team. + membership_id: The membership ID of the member to remove from the + team. Use the 'List team members' action to look up the + membership ID for a user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4711,7 +5903,7 @@ async def remove_member_from_team_async( f"/{quote(str(membership_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -4725,11 +5917,12 @@ async def remove_member_from_team_async( request_url, response.status, response.text, + response=response, ) - async def add_member_to_channel_async( + def add_member_to_channel( self, - input: AddMemberToChannelInput, + input: AddMemberToChannelInput | Mapping[str, Any], group_id: str, channel_id: str, *, @@ -4743,6 +5936,24 @@ async def add_member_to_channel_async( Adds a member to a channel in Microsoft Teams. The channel must be a private or shared channel. + + Swagger operation ID: `AddMemberToChannel`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Select team. + channel_id: Channel ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4754,7 +5965,7 @@ async def add_member_to_channel_async( f"/members" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4768,9 +5979,10 @@ async def add_member_to_channel_async( request_url, response.status, response.text, + response=response, ) - async def remove_member_from_channel_async( + def remove_member_from_channel( self, group_id: str, channel_id: str, @@ -4786,6 +5998,26 @@ async def remove_member_from_channel_async( Removes a direct member from a channel in Microsoft Teams. The channel must be a private or shared channel. + + Swagger operation ID: `RemoveMemberFromChannel`. + + Args: + group_id: Select team. + channel_id: Channel ID. + membership_id: The membership ID of the direct member to remove + from the channel. Use the 'List chat or channel members' action + with thread type 'Channel' to look up the membership ID for a + user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4798,7 +6030,7 @@ async def remove_member_from_channel_async( f"/{quote(str(membership_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -4812,11 +6044,12 @@ async def remove_member_from_channel_async( request_url, response.status, response.text, + response=response, ) - async def post_message_to_conversation_async( + def post_message_to_conversation( self, - input: DynamicPostMessageRequest, + input: DynamicPostMessageRequest | Mapping[str, Any], poster: str, location: str, *, @@ -4829,6 +6062,24 @@ async def post_message_to_conversation_async( Post message in a chat or channel Posts a message to a chat or a channel + + Swagger operation ID: `PostMessageToConversation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + poster: Select an option. + location: Select an option. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4842,7 +6093,7 @@ async def post_message_to_conversation_async( f"/{quote(str(location), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4856,6 +6107,7 @@ async def post_message_to_conversation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4863,9 +6115,9 @@ async def post_message_to_conversation_async( return json.loads(response.text) - async def reply_with_message_to_conversation_async( + def reply_with_message_to_conversation( self, - input: DynamicReplyMessageRequest, + input: DynamicReplyMessageRequest | Mapping[str, Any], poster: str, location: str, *, @@ -4878,6 +6130,24 @@ async def reply_with_message_to_conversation_async( Reply with a message in a channel Replies with a message to a channel's message + + Swagger operation ID: `ReplyWithMessageToConversation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + poster: Select an option. + location: Select an option. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4891,7 +6161,7 @@ async def reply_with_message_to_conversation_async( f"/{quote(str(location), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4905,6 +6175,7 @@ async def reply_with_message_to_conversation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4912,9 +6183,9 @@ async def reply_with_message_to_conversation_async( return json.loads(response.text) - async def post_card_to_conversation_async( + def post_card_to_conversation( self, - input: DynamicPostCardRequest, + input: DynamicPostCardRequest | Mapping[str, Any], poster: str, location: str, *, @@ -4927,6 +6198,24 @@ async def post_card_to_conversation_async( Post card in a chat or channel Posts a card to a chat or a channel + + Swagger operation ID: `PostCardToConversation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + poster: Select an option. + location: Select an option. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4940,7 +6229,7 @@ async def post_card_to_conversation_async( f"/{quote(str(location), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -4954,6 +6243,7 @@ async def post_card_to_conversation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -4961,9 +6251,9 @@ async def post_card_to_conversation_async( return json.loads(response.text) - async def post_card_and_wait_for_response_async( + def post_card_and_wait_for_response( self, - input: PostCardAndWaitForResponseInput, + input: PostCardAndWaitForResponseInput | Mapping[str, Any], poster: str, location: str, *, @@ -4977,6 +6267,24 @@ async def post_card_and_wait_for_response_async( Posts an adaptive card to a chat or a channel and waits for a response from any user. This will pause the flow until any user responds. + + Swagger operation ID: `PostCardAndWaitForResponse`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + poster: Select an option. + location: Select an option. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -4991,7 +6299,7 @@ async def post_card_and_wait_for_response_async( f"/$subscriptions" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5005,6 +6313,7 @@ async def post_card_and_wait_for_response_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5012,9 +6321,9 @@ async def post_card_and_wait_for_response_async( return json.loads(response.text) - async def reply_with_card_to_conversation_async( + def reply_with_card_to_conversation( self, - input: DynamicReplyCardRequest, + input: DynamicReplyCardRequest | Mapping[str, Any], poster: str, location: str, *, @@ -5027,6 +6336,24 @@ async def reply_with_card_to_conversation_async( Reply with an adaptive card in a channel Replies with an adaptive card to a channel's message + + Swagger operation ID: `ReplyWithCardToConversation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + poster: Select an option. + location: Select an option. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5040,7 +6367,7 @@ async def reply_with_card_to_conversation_async( f"/{quote(str(location), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5054,6 +6381,7 @@ async def reply_with_card_to_conversation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5061,9 +6389,9 @@ async def reply_with_card_to_conversation_async( return json.loads(response.text) - async def update_card_in_conversation_async( + def update_card_in_conversation( self, - input: DynamicUpdateCardRequest, + input: DynamicUpdateCardRequest | Mapping[str, Any], poster: str, location: str, *, @@ -5076,6 +6404,24 @@ async def update_card_in_conversation_async( Update an adaptive card in a chat or channel Updates an existing adaptive card + + Swagger operation ID: `UpdateCardInConversation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + poster: Select an option. + location: Select an option. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5089,7 +6435,7 @@ async def update_card_in_conversation_async( f"/{quote(str(location), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5103,6 +6449,7 @@ async def update_card_in_conversation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5110,7 +6457,7 @@ async def update_card_in_conversation_async( return json.loads(response.text) - async def http_request_async( + def http_request( self, input: bytes, *, @@ -5127,10 +6474,25 @@ async def http_request_async( /teams, /me, /users 2nd segment: channels, chats, installedApps, messages, pinnedMessages, onlineMeetings. Learn more: https://docs.microsoft.com/en-us/graph/use-the-api + + Swagger operation ID: `HttpRequest`. + + Args: + input: The binary request body. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/httprequest" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -5147,6 +6509,7 @@ async def http_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5154,9 +6517,9 @@ async def http_request_async( return json.loads(response.text) - async def add_member_to_chat_async( + def add_member_to_chat( self, - input: AddMemberToChatInput, + input: AddMemberToChatInput | Mapping[str, Any], chat_id: str, *, timeout: Optional[float] = None, @@ -5168,13 +6531,30 @@ async def add_member_to_chat_async( Add a user to a chat Adds a user to a chat in Microsoft Teams. + + Swagger operation ID: `AddMemberToChat`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + chat_id: The chat's unique identifier. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/chats/{quote(str(chat_id), safe='')}/members" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5188,9 +6568,10 @@ async def add_member_to_chat_async( request_url, response.status, response.text, + response=response, ) - async def remove_member_from_chat_async( + def remove_member_from_chat( self, chat_id: str, membership_id: str, @@ -5205,6 +6586,24 @@ async def remove_member_from_chat_async( Removes a member from a chat in Microsoft Teams. Only group chats support member removal. + + Swagger operation ID: `RemoveMemberFromChat`. + + Args: + chat_id: The chat's unique identifier. + membership_id: The membership ID of the member to remove from the + chat. Use the 'List chat or channel members' action with thread + type 'Group chat' to look up the membership ID for a user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5215,7 +6614,7 @@ async def remove_member_from_chat_async( f"/{quote(str(membership_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -5229,9 +6628,10 @@ async def remove_member_from_chat_async( request_url, response.status, response.text, + response=response, ) - async def get_online_meeting_async( + def get_online_meeting( self, lookup_type: str, lookup_value: str, @@ -5246,6 +6646,23 @@ async def get_online_meeting_async( Retrieves the properties and relationships of an online meeting. You can look up a meeting by meeting ID, join web URL, or join meeting ID. + + Swagger operation ID: `GetOnlineMeeting`. + + Args: + lookup_type: Select how to identify the meeting. + lookup_value: The value corresponding to the selected lookup type + (meeting ID, join web URL, or join meeting ID). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1.0/me/onlineMeetings/lookup" @@ -5262,7 +6679,7 @@ async def get_online_meeting_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5276,6 +6693,7 @@ async def get_online_meeting_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5283,7 +6701,7 @@ async def get_online_meeting_async( return json.loads(response.text) - async def list_meeting_transcripts_async( + def list_meeting_transcripts( self, meeting_id: str, *, @@ -5291,11 +6709,30 @@ async def list_meeting_transcripts_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List meeting transcripts Lists all transcripts for an online meeting + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListMeetingTranscripts`. + + Args: + meeting_id: The online meeting ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5305,29 +6742,50 @@ async def list_meeting_transcripts_async( f"/{quote(str(meeting_id), safe='')}" f"/transcripts" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - async def get_meeting_transcript_async( + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_meeting_transcript( self, meeting_id: str, transcript_id: str, @@ -5341,6 +6799,22 @@ async def get_meeting_transcript_async( Get meeting transcript Gets a specific transcript for an online meeting + + Swagger operation ID: `GetMeetingTranscript`. + + Args: + meeting_id: The online meeting ID. + transcript_id: The transcript ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5352,7 +6826,7 @@ async def get_meeting_transcript_async( f"/{quote(str(transcript_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5366,6 +6840,7 @@ async def get_meeting_transcript_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5373,7 +6848,7 @@ async def get_meeting_transcript_async( return json.loads(response.text) - async def get_meeting_transcript_content_async( + def get_meeting_transcript_content( self, meeting_id: str, transcript_id: str, @@ -5387,6 +6862,22 @@ async def get_meeting_transcript_content_async( Get meeting transcript content Gets the content of a meeting transcript + + Swagger operation ID: `GetMeetingTranscriptContent`. + + Args: + meeting_id: The online meeting ID. + transcript_id: The transcript ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5399,7 +6890,7 @@ async def get_meeting_transcript_content_async( f"/content" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5413,6 +6904,7 @@ async def get_meeting_transcript_content_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5420,7 +6912,7 @@ async def get_meeting_transcript_content_async( return json.loads(response.text) - async def list_meeting_recordings_async( + def list_meeting_recordings( self, meeting_id: str, *, @@ -5428,11 +6920,30 @@ async def list_meeting_recordings_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List meeting recordings Lists all recordings for an online meeting + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListMeetingRecordings`. + + Args: + meeting_id: The online meeting ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5442,29 +6953,50 @@ async def list_meeting_recordings_async( f"/{quote(str(meeting_id), safe='')}" f"/recordings" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_meeting_recording_async( + def get_meeting_recording( self, meeting_id: str, recording_id: str, @@ -5478,6 +7010,22 @@ async def get_meeting_recording_async( Get meeting recording Gets a specific recording for an online meeting + + Swagger operation ID: `GetMeetingRecording`. + + Args: + meeting_id: The online meeting ID. + recording_id: The recording ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5489,7 +7037,7 @@ async def get_meeting_recording_async( f"/{quote(str(recording_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5503,6 +7051,7 @@ async def get_meeting_recording_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5510,7 +7059,7 @@ async def get_meeting_recording_async( return json.loads(response.text) - async def get_meeting_recording_content_async( + def get_meeting_recording_content( self, meeting_id: str, recording_id: str, @@ -5524,6 +7073,22 @@ async def get_meeting_recording_content_async( Get meeting recording content Gets the content stream of a meeting recording + + Swagger operation ID: `GetMeetingRecordingContent`. + + Args: + meeting_id: The online meeting ID. + recording_id: The recording ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5536,7 +7101,7 @@ async def get_meeting_recording_content_async( f"/content" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5550,52 +7115,94 @@ async def get_meeting_recording_content_async( request_url, response.status, response.text, + response=response, ) return response.content - async def list_sections_async( + def list_sections( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List sections Lists the current user's teamwork sections + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListSections`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/beta/me/teamwork/sections" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def create_section_async( + return ItemPaged(get_next, extract_data) + + def create_section( self, - input: CreateSectionInput, + input: CreateSectionInput | Mapping[str, Any], *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5605,12 +7212,37 @@ async def create_section_async( Create a section Creates a new teamwork section for the current user + + Swagger operation ID: `CreateSection`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + request_url = ( f"{self._connection_runtime_url}/beta/me/teamwork/sections" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5624,6 +7256,7 @@ async def create_section_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5631,7 +7264,7 @@ async def create_section_async( return json.loads(response.text) - async def get_section_async( + def get_section( self, section_id: str, *, @@ -5644,13 +7277,28 @@ async def get_section_async( Get a section Gets a specific teamwork section by ID + + Swagger operation ID: `GetSection`. + + Args: + section_id: The section ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/beta/me/teamwork/sections/{quote(str(section_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -5664,6 +7312,7 @@ async def get_section_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5671,11 +7320,13 @@ async def get_section_async( return json.loads(response.text) - async def update_section_async( + def update_section( self, - input: UpdateSectionInput, + input: UpdateSectionInput | Mapping[str, Any], section_id: str, *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5685,13 +7336,39 @@ async def update_section_async( Update a section Updates a teamwork section for the current user + + Swagger operation ID: `UpdateSection`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + section_id: The section ID. + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + request_url = ( f"{self._connection_runtime_url}" f"/beta/me/teamwork/sections/{quote(str(section_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -5705,6 +7382,7 @@ async def update_section_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5712,10 +7390,12 @@ async def update_section_async( return json.loads(response.text) - async def delete_section_async( + def delete_section( self, section_id: str, *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5725,13 +7405,37 @@ async def delete_section_async( Delete a section Deletes a teamwork section for the current user + + Swagger operation ID: `DeleteSection`. + + Args: + section_id: The section ID. + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + request_url = ( f"{self._connection_runtime_url}" f"/beta/me/teamwork/sections/{quote(str(section_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -5745,9 +7449,10 @@ async def delete_section_async( request_url, response.status, response.text, + response=response, ) - async def list_section_items_async( + def list_section_items( self, section_id: str, *, @@ -5755,12 +7460,31 @@ async def list_section_items_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List section items Lists the items (chats, channels, meetings, communities) in a teamwork section. Each item belongs to exactly one section at a time. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListSectionItems`. + + Args: + section_id: The section ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -5771,33 +7495,56 @@ async def list_section_items_async( f"/{quote(str(section_id), safe='')}" f"/items" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def add_section_item_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def add_section_item( self, - input: AddSectionItemInput, + input: AddSectionItemInput | Mapping[str, Any], section_id: str, *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5809,7 +7556,33 @@ async def add_section_item_async( Adds an item (chat, channel, meeting, or community) currently in a system-defined section to a user-defined teamwork section. Use Move Section Item to relocate items already in another user-defined section. + + Swagger operation ID: `AddSectionItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + section_id: The section ID. + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + request_url = ( f"{self._connection_runtime_url}" f"/beta" @@ -5820,7 +7593,7 @@ async def add_section_item_async( f"/items" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5834,6 +7607,7 @@ async def add_section_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5841,11 +7615,13 @@ async def add_section_item_async( return json.loads(response.text) - async def remove_section_item_async( + def remove_section_item( self, section_id: str, section_item_id: str, *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5857,7 +7633,33 @@ async def remove_section_item_async( Removes an item from a user-defined teamwork section. The underlying chat, channel, meeting, or community is not deleted; the item returns to its default system-defined section. + + Swagger operation ID: `RemoveSectionItem`. + + Args: + section_id: The section ID. + section_item_id: The section item ID (the conversation ID of the + underlying chat, channel, meeting, or community). + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + request_url = ( f"{self._connection_runtime_url}" f"/beta" @@ -5869,7 +7671,7 @@ async def remove_section_item_async( f"/{quote(str(section_item_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -5883,14 +7685,17 @@ async def remove_section_item_async( request_url, response.status, response.text, + response=response, ) - async def move_section_item_async( + def move_section_item( self, - input: MoveSectionItemInput, + input: MoveSectionItemInput | Mapping[str, Any], section_id: str, section_item_id: str, *, + etag: Optional[str] = None, + match_condition: Optional[MatchConditions] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -5903,7 +7708,35 @@ async def move_section_item_async( another user-defined section. Each item can belong to only one section at a time. This action removes the item from its current section and adds it to the target section. - """ + + Swagger operation ID: `MoveSectionItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + section_id: The section ID. + section_item_id: The section item ID (the conversation ID of the + underlying chat, channel, meeting, or community). + etag: The entity tag for the conditional request. + match_condition: The Azure Core match condition. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. + """ + headers = self._prepare_match_headers( + headers, + etag, + match_condition, + if_match_required=True, + ) + request_url = ( f"{self._connection_runtime_url}" f"/beta" @@ -5916,7 +7749,7 @@ async def move_section_item_async( f"/move" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -5930,6 +7763,7 @@ async def move_section_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -5937,7 +7771,7 @@ async def move_section_item_async( return json.loads(response.text) - async def get_tags_async( + def list_tags( self, group_id: str, *, @@ -5945,41 +7779,81 @@ async def get_tags_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List all tags for a team Lists the team's tags + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTags`. + + Args: + group_id: Select team. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/teams/{quote(str(group_id), safe='')}/tags" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - async def create_tag_async( + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def create_tag( self, - input: CreateTagInput, + input: CreateTagInput | Mapping[str, Any], group_id: str, *, timeout: Optional[float] = None, @@ -5991,13 +7865,30 @@ async def create_tag_async( Create a tag for a team Creates a tag in a team + + Swagger operation ID: `CreateTag`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Select team. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/teams/{quote(str(group_id), safe='')}/tags" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6011,6 +7902,7 @@ async def create_tag_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6018,7 +7910,7 @@ async def create_tag_async( return json.loads(response.text) - async def get_tag_async( + def get_tag( self, group_id: str, tag_id: str, @@ -6032,6 +7924,22 @@ async def get_tag_async( Get a team tag Gets a specific tag by ID from a team + + Swagger operation ID: `GetTag`. + + Args: + group_id: Select team. + tag_id: Select tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6042,7 +7950,7 @@ async def get_tag_async( f"/{quote(str(tag_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6056,6 +7964,7 @@ async def get_tag_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6063,9 +7972,9 @@ async def get_tag_async( return json.loads(response.text) - async def update_tag_async( + def update_tag( self, - input: UpdateTagInput, + input: UpdateTagInput | Mapping[str, Any], group_id: str, tag_id: str, *, @@ -6078,6 +7987,24 @@ async def update_tag_async( Update a team tag Updates the display name of a tag in a team + + Swagger operation ID: `UpdateTag`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Select team. + tag_id: Select tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6088,7 +8015,7 @@ async def update_tag_async( f"/{quote(str(tag_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -6102,6 +8029,7 @@ async def update_tag_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6109,7 +8037,7 @@ async def update_tag_async( return json.loads(response.text) - async def delete_tag_async( + def delete_tag( self, group_id: str, tag_id: str, @@ -6123,6 +8051,22 @@ async def delete_tag_async( Delete a team tag Deletes a tag from a team + + Swagger operation ID: `DeleteTag`. + + Args: + group_id: Select team. + tag_id: Select tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6133,7 +8077,7 @@ async def delete_tag_async( f"/{quote(str(tag_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -6147,11 +8091,12 @@ async def delete_tag_async( request_url, response.status, response.text, + response=response, ) - async def add_member_to_tag_async( + def add_member_to_tag( self, - input: AddMemberToTagInput, + input: AddMemberToTagInput | Mapping[str, Any], group_id: str, tag_id: str, *, @@ -6164,6 +8109,24 @@ async def add_member_to_tag_async( Add a member to a team tag Adds a user to a team tag + + Swagger operation ID: `AddMemberToTag`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + group_id: Select team. + tag_id: Select tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6175,7 +8138,7 @@ async def add_member_to_tag_async( f"/members" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -6189,6 +8152,7 @@ async def add_member_to_tag_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6196,7 +8160,7 @@ async def add_member_to_tag_async( return json.loads(response.text) - async def get_tag_members_async( + def list_tag_members( self, group_id: str, tag_id: str, @@ -6205,11 +8169,31 @@ async def get_tag_members_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List the members of a team tag Lists the members of a team tag + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTagMembers`. + + Args: + group_id: Select team. + tag_id: Select tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6220,29 +8204,50 @@ async def get_tag_members_async( f"/{quote(str(tag_id), safe='')}" f"/members" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def delete_tag_member_async( + def delete_tag_member( self, group_id: str, tag_id: str, @@ -6257,6 +8262,23 @@ async def delete_tag_member_async( Delete a member from a team tag Deletes a member from a team tag + + Swagger operation ID: `DeleteTagMember`. + + Args: + group_id: Select team. + tag_id: Select tag. + tag_member_id: ID of the member to remove from the tag. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6269,7 +8291,7 @@ async def delete_tag_member_async( f"/{quote(str(tag_member_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -6283,9 +8305,10 @@ async def delete_tag_member_async( request_url, response.status, response.text, + response=response, ) - async def list_call_recordings_async( + def list_call_recordings( self, call_id: str, *, @@ -6293,39 +8316,79 @@ async def list_call_recordings_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List call recordings Lists all recordings for an ad-hoc call + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListCallRecordings`. + + Args: + call_id: The call ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/me/adhocCalls/{quote(str(call_id), safe='')}/recordings" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - async def get_call_recording_async( + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_call_recording( self, call_id: str, recording_id: str, @@ -6339,6 +8402,22 @@ async def get_call_recording_async( Get call recording Gets a specific recording for an ad-hoc call + + Swagger operation ID: `GetCallRecording`. + + Args: + call_id: The call ID. + recording_id: The recording ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6350,7 +8429,7 @@ async def get_call_recording_async( f"/{quote(str(recording_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6364,6 +8443,7 @@ async def get_call_recording_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6371,7 +8451,7 @@ async def get_call_recording_async( return json.loads(response.text) - async def get_call_recording_content_async( + def get_call_recording_content( self, call_id: str, recording_id: str, @@ -6385,6 +8465,22 @@ async def get_call_recording_content_async( Get call recording content Gets the content of a call recording + + Swagger operation ID: `GetCallRecordingContent`. + + Args: + call_id: The call ID. + recording_id: The recording ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6397,7 +8493,7 @@ async def get_call_recording_content_async( f"/content" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6411,11 +8507,12 @@ async def get_call_recording_content_async( request_url, response.status, response.text, + response=response, ) return response.content - async def list_call_transcripts_async( + def list_call_transcripts( self, call_id: str, *, @@ -6423,39 +8520,79 @@ async def list_call_transcripts_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List call transcripts Lists all transcripts for an ad-hoc call + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListCallTranscripts`. + + Args: + call_id: The call ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1.0/me/adhocCalls/{quote(str(call_id), safe='')}/transcripts" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def get_call_transcript_async( + return ItemPaged(get_next, extract_data) + + def get_call_transcript( self, call_id: str, transcript_id: str, @@ -6469,6 +8606,22 @@ async def get_call_transcript_async( Get call transcript Gets a specific transcript for an ad-hoc call + + Swagger operation ID: `GetCallTranscript`. + + Args: + call_id: The call ID. + transcript_id: The transcript ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6480,7 +8633,7 @@ async def get_call_transcript_async( f"/{quote(str(transcript_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6494,6 +8647,7 @@ async def get_call_transcript_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6501,7 +8655,7 @@ async def get_call_transcript_async( return json.loads(response.text) - async def get_call_transcript_content_async( + def get_call_transcript_content( self, call_id: str, transcript_id: str, @@ -6515,6 +8669,22 @@ async def get_call_transcript_content_async( Get call transcript content Gets the content of a call transcript + + Swagger operation ID: `GetCallTranscriptContent`. + + Args: + call_id: The call ID. + transcript_id: The transcript ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6527,7 +8697,7 @@ async def get_call_transcript_content_async( f"/content" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6541,6 +8711,7 @@ async def get_call_transcript_content_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6548,23 +8719,46 @@ async def get_call_transcript_content_async( return json.loads(response.text) - async def get_all_adhoc_call_recordings_async( + def list_all_adhoc_call_recordings( self, + *, start_date_time: Optional[str] = None, end_date_time: Optional[str] = None, top: Optional[int] = None, skiptoken: Optional[str] = None, deltatoken: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get all ad-hoc call recordings Gets all recordings from ad-hoc calls for the signed-in user + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAllAdhocCallRecordings`. + + Args: + start_date_time: The start date and time to filter recordings. + end_date_time: The end date and time to filter recordings. + top: The number of recordings to return. + skiptoken: The skip token for pagination. + deltatoken: The delta token for tracking changes. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6598,45 +8792,89 @@ async def get_all_adhoc_call_recordings_async( query_params.append(f"$deltatoken={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_all_adhoc_call_transcripts_async( + def list_all_adhoc_call_transcripts( self, + *, start_date_time: Optional[str] = None, end_date_time: Optional[str] = None, top: Optional[int] = None, skiptoken: Optional[str] = None, deltatoken: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get all ad-hoc call transcripts Gets all transcripts from ad-hoc calls for the signed-in user + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAllAdhocCallTranscripts`. + + Args: + start_date_time: The start date and time to filter transcripts. + end_date_time: The end date and time to filter transcripts. + top: The number of transcripts to return. + skiptoken: The skip token for pagination. + deltatoken: The delta token for tracking changes. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6670,29 +8908,50 @@ async def get_all_adhoc_call_transcripts_async( query_params.append(f"$deltatoken={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def list_ai_insights_async( + return ItemPaged(get_next, extract_data) + + def list_ai_insights( self, meeting_id: str, *, @@ -6700,12 +8959,31 @@ async def list_ai_insights_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List AI insights Lists AI-generated insights for an online meeting. Requires Microsoft 365 Copilot license. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListAiInsights`. + + Args: + meeting_id: The online meeting ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6716,29 +8994,50 @@ async def list_ai_insights_async( f"/{quote(str(meeting_id), safe='')}" f"/aiInsights" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def get_ai_insight_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_ai_insight( self, meeting_id: str, ai_insight_id: str, @@ -6753,6 +9052,22 @@ async def get_ai_insight_async( Gets a specific AI-generated insight for an online meeting. Requires Microsoft 365 Copilot license. + + Swagger operation ID: `GetAiInsight`. + + Args: + meeting_id: The online meeting ID. + ai_insight_id: The AI insight ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6765,7 +9080,7 @@ async def get_ai_insight_async( f"/{quote(str(ai_insight_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6779,6 +9094,7 @@ async def get_ai_insight_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6786,7 +9102,7 @@ async def get_ai_insight_async( return json.loads(response.text) - async def get_message_locations_async( + def list_message_locations( self, message_type: str, poster: str, @@ -6795,12 +9111,32 @@ async def get_message_locations_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Conversation location for where to post Returns a list of locations to post a message or reply based on who the user is posting as + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMessageLocations`. + + Args: + message_type: Message Type. + poster: Select an option. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6810,29 +9146,50 @@ async def get_message_locations_async( f"/poster" f"/{quote(str(poster), safe='')}" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("locations", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_message_details_input_schema_async( + def get_message_details_input_schema( self, thread_type: str, *, @@ -6845,6 +9202,21 @@ async def get_message_details_input_schema_async( Get message details response schema Get the schema information for get message details response + + Swagger operation ID: `GetMessageDetailsInputSchema`. + + Args: + thread_type: Choose message type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6854,7 +9226,7 @@ async def get_message_details_input_schema_async( f"/{quote(str(thread_type), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6868,6 +9240,7 @@ async def get_message_details_input_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6875,7 +9248,7 @@ async def get_message_details_input_schema_async( return json.loads(response.text) - async def get_message_details_response_schema_async( + def get_message_details_response_schema( self, thread_type: str, *, @@ -6888,6 +9261,21 @@ async def get_message_details_response_schema_async( Get message details input metadata Get the schema information for message inputs + + Swagger operation ID: `GetMessageDetailsResponseSchema`. + + Args: + thread_type: Choose message type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6897,7 +9285,7 @@ async def get_message_details_response_schema_async( f"/{quote(str(thread_type), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6911,6 +9299,7 @@ async def get_message_details_response_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6918,7 +9307,7 @@ async def get_message_details_response_schema_async( return json.loads(response.text) - async def list_members_input_schema_async( + def list_members_input_schema( self, thread_type: str, *, @@ -6931,6 +9320,21 @@ async def list_members_input_schema_async( List members input schema Get the schema information for list members input based on thread type + + Swagger operation ID: `ListMembersInputSchema`. + + Args: + thread_type: Choose message type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6940,7 +9344,7 @@ async def list_members_input_schema_async( f"/{quote(str(thread_type), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -6954,6 +9358,7 @@ async def list_members_input_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -6961,7 +9366,7 @@ async def list_members_input_schema_async( return json.loads(response.text) - async def get_feed_notification_input_schema_async( + def get_feed_notification_input_schema( self, poster: str, notification_type: str, @@ -6975,6 +9380,22 @@ async def get_feed_notification_input_schema_async( Get feed notification input metadata Get the schema information for feed notification + + Swagger operation ID: `GetFeedNotificationInputSchema`. + + Args: + poster: Select an option. + notification_type: Choose notification type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -6986,7 +9407,7 @@ async def get_feed_notification_input_schema_async( f"/{quote(str(notification_type), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7000,6 +9421,7 @@ async def get_feed_notification_input_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7007,7 +9429,7 @@ async def get_feed_notification_input_schema_async( return json.loads(response.text) - async def get_unified_action_schema_async( + def get_unified_action_schema( self, action_type: str, poster: str, @@ -7022,6 +9444,23 @@ async def get_unified_action_schema_async( Get unified action input metadata Get the schema information for unified actions + + Swagger operation ID: `GetUnifiedActionSchema`. + + Args: + action_type: Unified Action. + poster: Select an option. + recipient_type: Type of the recipient of the action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7035,7 +9474,7 @@ async def get_unified_action_schema_async( f"/schema" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7049,6 +9488,7 @@ async def get_unified_action_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7056,7 +9496,7 @@ async def get_unified_action_schema_async( return json.loads(response.text) - async def get_message_with_options_subscription_input_metadata_async( + def get_message_with_options_subscription_input_metadata( self, recipient_type: str, *, @@ -7070,6 +9510,21 @@ async def get_message_with_options_subscription_input_metadata_async( Get the schema information for the message with options subscription inputs + + Swagger operation ID: `GetMessageWithOptionsSubscriptionInputMetadata`. + + Args: + recipient_type: Type of the recipient of the action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7082,7 +9537,7 @@ async def get_message_with_options_subscription_input_metadata_async( f"/subscriptioninputs" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7096,6 +9551,7 @@ async def get_message_with_options_subscription_input_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7103,7 +9559,7 @@ async def get_message_with_options_subscription_input_metadata_async( return json.loads(response.text) - async def get_message_with_options_subscription_output_metadata_async( + def get_message_with_options_subscription_output_metadata( self, recipient_type: str, *, @@ -7117,6 +9573,22 @@ async def get_message_with_options_subscription_output_metadata_async( Get the schema information for the message with options subscription outputs + + Swagger operation ID: + `GetMessageWithOptionsSubscriptionOutputMetadata`. + + Args: + recipient_type: Type of the recipient of the action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7129,7 +9601,7 @@ async def get_message_with_options_subscription_output_metadata_async( f"/subscriptionoutputs" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7143,6 +9615,7 @@ async def get_message_with_options_subscription_output_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7150,7 +9623,7 @@ async def get_message_with_options_subscription_output_metadata_async( return json.loads(response.text) - async def get_webhook_trigger_request_schema_async( + def get_webhook_trigger_request_schema( self, thread_type: str, *, @@ -7163,6 +9636,21 @@ async def get_webhook_trigger_request_schema_async( Input schema for webhook trigger Gets the input schema for webhook trigger + + Swagger operation ID: `GetWebhookTriggerRequestSchema`. + + Args: + thread_type: Choose message type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7173,7 +9661,7 @@ async def get_webhook_trigger_request_schema_async( f"/{quote(str(thread_type), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7187,6 +9675,7 @@ async def get_webhook_trigger_request_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7194,7 +9683,7 @@ async def get_webhook_trigger_request_schema_async( return json.loads(response.text) - async def get_webhook_trigger_response_schema_async( + def get_webhook_trigger_response_schema( self, trigger_type: str, thread_type: str, @@ -7208,6 +9697,22 @@ async def get_webhook_trigger_response_schema_async( Response schema for webhook trigger Gets the response schema for webhook trigger + + Swagger operation ID: `GetWebhookTriggerResponseSchema`. + + Args: + trigger_type: Trigger type. + thread_type: Choose message type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7220,7 +9725,7 @@ async def get_webhook_trigger_response_schema_async( f"/{quote(str(thread_type), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7234,6 +9739,7 @@ async def get_webhook_trigger_response_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7241,7 +9747,7 @@ async def get_webhook_trigger_response_schema_async( return json.loads(response.text) - async def get_post_to_conversation_response_schema_async( + def get_post_to_conversation_response_schema( self, action_type: str, poster: str, @@ -7256,6 +9762,23 @@ async def get_post_to_conversation_response_schema_async( Get response schema Get the schema information for unified action responses + + Swagger operation ID: `GetPostToConversationResponseSchema`. + + Args: + action_type: Unified Action. + poster: Select an option. + recipient_type: Type of the recipient of the action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7270,7 +9793,7 @@ async def get_post_to_conversation_response_schema_async( f"/schema" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7284,6 +9807,7 @@ async def get_post_to_conversation_response_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7291,7 +9815,7 @@ async def get_post_to_conversation_response_schema_async( return json.loads(response.text) - async def get_flow_continuation_subscription_with_poster_output_metadata_async( + def get_flow_continuation_subscription_with_poster_output_metadata( self, input: GetFlowContinuationSubscriptionWithPosterOutputMetadataInput, poster: str, @@ -7307,6 +9831,24 @@ async def get_flow_continuation_subscription_with_poster_output_metadata_async( Get the schema information for the flow continuation subscription outputs + + Swagger operation ID: + `GetFlowContinuationSubscriptionWithPosterOutputMetadata`. + + Args: + input: The request body. + poster: Select an option. + recipient_type: Type of the recipient of the action. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7321,7 +9863,7 @@ async def get_flow_continuation_subscription_with_poster_output_metadata_async( f"/subscriptionoutputs" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -7335,6 +9877,7 @@ async def get_flow_continuation_subscription_with_poster_output_metadata_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -7342,7 +9885,7 @@ async def get_flow_continuation_subscription_with_poster_output_metadata_async( return json.loads(response.text) - async def get_subscription_scope_schema_async( + def get_subscription_scope_schema( self, scope_type: str, *, @@ -7356,6 +9899,21 @@ async def get_subscription_scope_schema_async( Returns the input schema for a subscription trigger based on the selected scope type. + + Swagger operation ID: `GetSubscriptionScopeSchema`. + + Args: + scope_type: The selected scope type. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -7366,7 +9924,7 @@ async def get_subscription_scope_schema_async( f"/schema" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -7380,6 +9938,7 @@ async def get_subscription_scope_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/textrequest.py b/src/azure/connectors/textrequest.py index 37911af..350788f 100644 --- a/src/azure/connectors/textrequest.py +++ b/src/azure/connectors/textrequest.py @@ -5,21 +5,58 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "TextrequestClient", + "BulkUpdateContactsInput", + "CancelPaymentResponse", + "CreateContactInput", + "CreateContactResponse", + "CreateDashboardInput", + "CreateDashboardResponse", + "CreateGroupInput", + "CreateGroupResponse", + "CreatePaymentInput", + "CreatePaymentResponse", + "GetContactByPhoneNumberResponse", + "GetContactsResponse", + "GetConversationsResponse", + "GetDashboardResponse", + "GetDashboardsResponse", + "GetGroupByIdResponse", + "GetGroupsResponse", + "GetMessagesByContactPhoneResponse", + "GetPaymentResponse", + "GetPaymentsResponse", + "GetTagsResponse", + "MarkPaymentPaidResponse", + "SendMessageByPhoneNumberInput", + "SendMessageByPhoneNumberResponse", + "SendPaymentReminderResponse", + "TextingWebhookInput", + "TextingWebhookResponse", + "UpdateDashboardsNameInput", + "UpdateDashboardsNameResponse", + "UpdateGroupInput", + "UpdateGroupResponse", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,12 +66,12 @@ class GetMessagesByContactPhoneResponse: Response for Get a conversation's messages by a contact's phone number """ - meta: Optional[Dict[str, Any]] = None + meta: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """ Metadata about the data returned by this request. This data is returned by all bulk GET requests. """ - items: Optional[List[Dict[str, Any]]] = None + items: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of message entities gotten from Text Request.""" @@ -44,26 +81,26 @@ class SendMessageByPhoneNumberInput: Send a message to the contact with the given phone number """ - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """Content of the message to send.""" - sender_name: Optional[str] = None + sender_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ The name of the message sender. This is shown in the TextRequest web app and api when retrieving this message. """ - status_callback: Optional[str] = None + status_callback: Optional[str] = dataclass_field(default=None, kw_only=True) """ Url for the web app to hit with a POST command whenever this message's status goes from undelivered to sent (or error). """ - location_callback: Optional[str] = None + location_callback: Optional[str] = dataclass_field(default=None, kw_only=True) """ Location callback url to hit with a POST command when the user accesses and approves sharing their location with the sender. To include the link, add [Location Request] to the message body. This callback is not required for location requests, but it can be useful for APIs. """ - mms_media: Optional[List[str]] = None + mms_media: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ Array of MMS Media attachments for this message. Attachments must be urls gotten from the post /mms endpoint (not included in this connector). @@ -77,32 +114,32 @@ class SendMessageByPhoneNumberResponse: Response for Send a message to the contact with the given phone number """ - message_id: Optional[str] = None + message_id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id of the message. This value is unique for each message.""" - body: Optional[str] = None + body: Optional[str] = dataclass_field(default=None, kw_only=True) """Content of this message.""" - message_direction: Optional[str] = None + message_direction: Optional[str] = dataclass_field(default=None, kw_only=True) """ Singular character, either R or S, denoting whether this message was received from the contact or sent to them, respectively. """ - response_by_username: Optional[str] = None + response_by_username: Optional[str] = dataclass_field(default=None, kw_only=True) """ Username of the Text Request user that last sent a message to this user. """ - message_timestamp_utc: Optional[str] = None + message_timestamp_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of when the message was sent or received by Text Request.""" - delivery_status: Optional[str] = None + delivery_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Current status of this message. This can be 'sending', 'delivered', 'error', or 'send'. """ - delivery_error: Optional[str] = None + delivery_error: Optional[str] = dataclass_field(default=None, kw_only=True) """ Error that caused this message to not be delivered. If the delivery_status is not 'error', this value will be null. """ - mms_media: Optional[List[str]] = None + mms_media: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ List of urls pointing to this message's attachments. All urls will be text-request generated urls. @@ -115,75 +152,80 @@ class GetContactByPhoneNumberResponse: Response for Gets the contact with the specified phone number """ - phone_number: Optional[str] = None + phone_number: Optional[str] = dataclass_field(default=None, kw_only=True) """Phone number of this contact.""" - first_name: Optional[str] = None + first_name: Optional[str] = dataclass_field(default=None, kw_only=True) """First name of this contact.""" - last_name: Optional[str] = None + last_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Last name of this contact.""" - display_name: Optional[str] = None + display_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Full name of this contact. This is the default name displayed in the web app when viewing contacts. """ - is_suppressed: Optional[bool] = None + is_suppressed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether the conversation with this contact are suppressed, and therefore not pushed to the top of the message queue when received. """ - is_archived: Optional[bool] = None + is_archived: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether the conversation with this contact are archived, and therefore cannot be seen when querying conversations (by default). """ - is_blocked: Optional[bool] = None + is_blocked: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether the conversation with this contact are blocked, and therefore not received or stored. """ - suppressed_reason: Optional[str] = None + suppressed_reason: Optional[str] = dataclass_field(default=None, kw_only=True) """ Phrase describing the reason for suppressing contact. If is_suppressed is false, this will be null. """ - note: Optional[str] = None + note: Optional[str] = dataclass_field(default=None, kw_only=True) """ Short phrase describing contact. Used for convenience. This is never shown to the contact. """ - groups: Optional[List[int]] = None + groups: Optional[List[int]] = dataclass_field(default=None, kw_only=True) """Array of integer ids referring to groups this contact belongs to.""" - contact_tags: Optional[List[str]] = None + contact_tags: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Array of guids referring to tags attached to this contact.""" - custom_fields: Optional[List[Dict[str, Any]]] = None + custom_fields: Optional[ + List[Dict[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Array of custom field ids and values defined for this contact.""" - is_resolved: Optional[bool] = None + is_resolved: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether the conversation with this contact is resolved. Any new texts received by this contact will set this false. """ - first_contact_utc: Optional[str] = None + first_contact_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of when the first message was sent to this contact.""" - opted_out_utc: Optional[str] = None + opted_out_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of when this contact opted out to receiving messages.""" - last_msg_sent_utc: Optional[str] = None + last_msg_sent_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of when the last message was sent to this contact.""" - last_msg_received_utc: Optional[str] = None + last_msg_received_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of when the last message was received from this contact.""" - total_msgs_sent: Optional[int] = None + total_msgs_sent: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of total messages sent to this contact.""" - total_msgs_received: Optional[int] = None + total_msgs_received: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of total messages received from this contact.""" - response_count: Optional[int] = None + response_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The total number of response messages from the contact.""" - date_created_utc: Optional[str] = None + date_created_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """The timestamp of when ths contact was created.""" - last_contact_date_utc: Optional[str] = None + last_contact_date_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """ The timestamp of when the last message was sent or received from this contact. """ - last_message: Optional[Dict[str, Any]] = None + last_message: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Last message sent to or from this contact.""" @@ -193,44 +235,49 @@ class CreateContactInput: Create or update a contact """ - first_name: Optional[str] = None + first_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The new first name of the contact.""" - last_name: Optional[str] = None + last_name: Optional[str] = dataclass_field(default=None, kw_only=True) """The new last name of the contact.""" - display_name: Optional[str] = None + display_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ The new full name of the contact. This is the default name displayed in the web app when viewing contacts. """ - is_suppressed: Optional[bool] = None + is_suppressed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Determines whether conversations with this contact are suppressed, and therefore not pushed to the top of the message queue when received. """ - is_archived: Optional[bool] = None + is_archived: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Determines whether conversations with this contact are archived, and therefore cannot be seen when querying conversations (by default). """ - is_blocked: Optional[bool] = None + is_blocked: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Determines whether conversations with this contact are blocked, and therefore not received or stored. """ - suppressed_reason: Optional[str] = None + suppressed_reason: Optional[str] = dataclass_field(default=None, kw_only=True) """Phrase describing the reason for suppressing contact.""" - note: Optional[str] = None + note: Optional[str] = dataclass_field(default=None, kw_only=True) """ Short phrase describing contact. Used for convenience. This is never shown to the contact. """ - groups: Optional[List[int]] = None + groups: Optional[List[int]] = dataclass_field(default=None, kw_only=True) """Array of integer ids referring to groups this contact will belong to.""" - contact_tags: Optional[List[str]] = None + contact_tags: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Array of guids referring to tags attached to this contact.""" - custom_fields: Optional[List[Dict[str, Any]]] = None + custom_fields: Optional[ + List[Dict[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Array of custom field ids and values defined for this contact.""" - is_resolved: Optional[bool] = None + is_resolved: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Determines whether the current conversation with this contact is resolved. Any new texts received by this contact will set this false. @@ -243,74 +290,79 @@ class CreateContactResponse: Response for Create or update a contact """ - phone_number: Optional[str] = None + phone_number: Optional[str] = dataclass_field(default=None, kw_only=True) """Phone number of this contact.""" - first_name: Optional[str] = None + first_name: Optional[str] = dataclass_field(default=None, kw_only=True) """First name of this contact.""" - last_name: Optional[str] = None + last_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Last name of this contact.""" - display_name: Optional[str] = None + display_name: Optional[str] = dataclass_field(default=None, kw_only=True) """ Full name of this contact. This is the default name displayed in the web app when viewing contacts. """ - is_suppressed: Optional[bool] = None + is_suppressed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether the conversation with this contact are suppressed, and therefore not pushed to the top of the message queue when received. """ - is_archived: Optional[bool] = None + is_archived: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether the conversation with this contact are archived, and therefore cannot be seen when querying conversations (by default). """ - is_blocked: Optional[bool] = None + is_blocked: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether the conversation with this contact are blocked, and therefore not received or stored. """ - suppressed_reason: Optional[str] = None + suppressed_reason: Optional[str] = dataclass_field(default=None, kw_only=True) """ Phrase describing the reason for suppressing contact. If is_suppressed is false, this will be null. """ - note: Optional[str] = None + note: Optional[str] = dataclass_field(default=None, kw_only=True) """ Short phrase describing contact. Used for convenience. This is never shown to the contact. """ - groups: Optional[List[int]] = None + groups: Optional[List[int]] = dataclass_field(default=None, kw_only=True) """Array of integer ids referring to groups this contact belongs to.""" - contact_tags: Optional[List[str]] = None + contact_tags: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Array of guids referring to tags attached to this contact.""" - custom_fields: Optional[List[Dict[str, Any]]] = None + custom_fields: Optional[ + List[Dict[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Array of custom field ids and values defined for this contact.""" - is_resolved: Optional[bool] = None + is_resolved: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether the conversation with this contact is resolved. Any new texts received by this contact will set this false. """ - first_contact_utc: Optional[str] = None + first_contact_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of when the first message was sent to this contact.""" - opted_out_utc: Optional[str] = None + opted_out_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of when this contact opted out to receiving messages.""" - last_msg_sent_utc: Optional[str] = None + last_msg_sent_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of when the last message was sent to this contact.""" - last_msg_received_utc: Optional[str] = None + last_msg_received_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of when the last message was received from this contact.""" - total_msgs_sent: Optional[int] = None + total_msgs_sent: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of total messages sent to this contact.""" - total_msgs_received: Optional[int] = None + total_msgs_received: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of total messages received from this contact.""" - response_count: Optional[int] = None + response_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Total number of response messages from the contact.""" - date_created_utc: Optional[str] = None + date_created_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of when ths contact was created.""" - last_contact_date_utc: Optional[str] = None + last_contact_date_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """ Timestamp of when the last message was sent or received from this contact. """ - last_message: Optional[Dict[str, Any]] = None + last_message: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Last message sent to or from this contact.""" @@ -320,12 +372,12 @@ class GetContactsResponse: Response for Get all contacts that match the specified filtering criterion """ - meta: Optional[Dict[str, Any]] = None + meta: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """ Metadata about the data returned by this request. This data is returned by all bulk GET requests. """ - items: Optional[List[Dict[str, Any]]] = None + items: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of contact entities gotten from Text Request.""" @@ -338,20 +390,20 @@ class GetGroupByIdResponse: Response for Get a group by its id """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numerical id of the group.""" - group_member_count: Optional[int] = None + group_member_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of members of the group.""" - is_keyword: Optional[bool] = None + is_keyword: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Wheter this group is a keyword group. Such groups are autogenerated when a user sets up a keyword. Contacts are automatically added when they enroll. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of this group.""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """Any notes on this group.""" - last_message_sent_utc: Optional[str] = None + last_message_sent_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of when the last group message was sent for this group.""" @@ -361,9 +413,9 @@ class UpdateGroupInput: Updates a group with the given id """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The new name of the group.""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """Short phrase describing group. Used for convenience.""" @@ -373,20 +425,20 @@ class UpdateGroupResponse: Response for Updates a group with the given id """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numerical id of the group.""" - group_member_count: Optional[int] = None + group_member_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of members of the group.""" - is_keyword: Optional[bool] = None + is_keyword: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Wheter this group is a keyword group. Such groups are autogenerated when a user sets up a keyword. Contacts are automatically added when they enroll. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of this group.""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """Any notes on this group.""" - last_message_sent_utc: Optional[str] = None + last_message_sent_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of when the last group message was sent for this group.""" @@ -396,12 +448,12 @@ class GetGroupsResponse: Response for Gets all groups """ - meta: Optional[Dict[str, Any]] = None + meta: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """ Metadata about the data returned by this request. This data is returned by all bulk GET requests. """ - items: Optional[List[Dict[str, Any]]] = None + items: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of group entities gotten from Text Request.""" @@ -411,9 +463,9 @@ class CreateGroupInput: Creates a new group """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The new name of the group.""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """Short phrase describing group. Used for convenience.""" @@ -423,20 +475,20 @@ class CreateGroupResponse: Response for Creates a new group """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numerical id of the group.""" - group_member_count: Optional[int] = None + group_member_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of members of the group.""" - is_keyword: Optional[bool] = None + is_keyword: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Wheter this group is a keyword group. Such groups are autogenerated when a user sets up a keyword. Contacts are automatically added when they enroll. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of this group.""" - notes: Optional[str] = None + notes: Optional[str] = dataclass_field(default=None, kw_only=True) """Any notes on this group.""" - last_message_sent_utc: Optional[str] = None + last_message_sent_utc: Optional[str] = dataclass_field(default=None, kw_only=True) """Timestamp of when the last group message was sent for this group.""" @@ -446,12 +498,12 @@ class GetTagsResponse: Response for Gets all tags """ - meta: Optional[Dict[str, Any]] = None + meta: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """ Metadata about the data returned by this request. This data is returned by all bulk GET requests. """ - items: Optional[List[Dict[str, Any]]] = None + items: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of tag entities gotten from Text Request.""" @@ -461,40 +513,40 @@ class GetPaymentResponse: Response for Gets the payment with the specified id """ - payment_id: Optional[int] = None + payment_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numerical id of the payment.""" - request_date: Optional[str] = None + request_date: Optional[str] = dataclass_field(default=None, kw_only=True) """ The timestamp of when this payment's initial message was queued to be sent. """ - recipient: Optional[str] = None + recipient: Optional[str] = dataclass_field(default=None, kw_only=True) """ The name of the payment recipient. This may be null if the contact does not have a name associated with their phone number. """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """ The description of the payment. This is not shown to the contact. It is only used by internal users for context about payments. """ - customer_phone: Optional[str] = None + customer_phone: Optional[str] = dataclass_field(default=None, kw_only=True) """The phone number of the contact who is being sent this payment.""" - amount_requested: Optional[float] = None + amount_requested: Optional[float] = dataclass_field(default=None, kw_only=True) """The amount in dollars requested by this payment.""" - is_past_due: Optional[bool] = None + is_past_due: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether this payment is past the request date.""" - reminder_was_sent: Optional[bool] = None + reminder_was_sent: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether a text reminder has already been sent for this payment.""" - transaction_status: Optional[str] = None + transaction_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ The status of the transaction in authvia. This value starts as Unknown. """ - textrequest_payment_status: Optional[str] = None + textrequest_payment_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ The status of the transaction in Text Request. This represents that status shown in the payments page on the Text Request app. It starts as Sent. """ - reference_number: Optional[str] = None + reference_number: Optional[str] = dataclass_field(default=None, kw_only=True) """ The user-defined id defined when payments are created that can be used to quickly find payments. Reference numbers are not unique; many payments can @@ -508,40 +560,40 @@ class MarkPaymentPaidResponse: Response for Mark a payment as paid """ - payment_id: Optional[int] = None + payment_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numerical id of the payment.""" - request_date: Optional[str] = None + request_date: Optional[str] = dataclass_field(default=None, kw_only=True) """ The timestamp of when this payment's initial message was queued to be sent. """ - recipient: Optional[str] = None + recipient: Optional[str] = dataclass_field(default=None, kw_only=True) """ The name of the payment recipient. This may be null if the contact does not have a name associated with their phone number. """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """ The description of the payment. This is not shown to the contact. It is only used by internal users for context about payments. """ - customer_phone: Optional[str] = None + customer_phone: Optional[str] = dataclass_field(default=None, kw_only=True) """The phone number of the contact who is being sent this payment.""" - amount_requested: Optional[float] = None + amount_requested: Optional[float] = dataclass_field(default=None, kw_only=True) """The amount in dollars requested by this payment.""" - is_past_due: Optional[bool] = None + is_past_due: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether this payment is past the request date.""" - reminder_was_sent: Optional[bool] = None + reminder_was_sent: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether a text reminder has already been sent for this payment.""" - transaction_status: Optional[str] = None + transaction_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ The status of the transaction in authvia. This value starts as Unknown. """ - textrequest_payment_status: Optional[str] = None + textrequest_payment_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ The status of the transaction in Text Request. This represents that status shown in the payments page on the Text Request app. It starts as Sent. """ - reference_number: Optional[str] = None + reference_number: Optional[str] = dataclass_field(default=None, kw_only=True) """ The user-defined id defined when payments are created that can be used to quickly find payments. Reference numbers are not unique; many payments can @@ -555,40 +607,40 @@ class SendPaymentReminderResponse: Response for Send a follow-up text reminding the user to pay the specified payment """ - payment_id: Optional[int] = None + payment_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numerical id of the payment.""" - request_date: Optional[str] = None + request_date: Optional[str] = dataclass_field(default=None, kw_only=True) """ The timestamp of when this payment's initial message was queued to be sent. """ - recipient: Optional[str] = None + recipient: Optional[str] = dataclass_field(default=None, kw_only=True) """ The name of the payment recipient. This may be null if the contact does not have a name associated with their phone number. """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """ The description of the payment. This is not shown to the contact. It is only used by internal users for context about payments. """ - customer_phone: Optional[str] = None + customer_phone: Optional[str] = dataclass_field(default=None, kw_only=True) """The phone number of the contact who is being sent this payment.""" - amount_requested: Optional[float] = None + amount_requested: Optional[float] = dataclass_field(default=None, kw_only=True) """The amount in dollars requested by this payment.""" - is_past_due: Optional[bool] = None + is_past_due: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether this payment is past the request date.""" - reminder_was_sent: Optional[bool] = None + reminder_was_sent: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether a text reminder has already been sent for this payment.""" - transaction_status: Optional[str] = None + transaction_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ The status of the transaction in authvia. This value starts as Unknown. """ - textrequest_payment_status: Optional[str] = None + textrequest_payment_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ The status of the transaction in Text Request. This represents that status shown in the payments page on the Text Request app. It starts as Sent. """ - reference_number: Optional[str] = None + reference_number: Optional[str] = dataclass_field(default=None, kw_only=True) """ The user-defined id defined when payments are created that can be used to quickly find payments. Reference numbers are not unique; many payments can @@ -602,40 +654,40 @@ class CancelPaymentResponse: Response for Cancels the specified payment """ - payment_id: Optional[int] = None + payment_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numerical id of the payment.""" - request_date: Optional[str] = None + request_date: Optional[str] = dataclass_field(default=None, kw_only=True) """ The timestamp of when this payment's initial message was queued to be sent. """ - recipient: Optional[str] = None + recipient: Optional[str] = dataclass_field(default=None, kw_only=True) """ The name of the payment recipient. This may be null if the contact does not have a name associated with their phone number. """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """ The description of the payment. This is not shown to the contact. It is only used by internal users for context about payments. """ - customer_phone: Optional[str] = None + customer_phone: Optional[str] = dataclass_field(default=None, kw_only=True) """The phone number of the contact who is being sent this payment.""" - amount_requested: Optional[float] = None + amount_requested: Optional[float] = dataclass_field(default=None, kw_only=True) """The amount in dollars requested by this payment.""" - is_past_due: Optional[bool] = None + is_past_due: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether this payment is past the request date.""" - reminder_was_sent: Optional[bool] = None + reminder_was_sent: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether a text reminder has already been sent for this payment.""" - transaction_status: Optional[str] = None + transaction_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ The status of the transaction in authvia. This value starts as Unknown. """ - textrequest_payment_status: Optional[str] = None + textrequest_payment_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ The status of the transaction in Text Request. This represents that status shown in the payments page on the Text Request app. It starts as Sent. """ - reference_number: Optional[str] = None + reference_number: Optional[str] = dataclass_field(default=None, kw_only=True) """ The user-defined id defined when payments are created that can be used to quickly find payments. Reference numbers are not unique; many payments can @@ -649,12 +701,12 @@ class GetPaymentsResponse: Response for Gets all payments """ - meta: Optional[Dict[str, Any]] = None + meta: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """ Metadata about the data returned by this request. This data is returned by all bulk GET requests. """ - items: Optional[List[Dict[str, Any]]] = None + items: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of payment entities gotten from Text Request.""" @@ -664,18 +716,18 @@ class CreatePaymentInput: Creates a new payment """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """ Description of the payment. Description is not shown to the contact and is only used by internal users for context about payments. """ - customer_phone: Optional[str] = None + customer_phone: Optional[str] = dataclass_field(default=None, kw_only=True) """Phone number of the contact this payment will be sent to.""" - amount_requested: Optional[float] = None + amount_requested: Optional[float] = dataclass_field(default=None, kw_only=True) """The amount in dollars requested by this payment. """ - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """Message text to send to contact along with payment link.""" - reference_number: Optional[str] = None + reference_number: Optional[str] = dataclass_field(default=None, kw_only=True) """ User-defined id defined when payments are created that can be used to quickly find payments. Reference numbers are not unique; many payments can @@ -689,40 +741,40 @@ class CreatePaymentResponse: Response for Creates a new payment """ - payment_id: Optional[int] = None + payment_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numerical id of the payment.""" - request_date: Optional[str] = None + request_date: Optional[str] = dataclass_field(default=None, kw_only=True) """ The timestamp of when this payment's initial message was queued to be sent. """ - recipient: Optional[str] = None + recipient: Optional[str] = dataclass_field(default=None, kw_only=True) """ The name of the payment recipient. This may be null if the contact does not have a name associated with their phone number. """ - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """ The description of the payment. This is not shown to the contact. It is only used by internal users for context about payments. """ - customer_phone: Optional[str] = None + customer_phone: Optional[str] = dataclass_field(default=None, kw_only=True) """The phone number of the contact who is being sent this payment.""" - amount_requested: Optional[float] = None + amount_requested: Optional[float] = dataclass_field(default=None, kw_only=True) """The amount in dollars requested by this payment.""" - is_past_due: Optional[bool] = None + is_past_due: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether this payment is past the request date.""" - reminder_was_sent: Optional[bool] = None + reminder_was_sent: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether a text reminder has already been sent for this payment.""" - transaction_status: Optional[str] = None + transaction_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ The status of the transaction in authvia. This value starts as Unknown. """ - textrequest_payment_status: Optional[str] = None + textrequest_payment_status: Optional[str] = dataclass_field(default=None, kw_only=True) """ The status of the transaction in Text Request. This represents that status shown in the payments page on the Text Request app. It starts as Sent. """ - reference_number: Optional[str] = None + reference_number: Optional[str] = dataclass_field(default=None, kw_only=True) """ The user-defined id defined when payments are created that can be used to quickly find payments. Reference numbers are not unique; many payments can @@ -736,11 +788,11 @@ class GetDashboardResponse: Response for Get info on this specific dashboard """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numerical id of the dashboard.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the dashboard.""" - phone: Optional[str] = None + phone: Optional[str] = dataclass_field(default=None, kw_only=True) """The texting number associated with this dashboard.""" @@ -750,7 +802,7 @@ class UpdateDashboardsNameInput: Update a specific dashboard's name """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The new name of the dashboard.""" @@ -760,11 +812,11 @@ class UpdateDashboardsNameResponse: Response for Update a specific dashboard's name """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numerical id of the dashboard.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the dashboard.""" - phone: Optional[str] = None + phone: Optional[str] = dataclass_field(default=None, kw_only=True) """The texting number associated with this dashboard.""" @@ -774,12 +826,12 @@ class GetConversationsResponse: Response for Gets all conversations for this dashboard """ - meta: Optional[Dict[str, Any]] = None + meta: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """ Metadata about the data returned by this request. This data is returned by all bulk GET requests. """ - items: Optional[List[Dict[str, Any]]] = None + items: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of conversation entities gotten from Text Request.""" @@ -789,12 +841,12 @@ class GetDashboardsResponse: Response for Get all dashboards in an account """ - meta: Optional[Dict[str, Any]] = None + meta: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """ Metadata about the data returned by this request. This data is returned by all bulk GET requests. """ - items: Optional[List[Dict[str, Any]]] = None + items: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of dashboard entities gotten from Text Request.""" @@ -804,9 +856,9 @@ class CreateDashboardInput: Create a new dashboard with the given name and phone number """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the dashboard.""" - phone: Optional[str] = None + phone: Optional[str] = dataclass_field(default=None, kw_only=True) """The texting number associated with this dashboard.""" @@ -816,11 +868,11 @@ class CreateDashboardResponse: Response for Create a new dashboard with the given name and phone number """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numerical id of the dashboard.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the dashboard.""" - phone: Optional[str] = None + phone: Optional[str] = dataclass_field(default=None, kw_only=True) """The texting number associated with this dashboard.""" @@ -830,14 +882,11 @@ class TextingWebhookInput: Triggers when a text is sent or received """ - target_url: Optional[str] = None + target_url: str """Url the webhook will redirect to""" - event: Optional[str] = None + event: str """event""" - http_verb: Optional[str] = field( - default=None, - metadata={"wire_name": "httpVerb"}, - ) + http_verb: str = dataclass_field(metadata={"wire_name": "httpVerb"}) """httpVerb""" @@ -847,11 +896,11 @@ class TextingWebhookResponse: Response for Triggers when a text is sent or received """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The numerical id of the dashboard.""" - target_url: Optional[str] = None + target_url: Optional[str] = dataclass_field(default=None, kw_only=True) """The url the webhook will post to""" - event: Optional[str] = None + event: Optional[str] = dataclass_field(default=None, kw_only=True) """The webhook's associated trigger event""" @@ -863,16 +912,16 @@ class TextrequestClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -883,8 +932,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -892,8 +941,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -905,7 +954,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -920,7 +969,46 @@ def __init__( def connector_name(self) -> str: return "textrequest" - async def get_messages_by_contact_phone_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_messages_by_contact_phone( self, dashboard_id: int, phone_number: str, @@ -931,11 +1019,39 @@ async def get_messages_by_contact_phone_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get a conversation's messages by a contact's phone number Get the conversation between the specified dashboard and phone number. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMessagesByContactPhone`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + phone_number: Phone number of the contact to get messages for. + page: The page of entities to get. When getting values, there is a + max size per page, defined by page_size. If page is greater + than the last page, an empty array will be returned. + page_size: The size of each page to get. When getting values, this + is a max size per page, with accessing subsequent pages done by + the page parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -956,31 +1072,52 @@ async def get_messages_by_contact_phone_async( query_params.append(f"page_size={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item - async def send_message_by_phone_number_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def send_message_by_phone_number( self, - input: SendMessageByPhoneNumberInput, + input: SendMessageByPhoneNumberInput | Mapping[str, Any], dashboard_id: int, phone_number: str, *, @@ -994,6 +1131,26 @@ async def send_message_by_phone_number_async( Sends a message (starting a new conversation if the given phone number has no message history). + + Swagger operation ID: `SendMessageByPhoneNumber`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + phone_number: Phone number of the contact to send a message to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1004,7 +1161,7 @@ async def send_message_by_phone_number_async( f"/messages" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1018,6 +1175,7 @@ async def send_message_by_phone_number_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1025,7 +1183,7 @@ async def send_message_by_phone_number_async( return json.loads(response.text) - async def archive_conversation_async( + def archive_conversation( self, dashboard_id: int, phone_number: str, @@ -1046,6 +1204,24 @@ async def archive_conversation_async( you don't plan on talking to in the future. Note that if a customer texts in \"STOP\" to prevent you from sending them any further SMS messages, the conversation is automatically archived. + + Swagger operation ID: `ArchiveConversation`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + phone_number: Phone number of the conversation to archive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1057,7 +1233,7 @@ async def archive_conversation_async( f"/archive" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -1071,6 +1247,7 @@ async def archive_conversation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1078,7 +1255,7 @@ async def archive_conversation_async( return json.loads(response.text) - async def unarchive_conversation_async( + def unarchive_conversation( self, dashboard_id: int, phone_number: str, @@ -1095,6 +1272,24 @@ async def unarchive_conversation_async( once again appear in the queue. it will also appear in conversations returned by the /conversations endpoint. If a conversation is already unarchived, this method has no effect. + + Swagger operation ID: `UnarchiveConversation`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + phone_number: Phone number of the conversation to archive. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1106,7 +1301,7 @@ async def unarchive_conversation_async( f"/unarchive" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -1120,6 +1315,7 @@ async def unarchive_conversation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1127,7 +1323,7 @@ async def unarchive_conversation_async( return json.loads(response.text) - async def get_contact_by_phone_number_async( + def get_contact_by_phone_number( self, dashboard_id: int, phone_number: str, @@ -1141,6 +1337,24 @@ async def get_contact_by_phone_number_async( Gets the contact with the specified phone number Gets the contact with the specified phone number + + Swagger operation ID: `GetContactByPhoneNumber`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + phone_number: Phone number of the contact to get. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1150,7 +1364,7 @@ async def get_contact_by_phone_number_async( f"/{quote(str(phone_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1164,6 +1378,7 @@ async def get_contact_by_phone_number_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1171,7 +1386,7 @@ async def get_contact_by_phone_number_async( return json.loads(response.text) - async def delete_contact_async( + def delete_contact( self, dashboard_id: int, phone_number: str, @@ -1185,6 +1400,24 @@ async def delete_contact_async( Deletes the contact with the specified phone number Deletes the contact with the specified phone number + + Swagger operation ID: `DeleteContact`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + phone_number: Phone number of the contact to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1194,7 +1427,7 @@ async def delete_contact_async( f"/{quote(str(phone_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1208,6 +1441,7 @@ async def delete_contact_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1215,9 +1449,9 @@ async def delete_contact_async( return json.loads(response.text) - async def create_contact_async( + def create_contact( self, - input: CreateContactInput, + input: CreateContactInput | Mapping[str, Any], dashboard_id: int, phone_number: str, *, @@ -1231,6 +1465,26 @@ async def create_contact_async( Creates or updates a contact (depending on whether one already exists with the given phone number). + + Swagger operation ID: `CreateContact`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + phone_number: Phone number of the contact to create or update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1240,7 +1494,7 @@ async def create_contact_async( f"/{quote(str(phone_number), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1254,6 +1508,7 @@ async def create_contact_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1261,11 +1516,12 @@ async def create_contact_async( return json.loads(response.text) - async def get_contacts_async( + def list_contacts( self, dashboard_id: int, page: int, page_size: int, + *, contact_phone_number: Optional[str] = None, last_message_timestamp_before_utc: Optional[str] = None, last_message_timestamp_after_utc: Optional[str] = None, @@ -1288,18 +1544,101 @@ async def get_contacts_async( custom_field_value2: Optional[str] = None, custom_field_id3: Optional[str] = None, custom_field_value3: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get all contacts that match the specified filtering criterion Gets all contacts that match the specified filtering criterion. Only the dashboard specified will be searched; there is no account level search for a number available. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetContacts`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + page: The page of entities to get. When getting values, there is a + max size per page, defined by page_size. If page is greater + than the last page, an empty array will be returned. + page_size: The size of each page to get. When getting values, this + is a max size per page, with accessing subsequent pages done by + the page parameter. + contact_phone_number: Phone number to filter contacts by. + last_message_timestamp_before_utc: Cutoff time for searching + contacts by the last message sent or received. No contacts who + sent messages after this time will be shown. + last_message_timestamp_after_utc: Cutoff time for searching + contacts by the last message sent or received. No contacts + whose last sent message is before this time will be shown. + contact_created_before: Cutoff time for searching contacts by when + they were created. No contacts created after this time will be + shown. + contact_created_after: Cutoff time for searching contacts by when + they were created. No contacts created before this time will be + shown. + is_resolved: Whether to search for contacts whose conversations + have been resolved. + is_blocked: Whether to search for contacts who have been blocked. + is_archived: Whether to search for contacts who have been archived. + is_suppressed: Whether to search for contacts who have been + suppressed. + has_opted_out: Whether to search for contacts who have opted out of + receiving texts. + last_message_sent_before: Cutoff time for searching contacts by + when the last message was sent to the customer. No contacts who + sent messages after this time will be shown. Uses timestamp as + local time. To filter by time stamp in UTC time, use + last_message_sent_before_utc. + last_message_sent_after: Cutoff time for searching contacts by when + the last message was sent to the customer. No contacts whose + last sent message is before this time will be shown. Uses + timestamp as local time. To filter by time stamp in UTC time, + use last_message_sent_after_utc. + last_message_received_before: Cutoff time for searching contacts by + the last message received from the customer. No contacts who + received messages after this time will be shown. Uses timestamp + as local time. To filter by time stamp in UTC time, use + last_message_sent_before_utc. + last_message_received_after: Cutoff time for searching contacts by + the last message received from the customer. No contacts whose + last sent message is before this time will be shown. Uses + timestamp as local time. To filter by time stamp in UTC time, + use last_message_sent_before_utc. + tags: Comma-separated list of guids referring to tags to filter + contacts by. + groups: Comma-separated list of integer ids referring to groups to + filter contacts by. + custom_field_id1: Guid referring to custom field to filter contacts + by. + custom_field_value1: Value referring to custom field to filter + contacts by. + custom_field_id2: Guid referring to second custom field to filter + contacts by. + custom_field_value2: Value referring to second custom field to + filter contacts by. + custom_field_id3: Guid referring to third custom field to filter + contacts by. + custom_field_value3: Value referring to third custom field to + filter contacts by. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1426,29 +1765,50 @@ async def get_contacts_async( query_params.append(f"page_size={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() - async def bulk_update_contacts_async( + return ItemPaged(get_next, extract_data) + + def bulk_update_contacts( self, input: BulkUpdateContactsInput, dashboard_id: int, @@ -1464,13 +1824,31 @@ async def bulk_update_contacts_async( Only the dashboard specified will have contacts added; contacts are organized by dashboard, and there is no account level search for a number available. + + Swagger operation ID: `BulkUpdateContacts`. + + Args: + input: The request body. + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/dashboards/{quote(str(dashboard_id), safe='')}/contacts" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1484,6 +1862,7 @@ async def bulk_update_contacts_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1491,7 +1870,7 @@ async def bulk_update_contacts_async( return json.loads(response.text) - async def get_group_by_id_async( + def get_group_by_id( self, dashboard_id: int, group_id: int, @@ -1505,6 +1884,24 @@ async def get_group_by_id_async( Get a group by its id Gets the group with the specified id. + + Swagger operation ID: `GetGroupById`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + group_id: The numerical id of the group to get. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1514,7 +1911,7 @@ async def get_group_by_id_async( f"/{quote(str(group_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1528,6 +1925,7 @@ async def get_group_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1535,7 +1933,7 @@ async def get_group_by_id_async( return json.loads(response.text) - async def delete_group_async( + def delete_group( self, dashboard_id: int, group_id: int, @@ -1551,6 +1949,24 @@ async def delete_group_async( Deletes the group with the specified id. This will succeed even if there are contacts that are members of the group (the contacts will not be deleted). + + Swagger operation ID: `DeleteGroup`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + group_id: The numerical id of the group to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1560,7 +1976,7 @@ async def delete_group_async( f"/{quote(str(group_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1574,6 +1990,7 @@ async def delete_group_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1581,9 +1998,9 @@ async def delete_group_async( return json.loads(response.text) - async def update_group_async( + def update_group( self, - input: UpdateGroupInput, + input: UpdateGroupInput | Mapping[str, Any], dashboard_id: int, group_id: int, *, @@ -1597,6 +2014,26 @@ async def update_group_async( Updates a group's name using the group's numerical id. If the passed in group id does not exist, the call will fail. + + Swagger operation ID: `UpdateGroup`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + group_id: The numerical id of the group to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1606,7 +2043,7 @@ async def update_group_async( f"/{quote(str(group_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -1620,6 +2057,7 @@ async def update_group_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1627,7 +2065,7 @@ async def update_group_async( return json.loads(response.text) - async def get_groups_async( + def list_groups( self, dashboard_id: int, page: int, @@ -1637,11 +2075,38 @@ async def get_groups_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Gets all groups Gets all groups for the user's account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetGroups`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + page: The page of entities to get. When getting values, there is a + max size per page, defined by page_size. If page is greater + than the last page, an empty array will be returned. + page_size: The size of each page to get. When getting values, this + is a max size per page, with accessing subsequent pages done by + the page parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1658,31 +2123,52 @@ async def get_groups_async( query_params.append(f"page_size={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() - async def create_group_async( + return ItemPaged(get_next, extract_data) + + def create_group( self, - input: CreateGroupInput, + input: CreateGroupInput | Mapping[str, Any], dashboard_id: int, *, timeout: Optional[float] = None, @@ -1694,13 +2180,32 @@ async def create_group_async( Creates a new group Creates a new group with the provided name. + + Swagger operation ID: `CreateGroup`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/dashboards/{quote(str(dashboard_id), safe='')}/groups" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1714,6 +2219,7 @@ async def create_group_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1721,7 +2227,7 @@ async def create_group_async( return json.loads(response.text) - async def get_tags_async( + def list_tags( self, dashboard_id: int, page: int, @@ -1731,12 +2237,39 @@ async def get_tags_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Gets all tags Gets all the tags for this dashboard. Tags are unique between dashboards. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTags`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + page: The page of entities to get. When getting values, there is a + max size per page, defined by page_size. If page is greater + than the last page, an empty array will be returned. + page_size: The size of each page to get. When getting values, this + is a max size per page, with accessing subsequent pages done by + the page parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1753,29 +2286,50 @@ async def get_tags_async( query_params.append(f"page_size={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item - async def get_custom_fields_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_custom_fields( self, dashboard_id: int, *, @@ -1783,40 +2337,82 @@ async def get_custom_fields_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Gets all custom fields Gets all custom fields for this dashboard. Custom fields are unique between dashboards. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetCustomFields`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/dashboards/{quote(str(dashboard_id), safe='')}/fields" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def get_payment_async( + return ItemPaged(get_next, extract_data) + + def get_payment( self, dashboard_id: int, payment_id: int, @@ -1830,6 +2426,24 @@ async def get_payment_async( Gets the payment with the specified id Gets the payment with the specified id. + + Swagger operation ID: `GetPayment`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + payment_id: The numerical id of the payment to get. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1839,7 +2453,7 @@ async def get_payment_async( f"/{quote(str(payment_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1853,6 +2467,7 @@ async def get_payment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1860,7 +2475,7 @@ async def get_payment_async( return json.loads(response.text) - async def mark_payment_paid_async( + def mark_payment_paid( self, dashboard_id: int, payment_id: int, @@ -1879,6 +2494,24 @@ async def mark_payment_paid_async( endpoint is not required for payments paid through the payments-portal sent through Text Request; that will automatically mark a payment as paid. + + Swagger operation ID: `MarkPaymentPaid`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + payment_id: The numerical id of the payment to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1889,7 +2522,7 @@ async def mark_payment_paid_async( f"/mark_as_paid" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1903,6 +2536,7 @@ async def mark_payment_paid_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1910,7 +2544,7 @@ async def mark_payment_paid_async( return json.loads(response.text) - async def send_payment_reminder_async( + def send_payment_reminder( self, dashboard_id: int, payment_id: int, @@ -1926,6 +2560,24 @@ async def send_payment_reminder_async( Sends a reminder to the contact to pay the specified payment. The content of the message is auto-generated. To avoid spam, only one reminder can be sent per payment + + Swagger operation ID: `SendPaymentReminder`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + payment_id: The numerical id of the payment to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1936,7 +2588,7 @@ async def send_payment_reminder_async( f"/resend" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1950,6 +2602,7 @@ async def send_payment_reminder_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1957,7 +2610,7 @@ async def send_payment_reminder_async( return json.loads(response.text) - async def cancel_payment_async( + def cancel_payment( self, dashboard_id: int, payment_id: int, @@ -1973,6 +2626,24 @@ async def cancel_payment_async( Cancels the specified payment, texting the user that the payment has been canceled. Payments cannot be edited, so canceling and issuing a new payment is the best way to correct a payment. + + Swagger operation ID: `CancelPayment`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + payment_id: The numerical id of the payment to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1983,7 +2654,7 @@ async def cancel_payment_async( f"/cancel" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -1997,6 +2668,7 @@ async def cancel_payment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2004,26 +2676,61 @@ async def cancel_payment_async( return json.loads(response.text) - async def get_payments_async( + def list_payments( self, dashboard_id: int, page: int, page_size: int, + *, reference_number: Optional[str] = None, phone_number: Optional[str] = None, sort_type: Optional[str] = None, sort_direction: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Gets all payments Gets all payments, including canceled and paid payments. These can be filtered using the query parameters. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetPayments`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + page: The page of entities to get. When getting values, there is a + max size per page, defined by page_size. If page is greater + than the last page, an empty array will be returned. + page_size: The size of each page to get. When getting values, this + is a max size per page, with accessing subsequent pages done by + the page parameter. + reference_number: User-defined id defined when payments are created + that can be used to quickly find payments. Reference numbers + are not unique; many payments can have the same reference. + phone_number: Phone number of the contact this payment was sent to. + sort_type: Property to sort payments by. Can be \"amount\", + \"contact\", \"date\", \"status\". + sort_direction: Direction to sort payments in. Can be \"desc\" for + greatest to smallest, or \"asc\" for smallest to greatest. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2060,31 +2767,52 @@ async def get_payments_async( query_params.append(f"page_size={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() - async def create_payment_async( + return ItemPaged(get_next, extract_data) + + def create_payment( self, - input: CreatePaymentInput, + input: CreatePaymentInput | Mapping[str, Any], dashboard_id: int, *, timeout: Optional[float] = None, @@ -2097,13 +2825,32 @@ async def create_payment_async( Creates a new payment with the provided message to the provided contact. + + Swagger operation ID: `CreatePayment`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/dashboards/{quote(str(dashboard_id), safe='')}/payments" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2117,6 +2864,7 @@ async def create_payment_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2124,7 +2872,7 @@ async def create_payment_async( return json.loads(response.text) - async def get_dashboard_async( + def get_dashboard( self, dashboard_id: int, *, @@ -2137,13 +2885,30 @@ async def get_dashboard_async( Get info on this specific dashboard Returns the name and phone of the dashboard. + + Swagger operation ID: `GetDashboard`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/dashboards/{quote(str(dashboard_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2157,6 +2922,7 @@ async def get_dashboard_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2164,7 +2930,7 @@ async def get_dashboard_async( return json.loads(response.text) - async def delete_dashboard_async( + def delete_dashboard( self, dashboard_id: int, *, @@ -2177,13 +2943,30 @@ async def delete_dashboard_async( Deletes the specified dashboard Deletes the specified dashboard. + + Swagger operation ID: `DeleteDashboard`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/dashboards/{quote(str(dashboard_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -2197,6 +2980,7 @@ async def delete_dashboard_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2204,9 +2988,9 @@ async def delete_dashboard_async( return json.loads(response.text) - async def update_dashboards_name_async( + def update_dashboards_name( self, - input: UpdateDashboardsNameInput, + input: UpdateDashboardsNameInput | Mapping[str, Any], dashboard_id: int, *, timeout: Optional[float] = None, @@ -2221,13 +3005,32 @@ async def update_dashboards_name_async( If you want a new number with another dashboard's contacts, you will have to create a new dashboard with a POST and add the contacts with a bulk export/import. + + Swagger operation ID: `UpdateDashboardsName`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/dashboards/{quote(str(dashboard_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -2241,6 +3044,7 @@ async def update_dashboards_name_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2248,26 +3052,64 @@ async def update_dashboards_name_async( return json.loads(response.text) - async def get_conversations_async( + def list_conversations( self, dashboard_id: int, + *, tags: Optional[str] = None, show_unresolved_only: Optional[str] = None, include_archived: Optional[str] = None, search: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Gets all conversations for this dashboard Gets all conversations for this dashboard, and includes info on the last message for each conversation. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetConversations`. + + Args: + dashboard_id: The phone number dashboard to work on. A single + account can have several dashboards, representing different + phone lines for customers. + tags: Comma-separated list of guids referring to tags to filter + conversations by. + show_unresolved_only: Whether to only search for contacts whose + conversations have been resolved. If this is false, both + resolved and unresolved conversations will be shown. + include_archived: Whether to include conversations with contacts + that have been archived. + search: Search term for filtering conversations by phone number or + display name. If the search term is less than a full name or + phone number, the search will return all conversations that + partially match it. + page: The page of entities to get. When getting values, there is a + max size per page, defined by page_size. If page is greater + than the last page, an empty array will be returned. + page_size: The size of each page to get. When getting values, this + is a max size per page, with accessing subsequent pages done by + the page parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2306,42 +3148,87 @@ async def get_conversations_async( query_params.append(f"page_size={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_dashboards_async( + def list_dashboards( self, + *, page: Optional[int] = None, page_size: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get all dashboards in an account Gets all dashboards in an account. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetDashboards`. + + Args: + page: The page of entities to get. When getting values, there is a + max size per page, defined by page_size. If page is greater + than the last page, an empty array will be returned. + page_size: The size of each page to get. When getting values, this + is a max size per page, with accessing subsequent pages done by + the page parameter. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/dashboards" query_params = [] @@ -2357,31 +3244,52 @@ async def get_dashboards_async( query_params.append(f"page_size={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() - async def create_dashboard_async( + return ItemPaged(get_next, extract_data) + + def create_dashboard( self, - input: CreateDashboardInput, + input: CreateDashboardInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -2397,10 +3305,26 @@ async def create_dashboard_async( search for provisioned numbers in a specific area code using GET /dashboards/provisioning. If the phone number is already in use, a Bad Request exception will be thrown. + + Swagger operation ID: `CreateDashboard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/dashboards" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2414,6 +3338,7 @@ async def create_dashboard_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/ticketmaster.py b/src/azure/connectors/ticketmaster.py index e3ca3b4..9a65d31 100644 --- a/src/azure/connectors/ticketmaster.py +++ b/src/azure/connectors/ticketmaster.py @@ -5,14 +5,13 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, Dict, List, Any, Mapping from urllib.parse import quote import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, @@ -20,6 +19,23 @@ ConnectorResponseHook, ) +__all__ = [ + "TicketmasterClient", + "AttractionGetResponse", + "AttractionsGetResponse", + "ClassificationGetResponse", + "ClassificationsGetResponse", + "EventGetResponse", + "EventImagesGetResponse", + "EventsGetResponse", + "GenreGetResponse", + "SegmentGetResponse", + "SubGenreGetResponse", + "SuggestionsGetResponse", + "VenueGetResponse", + "VenuesGetResponse", +] + # Type Definitions @@ -29,15 +45,17 @@ class EventsGetResponse: Response for Event search """ - links: Optional[Dict[str, Any]] = field( + links: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) - embedded: Optional[Dict[str, Any]] = field( + embedded: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_embedded"}, ) - page: Optional[Dict[str, Any]] = None + page: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -46,39 +64,52 @@ class EventGetResponse: Response for Get event details """ - embedded: Optional[Dict[str, Any]] = field( + embedded: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_embedded"}, ) - links: Optional[Dict[str, Any]] = field( + links: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) - classifications: Optional[List[Dict[str, Any]]] = None - dates: Optional[Dict[str, Any]] = None - id: Optional[str] = None + classifications: Optional[ + List[Dict[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + dates: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - images: Optional[List[Dict[str, Any]]] = None - locale: Optional[str] = None + images: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + locale: Optional[str] = dataclass_field(default=None, kw_only=True) """The locale.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name.""" - please_note: Optional[str] = field( + please_note: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "pleaseNote"}, ) """The please note.""" - price_ranges: Optional[List[Dict[str, Any]]] = field( + price_ranges: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "priceRanges"}, ) - promoter: Optional[Dict[str, Any]] = None - sales: Optional[Dict[str, Any]] = None - test: Optional[bool] = None + promoter: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + sales: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + test: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether test.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The URL address.""" @@ -88,13 +119,18 @@ class EventImagesGetResponse: Response for Get event images """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - images: Optional[List[Dict[str, Any]]] = None - links: Optional[Dict[str, Any]] = field( + images: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + links: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) @@ -105,15 +141,17 @@ class AttractionsGetResponse: Response for Attraction search """ - links: Optional[Dict[str, Any]] = field( + links: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) - embedded: Optional[Dict[str, Any]] = field( + embedded: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_embedded"}, ) - page: Optional[Dict[str, Any]] = None + page: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -122,20 +160,30 @@ class AttractionGetResponse: Response for Get attraction details """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - test: Optional[bool] = None + test: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether test.""" - locale: Optional[str] = None + locale: Optional[str] = dataclass_field(default=None, kw_only=True) """The locale.""" - images: Optional[List[Dict[str, Any]]] = None - classifications: Optional[List[Dict[str, Any]]] = None - links: Optional[Dict[str, Any]] = field( + images: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + classifications: Optional[ + List[Dict[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + links: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) @@ -146,15 +194,17 @@ class ClassificationsGetResponse: Response for Classification search """ - links: Optional[Dict[str, Any]] = field( + links: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) - embedded: Optional[Dict[str, Any]] = field( + embedded: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_embedded"}, ) - page: Optional[Dict[str, Any]] = None + page: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -163,11 +213,12 @@ class ClassificationGetResponse: Response for Get classification details """ - links: Optional[Dict[str, Any]] = field( + links: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) - segment: Optional[Dict[str, Any]] = None + segment: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -176,17 +227,19 @@ class GenreGetResponse: Response for Get genre details """ - embedded: Optional[Dict[str, Any]] = field( + embedded: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_embedded"}, ) - links: Optional[Dict[str, Any]] = field( + links: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name.""" @@ -196,16 +249,18 @@ class SegmentGetResponse: Response for Get segment details """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name.""" - links: Optional[Dict[str, Any]] = field( + links: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) - embedded: Optional[Dict[str, Any]] = field( + embedded: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_embedded"}, ) @@ -216,15 +271,16 @@ class SubGenreGetResponse: Response for Get sub-genre details """ - links: Optional[Dict[str, Any]] = field( + links: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name.""" - locale: Optional[str] = None + locale: Optional[str] = dataclass_field(default=None, kw_only=True) """The locale.""" @@ -234,15 +290,17 @@ class VenuesGetResponse: Response for Venue search """ - embedded: Optional[Dict[str, Any]] = field( + embedded: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_embedded"}, ) - links: Optional[Dict[str, Any]] = field( + links: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) - page: Optional[Dict[str, Any]] = None + page: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -251,31 +309,37 @@ class VenueGetResponse: Response for Get venue details """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name.""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type.""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The identifier.""" - test: Optional[bool] = None + test: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether test.""" - locale: Optional[str] = None + locale: Optional[str] = dataclass_field(default=None, kw_only=True) """The locale.""" - postal_code: Optional[str] = field( + postal_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "postalCode"}, ) """The postal code.""" - timezone: Optional[str] = None + timezone: Optional[str] = dataclass_field(default=None, kw_only=True) """The timezone.""" - city: Optional[Dict[str, Any]] = None - state: Optional[Dict[str, Any]] = None - country: Optional[Dict[str, Any]] = None - address: Optional[Dict[str, Any]] = None - location: Optional[Dict[str, Any]] = None - markets: Optional[List[Dict[str, Any]]] = None - links: Optional[Dict[str, Any]] = field( + city: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + state: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + country: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + address: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + location: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + markets: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) + links: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) @@ -286,12 +350,14 @@ class SuggestionsGetResponse: Response for Find suggestions """ - links: Optional[Dict[str, Any]] = field( + links: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_links"}, ) - embedded: Optional[Dict[str, Any]] = field( + embedded: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_embedded"}, ) @@ -304,16 +370,16 @@ class TicketmasterClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -324,8 +390,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -333,8 +399,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -346,7 +412,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -361,8 +427,9 @@ def __init__( def connector_name(self) -> str: return "ticketmaster" - async def events_get_async( + def events_get( self, + *, size: Optional[int] = None, id: Optional[str] = None, keyword: Optional[str] = None, @@ -410,7 +477,6 @@ async def events_get_async( preferred_country: Optional[str] = None, include_spellcheck: Optional[str] = None, domain: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -421,6 +487,89 @@ async def events_get_async( Find events and filter your search by location, date, availability, and much more. + + Swagger operation ID: `EventsGet`. + + Args: + size: The page size of the response. + id: The filter for entities by their identifier. + keyword: The keyword to search on. + attraction_id: The filter by attraction identifier. + venue_id: The filter by venue identifier. + postal_code: The filter by postal code or zipcode. + latlong: The filter for events by latitude and longitude. This + filter is deprecated and may be removed in a future release, + please use geoPoint instead. + radius: The radius of the area in which we want to search for + events. + unit: The unit of the radius. + source: The filter for entities by their primary source name or + publishing source name. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + market_id: The filter by market identifier. + start_date_time: The filter with a start date after this date. + end_date_time: The filter with a start date before this date. + include_t_b_a: Indicates whether to include events with date to be + announced (TBA). + include_t_b_d: Indicates whether to include events with a date to + be defined (TBD). + include_test: Indicates whether to include entities flagged as test + in the response. + page: The page number. + sort: The sorting order of the search result. + onsale_start_date_time: The filter with onsale start date after + this date. + onsale_end_date_time: The filter with onsale end date before this + date. + city: The filter by city. + country_code: The filter by country code. + state_code: The filter by state code. + classification_name: The filter by classification name: name of any + segment, genre, sub-genre, type, sub-type. + classification_id: The filter by classification identifier: + identifier of any segment, genre, sub-genre, type, sub-type. + dma_id: The filter by DMA identifier. + local_start_date_time: The filter with event local start date time + within this range. + local_start_end_date_time: The filter for events where event local + start and end date overlap this range. + start_end_date_time: The filter for events where event start and + end date overlap this range. + public_visibility_start_date_time: The filter for events with + public visibility starting. + pre_sale_date_time: The filter for events with a presale start and + end that intersects with this range. + onsale_on_start_date: The filter with onsale start date on this + date. + onsale_on_after_start_date: The filter with onsale range within + this date. + collection_id: The filter by collection identifier. + segment_id: The filter by segment identifier. + segment_name: The filter by segment name. + include_family: The filter by classification that are + family-friendly. + promoter_id: The filter by promoter identifier. + genre_id: The filter by genre identifier. + sub_genre_id: The filter by sub-genre identifier. + type_id: The filter by type identifier. + sub_type_id: The filter by sub-type identifier. + geo_point: The filter for events by geoHash. + preferred_country: The popularity boost by country, default is us. + include_spellcheck: Indicates whether to include spell check + suggestions in the response. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/discovery/v2/events.json" @@ -825,7 +974,7 @@ async def events_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -839,6 +988,7 @@ async def events_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -846,12 +996,12 @@ async def events_get_async( return json.loads(response.text) - async def event_get_async( + def event_get( self, id: str, + *, locale: Optional[str] = None, domain: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -863,6 +1013,25 @@ async def event_get_async( Get details for a specific event using the unique identifier for the event. This includes the venue and location, the attraction(s), and the Ticketmaster Website URL for purchasing tickets for the event + + Swagger operation ID: `EventGet`. + + Args: + id: The unique identifier for the event. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -893,7 +1062,7 @@ async def event_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -907,6 +1076,7 @@ async def event_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -914,12 +1084,12 @@ async def event_get_async( return json.loads(response.text) - async def event_images_get_async( + def event_images_get( self, id: str, + *, locale: Optional[str] = None, domain: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -930,6 +1100,25 @@ async def event_images_get_async( Get images for a specific event using the unique identifier for the event. + + Swagger operation ID: `EventImagesGet`. + + Args: + id: The unique identifier for the event. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -960,7 +1149,7 @@ async def event_images_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -974,6 +1163,7 @@ async def event_images_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -981,8 +1171,9 @@ async def event_images_get_async( return json.loads(response.text) - async def attractions_get_async( + def attractions_get( self, + *, id: Optional[str] = None, keyword: Optional[str] = None, source: Optional[str] = None, @@ -1003,7 +1194,6 @@ async def attractions_get_async( preferred_country: Optional[str] = None, include_spellcheck: Optional[str] = None, domain: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1014,6 +1204,48 @@ async def attractions_get_async( Find attractions (artists, sports, packages, plays and so on) and filter your search by name, and much more. + + Swagger operation ID: `AttractionsGet`. + + Args: + id: The filter for entities by their identifier. + keyword: The keyword to search on. + source: The filter for entities by their primary source name or + publishing source name. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + include_test: Indicates whether to include entities flagged as test + in the response. + size: The page size of the response. + page: The page number. + sort: The sorting order of the search result. + classification_name: The filter for attractions by classification + name. + classification_id: The filter for attractions by classification + identifier. + include_family: The filter by classification that are + family-friendly. + segment_id: The filter for attractions by segment identifier. + genre_id: The filter for attractions by genre identifier. + sub_genre_id: The filter for attractions by sub-genre identifier. + type_id: The filter for attractions by type identifier. + sub_type_id: The filter for attractions by sub-type identifier. + country_code: The filter for attractions by country code. + preferred_country: The popularity boost by country, default is us. + include_spellcheck: Indicates whether to include spell check + suggestions in the response. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/discovery/v2/attractions" @@ -1203,7 +1435,7 @@ async def attractions_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1217,6 +1449,7 @@ async def attractions_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1224,12 +1457,12 @@ async def attractions_get_async( return json.loads(response.text) - async def attraction_get_async( + def attraction_get( self, id: str, + *, locale: Optional[str] = None, domain: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1240,6 +1473,25 @@ async def attraction_get_async( Get details for a specific attraction using the unique identifier for the attraction. + + Swagger operation ID: `AttractionGet`. + + Args: + id: The unique identifier for the attraction. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1270,7 +1522,7 @@ async def attraction_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1284,6 +1536,7 @@ async def attraction_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1291,8 +1544,9 @@ async def attraction_get_async( return json.loads(response.text) - async def classifications_get_async( + def classifications_get( self, + *, id: Optional[str] = None, keyword: Optional[str] = None, source: Optional[str] = None, @@ -1305,7 +1559,6 @@ async def classifications_get_async( preferred_country: Optional[str] = None, include_spellcheck: Optional[str] = None, domain: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1316,6 +1569,37 @@ async def classifications_get_async( Find classifications and filter your search by name, and much more. Classifications help define the nature of attractions and events. + + Swagger operation ID: `ClassificationsGet`. + + Args: + id: The filter for entities by their identifier. + keyword: The keyword to search on. + source: The filter for entities by their primary source name or + publishing source name. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + include_test: Indicates whether to include entities flagged as test + in the response. + size: The page size of the response. + page: The page number. + sort: The sorting order of the search result. + country_code: The filter for classifications by country code. + preferred_country: The popularity boost by country, default is us. + include_spellcheck: Indicates whether to include spell check + suggestions in the response. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/discovery/v2/classifications" @@ -1395,7 +1679,7 @@ async def classifications_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1409,6 +1693,7 @@ async def classifications_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1416,12 +1701,12 @@ async def classifications_get_async( return json.loads(response.text) - async def classification_get_async( + def classification_get( self, id: str, + *, locale: Optional[str] = None, domain: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1432,6 +1717,25 @@ async def classification_get_async( Get details for a specific segment, genre, or sub-genre using its unique identifier. + + Swagger operation ID: `ClassificationGet`. + + Args: + id: The unique identifier for the classification. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1462,7 +1766,7 @@ async def classification_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1476,6 +1780,7 @@ async def classification_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1483,12 +1788,12 @@ async def classification_get_async( return json.loads(response.text) - async def genre_get_async( + def genre_get( self, id: str, + *, locale: Optional[str] = None, domain: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1498,6 +1803,25 @@ async def genre_get_async( Get genre details Get details for a specific genre using its unique identifier. + + Swagger operation ID: `GenreGet`. + + Args: + id: The unique identifier for the genre. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1528,7 +1852,7 @@ async def genre_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1542,6 +1866,7 @@ async def genre_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1549,12 +1874,12 @@ async def genre_get_async( return json.loads(response.text) - async def segment_get_async( + def segment_get( self, id: str, + *, locale: Optional[str] = None, domain: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1564,6 +1889,25 @@ async def segment_get_async( Get segment details Get details for a specific segment using its unique identifier. + + Swagger operation ID: `SegmentGet`. + + Args: + id: The unique identifier for the segment. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1594,7 +1938,7 @@ async def segment_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1608,6 +1952,7 @@ async def segment_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1615,12 +1960,12 @@ async def segment_get_async( return json.loads(response.text) - async def sub_genre_get_async( + def sub_genre_get( self, id: str, + *, locale: Optional[str] = None, domain: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1630,6 +1975,25 @@ async def sub_genre_get_async( Get sub-genre details Get details for a specific sub-genre using its unique identifier. + + Swagger operation ID: `SubGenreGet`. + + Args: + id: The unique identifier for the sub-genre. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1664,7 +2028,7 @@ async def sub_genre_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1678,6 +2042,7 @@ async def sub_genre_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1685,8 +2050,9 @@ async def sub_genre_get_async( return json.loads(response.text) - async def venues_get_async( + def venues_get( self, + *, id: Optional[str] = None, keyword: Optional[str] = None, latlong: Optional[str] = None, @@ -1704,7 +2070,6 @@ async def venues_get_async( preferred_country: Optional[str] = None, include_spellcheck: Optional[str] = None, domain: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1714,6 +2079,45 @@ async def venues_get_async( Venue search Find venues and filter your search by name, and much more. + + Swagger operation ID: `VenuesGet`. + + Args: + id: The filter for entities by their identifier. + keyword: The keyword to search on. + latlong: The filter for venues by latitude and longitude. This + filter is deprecated and may be removed in a future release, + please use geoPoint instead. + radius: The radius of the area in which we want to search for + venues. + unit: The unit of the radius. + source: The filter for entities by their primary source name or + publishing source name. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + include_test: Indicates whether to include entities flagged as test + in the response. + size: The page size of the response. + page: The page number. + sort: The sorting order of the search result. + country_code: The filter for venues by country code. + state_code: The filter by state / province code. + geo_point: The filter for venues by geoHash. + preferred_country: The popularity boost by country, default is us. + include_spellcheck: Indicates whether to include spell check + suggestions in the response. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/discovery/v2/venues" query_params = [] @@ -1816,7 +2220,7 @@ async def venues_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1830,6 +2234,7 @@ async def venues_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1837,12 +2242,12 @@ async def venues_get_async( return json.loads(response.text) - async def venue_get_async( + def venue_get( self, id: str, + *, locale: Optional[str] = None, domain: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1853,6 +2258,25 @@ async def venue_get_async( Get details for a specific venue using the unique identifier for the venue. + + Swagger operation ID: `VenueGet`. + + Args: + id: The unique identifier for the venue. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1883,7 +2307,7 @@ async def venue_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1897,6 +2321,7 @@ async def venue_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1904,8 +2329,9 @@ async def venue_get_async( return json.loads(response.text) - async def suggestions_get_async( + def suggestions_get( self, + *, keyword: Optional[str] = None, latlong: Optional[str] = None, radius: Optional[str] = None, @@ -1925,7 +2351,6 @@ async def suggestions_get_async( local_start_end_date_time: Optional[List[str]] = None, include_spellcheck: Optional[str] = None, domain: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1936,6 +2361,54 @@ async def suggestions_get_async( Find search suggestions and filter your suggestions by location, source, etc. + + Swagger operation ID: `SuggestionsGet`. + + Args: + keyword: The keyword to search on. + latlong: The filter for events by latitude and longitude. This + filter is deprecated and may be removed in a future release, + please use geoPoint instead. + radius: The radius of the area in which we want to search for + events. + unit: The unit of the radius. + source: The filter for entities by their primary source name or + publishing source name. + locale: The locale in ISO code format. Multiple comma-separated + values can be provided. + include_t_b_a: Indicates whether to include events with date to be + announced (TBA). Defaults to no if date parameter sent, yes + otherwise. + include_t_b_d: Indicates whether to include events with a date to + be defined (TBD). Defaults to no if date parameter sent, yes + otherwise. + include_test: Indicates whether to include entities flagged as test + in the response. + size: Size of every entity returned in the response. + country_code: The filter suggestions by country code. + segment_id: The filter suggestions by segment identifier. + geo_point: The filter for events by geoHash. + resource: Which resources to include in the suggest response, + defaults to all resources. + preferred_country: The popularity boost by country, default is us. + start_end_date_time: The filter for events where event start and + end date overlap this range. + local_start_end_date_time: The filter for events where event local + start and end date overlap this range. + include_spellcheck: Indicates whether to include spell check + suggestions in the response. + domain: The filter for entities based on domains they are available + on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/discovery/v2/suggest" query_params = [] @@ -2088,7 +2561,7 @@ async def suggestions_get_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2102,6 +2575,7 @@ async def suggestions_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/todo.py b/src/azure/connectors/todo.py index 7e4bccd..e050874 100644 --- a/src/azure/connectors/todo.py +++ b/src/azure/connectors/todo.py @@ -5,21 +5,37 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "TodoClient", + "CreateToDo", + "CreateToDoBody", + "CreateToDoHtmlBody", + "CreateToDoList", + "CreateToDoListBody", + "ToDo", + "ToDoHtml", + "TodoList", + "UpdateToDo", + "UpdateToDoBody", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,19 +45,22 @@ class TodoList: Response for Update a to-do list """ - etag: Optional[str] = field( + etag: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.etag"}, ) - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the to-do list.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """Name of the to-do list.""" - wellknown_list_name: Optional[str] = field( + wellknown_list_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "wellknownListName"}, ) """ @@ -49,13 +68,15 @@ class TodoList: well-known list. Possible values are: none, defaultList, flaggedEmails, unknownFutureValue. """ - is_owner: Optional[bool] = field( + is_owner: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isOwner"}, ) """True if the user is owner of the given task list.""" - is_shared: Optional[bool] = field( + is_shared: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isShared"}, ) """True if the task list is shared with other users.""" @@ -67,61 +88,70 @@ class ToDo: Response for Add a to-do """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - etag: Optional[str] = field( + etag: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.etag"}, ) - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the to-do.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """YYYY-MM-DDThh:mm:ssZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """YYYY-MM-DDThh:mm:ssZ (UTC format)""" - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """To-do body that typically contains information about the to-do.""" - body_last_modified_date_time: Optional[str] = field( + body_last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "bodyLastModifiedDateTime"}, ) """YYYY-MM-DDThh:mm:ssZ (UTC format)""" - completed_date_time: Optional[Dict[str, Any]] = field( + completed_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "completedDateTime"}, ) """The date in the specified time zone that the task was finished.""" - due_date_time: Optional[Dict[str, Any]] = field( + due_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dueDateTime"}, ) """The date in the specified time zone that the task is to be finished.""" - importance: Optional[str] = None + importance: Optional[str] = dataclass_field(default=None, kw_only=True) """Low, normal or high.""" - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isReminderOn"}, ) """True if an alert is set to remind the user of the to-do.""" - reminder_date_time: Optional[Dict[str, Any]] = field( + reminder_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reminderDateTime"}, ) """The date and time for a reminder alert of the task to occur.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Indicates state or progress of the to-do - not started, in progress, completed, waiting on others or deferred. """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Brief description or title of the to-do.""" @@ -131,81 +161,93 @@ class ToDoHtml: Definition: ToDoHtml """ - context: Optional[str] = field( + context: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.context"}, ) - id_2: Optional[str] = field( + id_2: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.id"}, ) - etag: Optional[str] = field( + etag: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.etag"}, ) - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the to-do.""" - created_date_time: Optional[str] = field( + created_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdDateTime"}, ) """YYYY-MM-DDThh:mm:ssZ (UTC format)""" - last_modified_date_time: Optional[str] = field( + last_modified_date_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastModifiedDateTime"}, ) """YYYY-MM-DDThh:mm:ssZ (UTC format)""" - categories: Optional[List[str]] = None + categories: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """Collection of category names associated with the to-do.""" - assigned_to: Optional[str] = field( + assigned_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignedTo"}, ) """Name of the person who has been assigned the to-do.""" - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """To-do body that typically contains information about the to-do.""" - completed_date_time: Optional[Dict[str, Any]] = field( + completed_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "completedDateTime"}, ) """Date-time in the UTC time zone when the to-do was finished.""" - due_date_time: Optional[Dict[str, Any]] = field( + due_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dueDateTime"}, ) """Date in the UTC time zone when the to-do is to be finished.""" - importance: Optional[str] = None + importance: Optional[str] = dataclass_field(default=None, kw_only=True) """Low, normal or high.""" - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isReminderOn"}, ) """True if an alert is set to remind the user of the to-do.""" - owner: Optional[str] = None + owner: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the person who created the to-do.""" - parent_folder_id: Optional[str] = field( + parent_folder_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "parentFolderId"}, ) """Unique identifier of the parent folder.""" - reminder_date_time: Optional[Dict[str, Any]] = field( + reminder_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reminderDateTime"}, ) """ Date-time in the UTC time zone for a reminder alert of the to-do to occur. """ - start_date_time: Optional[Dict[str, Any]] = field( + start_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startDateTime"}, ) """Date in the UTC time zone when the to-do is to begin.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Indicates state or progress of the to-do - not started, in progress, completed, waiting on others or deferred. """ - subject: Optional[str] = None + subject: Optional[str] = dataclass_field(default=None, kw_only=True) """Brief description or title of the to-do.""" @@ -215,58 +257,64 @@ class CreateToDoBody: Definition: CreateToDoBody """ - due_date_time: Optional[Dict[str, Any]] = field( + due_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DueDateTime"}, ) """Date in the UTC time zone when the to-do is to be finished.""" - reminder_date_time: Optional[Dict[str, Any]] = field( + reminder_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReminderDateTime"}, ) """ Date-time in UTC time zone for a reminder alert of the to-do to occur. """ - start_date_time: Optional[Dict[str, Any]] = field( + start_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartDateTime"}, ) """Date in the UTC time zone when the to-do is to begin.""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Low, normal or high.""" - subject: Optional[str] = field( - default=None, - metadata={"wire_name": "Subject"}, - ) + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) """Brief description or title of the to-do.""" - status: Optional[str] = field( + status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Status"}, ) """ Indicates state or progress of the to-do - not started, in progress, completed, waiting on others or deferred. """ - sensitivity: Optional[str] = field( + sensitivity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sensitivity"}, ) """Indicates the level of privacy for the event.""" - body: Optional[Dict[str, Any]] = field( + body: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Body"}, ) """To-do body that typically contains information about the to-do.""" - categories: Optional[List[str]] = field( + categories: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Categories"}, ) """Collection of category names associated with the to-do.""" - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsReminderOn"}, ) """True if an alert is set to remind the user of the to-do.""" @@ -278,58 +326,64 @@ class CreateToDoHtmlBody: Definition: CreateToDoHtmlBody """ - due_date_time: Optional[Dict[str, Any]] = field( + due_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DueDateTime"}, ) """Date in the UTC time zone when the to-do is to be finished.""" - reminder_date_time: Optional[Dict[str, Any]] = field( + reminder_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReminderDateTime"}, ) """ Date-time in UTC time zone for a reminder alert of the to-do to occur. """ - start_date_time: Optional[Dict[str, Any]] = field( + start_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartDateTime"}, ) """Date in the UTC time zone when the to-do is to begin.""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Low, normal or high.""" - subject: Optional[str] = field( - default=None, - metadata={"wire_name": "Subject"}, - ) + subject: str = dataclass_field(metadata={"wire_name": "Subject"}) """Brief description or title of the to-do.""" - status: Optional[str] = field( + status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Status"}, ) """ Indicates state or progress of the to-do - not started, in progress, completed, waiting on others or deferred. """ - sensitivity: Optional[str] = field( + sensitivity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sensitivity"}, ) """Indicates the level of privacy for the event.""" - body: Optional[Dict[str, Any]] = field( + body: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Body"}, ) """To-do body that typically contains information about the to-do.""" - categories: Optional[List[str]] = field( + categories: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Categories"}, ) """Collection of category names associated with the to-do.""" - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsReminderOn"}, ) """True if an alert is set to remind the user of the to-do.""" @@ -341,58 +395,68 @@ class UpdateToDoBody: Definition: UpdateToDoBody """ - due_date_time: Optional[Dict[str, Any]] = field( + due_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DueDateTime"}, ) """Date in the UTC time zone when the to-do is to be finished.""" - reminder_date_time: Optional[Dict[str, Any]] = field( + reminder_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ReminderDateTime"}, ) """ Date-time in UTC time zone for a reminder alert of the to-do to occur. """ - start_date_time: Optional[Dict[str, Any]] = field( + start_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StartDateTime"}, ) """Date in the UTC time zone when the to-do is to begin.""" - importance: Optional[str] = field( + importance: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Importance"}, ) """Low, normal or high.""" - subject: Optional[str] = field( + subject: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subject"}, ) """Brief description or title of the to-do.""" - status: Optional[str] = field( + status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Status"}, ) """ Indicates state or progress of the to-do - not started, in progress, completed, waiting on others or deferred. """ - sensitivity: Optional[str] = field( + sensitivity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Sensitivity"}, ) """Indicates the level of privacy for the event.""" - body: Optional[Dict[str, Any]] = field( + body: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Body"}, ) """To-do body that typically contains information about the to-do.""" - categories: Optional[List[str]] = field( + categories: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Categories"}, ) """Collection of category names associated with the to-do.""" - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsReminderOn"}, ) """True if an alert is set to remind the user of the to-do.""" @@ -404,7 +468,7 @@ class CreateToDoListBody: Definition: CreateToDoListBody """ - name: Optional[str] = None + name: str """List name""" @@ -414,34 +478,37 @@ class CreateToDo: Definition: CreateToDo """ - due_date_time: Optional[Dict[str, Any]] = field( + due_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dueDateTime"}, ) """ Date in the UTC time zone when the to-do is to be finished (note the time portion will be ignored). """ - reminder_date_time: Optional[Dict[str, Any]] = field( + reminder_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reminderDateTime"}, ) """ Date-time in UTC time zone for a reminder alert of the to-do to occur. """ - importance: Optional[str] = None + importance: Optional[str] = dataclass_field(default=None, kw_only=True) """Low, normal or high.""" - title: Optional[str] = None + title: str """Brief description or title of the to-do.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Indicates state or progress of the to-do - not started, in progress, completed, waiting on others or deferred. """ - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """To-do body that typically contains information about the to-do.""" - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isReminderOn"}, ) """True if an alert is set to remind the user of the to-do.""" @@ -453,34 +520,37 @@ class UpdateToDo: Definition: UpdateToDo """ - due_date_time: Optional[Dict[str, Any]] = field( + due_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dueDateTime"}, ) """ Date in the UTC time zone when the to-do is to be finished (note the time portion will be ignored). """ - reminder_date_time: Optional[Dict[str, Any]] = field( + reminder_date_time: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "reminderDateTime"}, ) """ Date-time in UTC time zone for a reminder alert of the to-do to occur. """ - importance: Optional[str] = None + importance: Optional[str] = dataclass_field(default=None, kw_only=True) """Low, normal or high.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Brief description or title of the to-do.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """ Indicates state or progress of the to-do - not started, in progress, completed, waiting on others or deferred. """ - body: Optional[Dict[str, Any]] = None + body: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """To-do body that typically contains information about the to-do.""" - is_reminder_on: Optional[bool] = field( + is_reminder_on: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isReminderOn"}, ) """True if an alert is set to remind the user of the to-do.""" @@ -492,10 +562,7 @@ class CreateToDoList: Definition: CreateToDoList """ - display_name: Optional[str] = field( - default=None, - metadata={"wire_name": "displayName"}, - ) + display_name: str = dataclass_field(metadata={"wire_name": "displayName"}) """List name""" @@ -507,16 +574,16 @@ class TodoClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -527,8 +594,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -536,8 +603,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -549,7 +616,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -564,9 +631,48 @@ def __init__( def connector_name(self) -> str: return "todo" - async def update_to_do_list_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def update_to_do_list( self, - input: CreateToDoList, + input: CreateToDoList | Mapping[str, Any], folder_id: str, *, timeout: Optional[float] = None, @@ -578,13 +684,30 @@ async def update_to_do_list_async( Update a to-do list This operation is used to update a specific to-do list. + + Swagger operation ID: `UpdateToDoList`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + folder_id: To-do list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/lists/{quote(str(folder_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -598,6 +721,7 @@ async def update_to_do_list_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -605,7 +729,7 @@ async def update_to_do_list_async( return json.loads(response.text) - async def delete_to_do_list_async( + def delete_to_do_list( self, folder_id: str, *, @@ -618,13 +742,28 @@ async def delete_to_do_list_async( Delete a to-do list This operation is used to delete a specific to-do list. + + Swagger operation ID: `DeleteToDoList`. + + Args: + folder_id: To-do list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/lists/{quote(str(folder_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -638,11 +777,12 @@ async def delete_to_do_list_async( request_url, response.status, response.text, + response=response, ) - async def create_to_do_async( + def create_to_do( self, - input: CreateToDo, + input: CreateToDo | Mapping[str, Any], folder_id: str, *, timeout: Optional[float] = None, @@ -654,13 +794,30 @@ async def create_to_do_async( Add a to-do This operation is used to create a to-do in the specified to-do list. + + Swagger operation ID: `CreateToDoV3`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + folder_id: To-do list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/lists/{quote(str(folder_id), safe='')}/tasks" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -674,6 +831,7 @@ async def create_to_do_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -681,9 +839,9 @@ async def create_to_do_async( return json.loads(response.text) - async def create_to_do_list_async( + def create_to_do_list( self, - input: CreateToDoList, + input: CreateToDoList | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -694,10 +852,26 @@ async def create_to_do_list_async( Create a to-do list This operation is used to create a new to-do list. + + Swagger operation ID: `CreateToDoListV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/lists" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -711,6 +885,7 @@ async def create_to_do_list_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -718,7 +893,7 @@ async def create_to_do_list_async( return json.loads(response.text) - async def delete_to_do_async( + def delete_to_do( self, folder_id: str, id: str, @@ -732,6 +907,22 @@ async def delete_to_do_async( Delete to-do This operation is used to delete a task. + + Swagger operation ID: `DeleteToDoV2`. + + Args: + folder_id: To-do list. + id: To-do task. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -741,7 +932,7 @@ async def delete_to_do_async( f"/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -755,45 +946,85 @@ async def delete_to_do_async( request_url, response.status, response.text, + response=response, ) - async def get_all_todo_lists_async( + def list_all_todo_lists( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List all to-do lists Returns a list of all the to-do lists. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAllTodoListsV2`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/lists" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def get_to_do_async( + return ItemPaged(get_next, extract_data) + + def get_to_do( self, folder_id: str, id: str, @@ -807,6 +1038,22 @@ async def get_to_do_async( Get a to-do This operation is used to get the to-do with the given Id. + + Swagger operation ID: `GetToDoV3`. + + Args: + folder_id: To-do list. + id: To-do task. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -816,7 +1063,7 @@ async def get_to_do_async( f"/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -830,6 +1077,7 @@ async def get_to_do_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -837,7 +1085,7 @@ async def get_to_do_async( return json.loads(response.text) - async def get_to_do_list_async( + def get_to_do_list( self, folder_id: str, *, @@ -850,13 +1098,28 @@ async def get_to_do_list_async( Get a to-do list This operation is used to get a specific to-do list. + + Swagger operation ID: `GetToDoListV2`. + + Args: + folder_id: To-do list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/lists/{quote(str(folder_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -870,6 +1133,7 @@ async def get_to_do_list_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -877,20 +1141,41 @@ async def get_to_do_list_async( return json.loads(response.text) - async def list_to_dos_by_folder_async( + def list_to_dos_by_folder( self, folder_id: str, - top: Optional[int] = None, *, + top: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List to-dos by folder This operation is used to retrieve all to-dos from a specific list. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListToDosByFolderV2`. + + Args: + folder_id: To-do list. + top: Total number of entries to retrieve (default = 10, maximum = + 999). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -904,31 +1189,52 @@ async def list_to_dos_by_folder_async( query_params.append(f"$top={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def update_to_do_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def update_to_do( self, - input: UpdateToDo, + input: UpdateToDo | Mapping[str, Any], folder_id: str, id: str, *, @@ -941,6 +1247,24 @@ async def update_to_do_async( Update to-do This operation is used to update a specific to-do. + + Swagger operation ID: `UpdateToDoV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + folder_id: To-do list. + id: To-do task. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -950,7 +1274,7 @@ async def update_to_do_async( f"/{quote(str(id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -964,6 +1288,7 @@ async def update_to_do_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/trello.py b/src/azure/connectors/trello.py index e75242a..3da48de 100644 --- a/src/azure/connectors/trello.py +++ b/src/azure/connectors/trello.py @@ -5,21 +5,57 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List as TypingList, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List as TypingList, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "TrelloClient", + "Badges", + "Board", + "BoardLabel", + "BoardWithChecklists", + "Card", + "CardInAction", + "CardWithChecklists", + "CheckItemState", + "Checkitem", + "Checklist", + "ClientSubscription", + "Comment", + "CommentPost", + "CreateBoard", + "CreateCard", + "CreateList", + "CreateListResponse", + "Label", + "List", + "Member", + "Membership", + "ObjectEntity", + "Perfs", + "SubscriptionPayload", + "SubscriptionResponse", + "Team", + "TeamPreferences", + "UpdateBoard", + "UpdateCard", + "Webhook", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,88 +65,104 @@ class Card: Response for List the cards in a board """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique id of the card.""" - check_item_states: Optional[TypingList[CheckItemState]] = field( + check_item_states: Optional[TypingList[CheckItemState | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "checkItemStates"}, ) """The check item states in the card.""" - closed: Optional[bool] = None + closed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not the card is closed. """ - date_last_activity: Optional[str] = field( + date_last_activity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dateLastActivity"}, ) """The datetime of last activity on the card.""" - desc: Optional[str] = None + desc: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the card.""" - id_board: Optional[str] = field( + id_board: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idBoard"}, ) """The unique Id of the board which the card belongs to.""" - id_list: Optional[str] = field( + id_list: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idList"}, ) """The unique Id of the list which the card belongs to.""" - id_members_voted: Optional[TypingList[str]] = field( + id_members_voted: Optional[TypingList[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idMembersVoted"}, ) """The unique Ids of the voting members.""" - id_short: Optional[int] = field( + id_short: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idShort"}, ) """The short Id of the card.""" - id_attachment_cover: Optional[str] = field( + id_attachment_cover: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idAttachmentCover"}, ) """The unique Id of the attachment cover.""" - manual_cover_attachment: Optional[bool] = field( + manual_cover_attachment: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "manualCoverAttachment"}, ) """ A boolean value (true, false) determining whether or not the card has a manual cover attachment. """ - id_labels: Optional[TypingList[str]] = field( + id_labels: Optional[TypingList[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idLabels"}, ) """A list of label Ids on the card.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the card.""" - pos: Optional[float] = None + pos: Optional[float] = dataclass_field(default=None, kw_only=True) """The position of the card.""" - short_link: Optional[str] = field( + short_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shortLink"}, ) """A short link to the card.""" - badges: Optional[Badges] = None - due: Optional[str] = None + badges: Optional[Badges | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + due: Optional[str] = dataclass_field(default=None, kw_only=True) """The due date of the card.""" - short_url: Optional[str] = field( + short_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shortUrl"}, ) """The short url link to the card.""" - subscribed: Optional[bool] = None + subscribed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not the card is subscribed to. """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The full url to the card.""" - checklists: Optional[TypingList[Checklist]] = None + checklists: Optional[ + TypingList[Checklist | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The set of board checklists.""" @@ -120,88 +172,104 @@ class CardWithChecklists: Response for Get a card by id """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique id of the card.""" - check_item_states: Optional[TypingList[CheckItemState]] = field( + check_item_states: Optional[TypingList[CheckItemState | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "checkItemStates"}, ) """The check item states in the card.""" - closed: Optional[bool] = None + closed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not the card is closed. """ - date_last_activity: Optional[str] = field( + date_last_activity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dateLastActivity"}, ) """The datetime of last activity on the card.""" - desc: Optional[str] = None + desc: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the card.""" - id_board: Optional[str] = field( + id_board: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idBoard"}, ) """The unique Id of the board which the card belongs to.""" - id_list: Optional[str] = field( + id_list: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idList"}, ) """The unique Id of the list which the card belongs to.""" - id_members_voted: Optional[TypingList[str]] = field( + id_members_voted: Optional[TypingList[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idMembersVoted"}, ) """The unique Ids of the voting members.""" - id_short: Optional[int] = field( + id_short: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idShort"}, ) """The short Id of the card.""" - id_attachment_cover: Optional[str] = field( + id_attachment_cover: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idAttachmentCover"}, ) """The unique Id of the attachment cover.""" - manual_cover_attachment: Optional[bool] = field( + manual_cover_attachment: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "manualCoverAttachment"}, ) """ A boolean value (true, false) determining whether or not the card has a manual cover attachment. """ - id_labels: Optional[TypingList[str]] = field( + id_labels: Optional[TypingList[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idLabels"}, ) """A list of label Ids on the card.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the card.""" - pos: Optional[float] = None + pos: Optional[float] = dataclass_field(default=None, kw_only=True) """The position of the card.""" - short_link: Optional[str] = field( + short_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shortLink"}, ) """A short link to the card.""" - badges: Optional[Badges] = None - due: Optional[str] = None + badges: Optional[Badges | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + due: Optional[str] = dataclass_field(default=None, kw_only=True) """The due date of the card.""" - short_url: Optional[str] = field( + short_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shortUrl"}, ) """The short url link to the card.""" - subscribed: Optional[bool] = None + subscribed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not the card is subscribed to. """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The full url to the card.""" - checklists: Optional[TypingList[Checklist]] = None + checklists: Optional[ + TypingList[Checklist | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The set of card checklists.""" @@ -211,7 +279,7 @@ class ObjectEntity: Response for Delete a card """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -224,73 +292,85 @@ class Board: Response for List boards """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique Id of the board.""" - closed: Optional[bool] = None + closed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not the board is closed. """ - date_last_activity: Optional[str] = field( + date_last_activity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dateLastActivity"}, ) """Date of the last activity on the board.""" - date_last_view: Optional[str] = field( + date_last_view: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dateLastView"}, ) """Date of the last time the board is viewed.""" - desc: Optional[str] = None + desc: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the board.""" - id_organization: Optional[str] = field( + id_organization: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idOrganization"}, ) """The id of the organization.""" - invitations: Optional[TypingList[str]] = None + invitations: Optional[TypingList[str]] = dataclass_field(default=None, kw_only=True) """The list of invitations on the board.""" - invited: Optional[bool] = None + invited: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not the account is invited to the board. """ - label_names: Optional[Label] = field( + label_names: Optional[Label | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "labelNames"}, ) - memberships: Optional[TypingList[Membership]] = None + memberships: Optional[ + TypingList[Membership | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The set of board memberships.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the board.""" - pinned: Optional[bool] = None + pinned: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not the board is pinned. """ - power_ups: Optional[TypingList[str]] = field( + power_ups: Optional[TypingList[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "powerUps"}, ) """The set of power ups on the board.""" - perfs: Optional[Perfs] = None - short_link: Optional[str] = field( + perfs: Optional[Perfs | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + short_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shortLink"}, ) """The short link of the board.""" - short_url: Optional[str] = field( + short_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shortUrl"}, ) """The short url to the board.""" - starred: Optional[bool] = None + starred: Optional[bool] = dataclass_field(default=None, kw_only=True) """A value determining whether or not the board is starred.""" - subscribed: Optional[bool] = None + subscribed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A value determining whether or not the account is subscribed to the board. """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The full url of the board.""" @@ -300,75 +380,92 @@ class BoardWithChecklists: Response for Get a board by Id """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique Id of the board.""" - closed: Optional[bool] = None + closed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not the board is closed. """ - date_last_activity: Optional[str] = field( + date_last_activity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dateLastActivity"}, ) """Date of the last activity on the board.""" - date_last_view: Optional[str] = field( + date_last_view: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dateLastView"}, ) """Date of the last time the board is viewed.""" - desc: Optional[str] = None + desc: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the board.""" - id_organization: Optional[str] = field( + id_organization: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idOrganization"}, ) """The id of the organization.""" - invitations: Optional[TypingList[str]] = None + invitations: Optional[TypingList[str]] = dataclass_field(default=None, kw_only=True) """The list of invitations on the board.""" - invited: Optional[bool] = None + invited: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not the account is invited to the board. """ - label_names: Optional[Label] = field( + label_names: Optional[Label | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "labelNames"}, ) - memberships: Optional[TypingList[Membership]] = None + memberships: Optional[ + TypingList[Membership | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The set of board memberships.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the board.""" - pinned: Optional[bool] = None + pinned: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not the board is pinned. """ - power_ups: Optional[TypingList[str]] = field( + power_ups: Optional[TypingList[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "powerUps"}, ) """The set of power ups on the board.""" - perfs: Optional[Perfs] = None - short_link: Optional[str] = field( + perfs: Optional[Perfs | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + short_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shortLink"}, ) """The short link of the board.""" - short_url: Optional[str] = field( + short_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shortUrl"}, ) """The short url to the board.""" - starred: Optional[bool] = None + starred: Optional[bool] = dataclass_field(default=None, kw_only=True) """A value determining whether or not the board is starred.""" - subscribed: Optional[bool] = None + subscribed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A value determining whether or not the account is subscribed to the board. """ - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The full url of the board.""" - checklists: Optional[TypingList[Checklist]] = None + checklists: Optional[ + TypingList[Checklist | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The set of board checklists.""" @@ -378,30 +475,36 @@ class List: Response for List the card lists in a board """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique Id of the list.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the list.""" - closed: Optional[bool] = None + closed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not the list is closed. """ - id_board: Optional[str] = field( + id_board: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idBoard"}, ) """The unique Id of the board which the list belongs to.""" - pos: Optional[float] = None + pos: Optional[float] = dataclass_field(default=None, kw_only=True) """The position of the list.""" - subscribed: Optional[bool] = None + subscribed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not to the account is subscribed to the list. """ - cards: Optional[TypingList[Card]] = None + cards: Optional[ + TypingList[Card | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The cards inside the list.""" - board: Optional[Board] = None + board: Optional[Board | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -410,16 +513,13 @@ class CreateListResponse: Response for Update a list """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique Id of the list.""" - name: Optional[str] = None + name: str """The name of the list.""" - id_board: Optional[str] = field( - default=None, - metadata={"wire_name": "idBoard"}, - ) + id_board: str = dataclass_field(metadata={"wire_name": "idBoard"}) """The unique Id of the board the list belongs to.""" - pos: Optional[float] = None + pos: Optional[float] = dataclass_field(default=None, kw_only=True) """The position of the list.""" @@ -429,33 +529,47 @@ class Team: Response for List teams you are a member of """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the team.""" - desc: Optional[str] = None + desc: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the team.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """The display name of the team.""" - id_boards: Optional[TypingList[str]] = field( + id_boards: Optional[TypingList[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idBoards"}, ) """The boards assigned to this team.""" - billable_member_count: Optional[int] = field( + billable_member_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "billableMemberCount"}, ) """The number of members in this team.""" - memberships: Optional[TypingList[Membership]] = None + memberships: Optional[ + TypingList[Membership | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The memberships for this team.""" - web_site: Optional[str] = field( + web_site: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "WebSite"}, ) """The team website.""" - prefs: Optional[TeamPreferences] = None + prefs: Optional[ + TeamPreferences | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -464,16 +578,17 @@ class Member: Response for List members of a team """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique Id of the member.""" - full_name: Optional[str] = field( + full_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fullName"}, ) """The full name of the member.""" - username: Optional[str] = None + username: Optional[str] = dataclass_field(default=None, kw_only=True) """The username of the member.""" - initials: Optional[str] = None + initials: Optional[str] = dataclass_field(default=None, kw_only=True) """The initials of the member.""" @@ -483,11 +598,11 @@ class BoardLabel: Response for List labels of a board """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The Label Id""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The Label name.""" - color: Optional[str] = None + color: Optional[str] = dataclass_field(default=None, kw_only=True) """The Label color.""" @@ -497,13 +612,14 @@ class Comment: Response for List comments for a card """ - member_creator: Optional[Member] = field( + member_creator: Optional[Member | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "memberCreator"}, ) - text: Optional[str] = None + text: Optional[str] = dataclass_field(default=None, kw_only=True) """The text of the comment.""" - date: Optional[str] = None + date: Optional[str] = dataclass_field(default=None, kw_only=True) """The datetime the comment was left.""" @@ -513,21 +629,23 @@ class CardInAction: Response for When a new card is added to a board """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique id of the card.""" - id_short: Optional[int] = field( + id_short: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idShort"}, ) """The short Id of the card.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the card.""" - short_link: Optional[str] = field( + short_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shortLink"}, ) """A short link to the card.""" - due: Optional[str] = None + due: Optional[str] = dataclass_field(default=None, kw_only=True) """The due date of the card.""" @@ -537,12 +655,13 @@ class CheckItemState: Definition: CheckItemState """ - id_check_item: Optional[str] = field( + id_check_item: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idCheckItem"}, ) """ID of the check item.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """State of the check item.""" @@ -552,55 +671,71 @@ class Badges: Definition: Badges """ - votes: Optional[int] = field(default=None, metadata={"wire_name": "Votes"}) + votes: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Votes"}, + ) """The number of votes on the card badges.""" - viewing_member_voted: Optional[bool] = field( + viewing_member_voted: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ViewingMemberVoted"}, ) """ A boolean value (true, false) determining whether or not viewing members voted on the badge. """ - subscribed: Optional[bool] = field( + subscribed: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Subscribed"}, ) """ A boolean value (true, false) determining whether or not the account is subscribed to the card badges. """ - fogbugz: Optional[str] = field( + fogbugz: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Fogbugz"}, ) """The fogbugz of the badges.""" - check_items: Optional[int] = field( + check_items: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckItems"}, ) """The number of check items in the badge.""" - check_items_checked: Optional[int] = field( + check_items_checked: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CheckItemsChecked"}, ) """The number of checked check items in the badge.""" - comments: Optional[int] = field( + comments: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Comments"}, ) """The comments on the badge.""" - attachments: Optional[int] = field( + attachments: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Attachments"}, ) """The attachments on the badge.""" - description: Optional[bool] = field( + description: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Description"}, ) """The description of the badge.""" - due: Optional[str] = field(default=None, metadata={"wire_name": "Due"}) + due: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Due"}, + ) """The due date of the badge.""" @@ -610,44 +745,48 @@ class UpdateCard: Definition: UpdateCard """ - name: Optional[str] = None + name: str """The updated name of the new card.""" - desc: Optional[str] = None + desc: Optional[str] = dataclass_field(default=None, kw_only=True) """The updated description of the new card.""" - closed: Optional[bool] = None + closed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not the card is closed. """ - id_members_array: Optional[TypingList[str]] = field( + id_members_array: Optional[TypingList[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idMembersArray"}, ) """An array of member Ids to attach to the card.""" - id_attachment_cover: Optional[str] = field( + id_attachment_cover: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idAttachmentCover"}, ) """The id of the attachment to attach to the card.""" - id_board: Optional[str] = field( + id_board: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idBoard"}, ) """The id of the board to attach the card to.""" - id_list: Optional[str] = field( + id_list: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idList"}, ) """The id of the list to attach the card to.""" - pos: Optional[str] = None + pos: Optional[str] = dataclass_field(default=None, kw_only=True) """ The position of the card on the page. Specify top, bottom, or a positive number. Note this is used in relation to existing card locations so the resulting location may not match the exact value provided. """ - due: Optional[str] = None + due: Optional[str] = dataclass_field(default=None, kw_only=True) """The due date of the card.""" - subscribed: Optional[bool] = None + subscribed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not to subscribe to the card. @@ -660,55 +799,58 @@ class CreateCard: Definition: CreateCard """ - id_list: Optional[str] = field( - default=None, - metadata={"wire_name": "idList"}, - ) + id_list: str = dataclass_field(metadata={"wire_name": "idList"}) """The id of the list that the card should be added to.""" - name: Optional[str] = None + name: str """The name of the new card.""" - desc: Optional[str] = None + desc: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the new card.""" - pos: Optional[str] = None + pos: Optional[str] = dataclass_field(default=None, kw_only=True) """ The position of the card. Specify top, bottom, or a positive number. Note this is used in relation to existing card locations so the resulting location may not match the exact value provided. """ - id_members_array: Optional[TypingList[str]] = field( + id_members_array: Optional[TypingList[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idMembersArray"}, ) """An array of member Ids to attach to the card.""" - id_labels_array: Optional[TypingList[str]] = field( + id_labels_array: Optional[TypingList[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idLabelsArray"}, ) """An array of label Ids to attach to the card.""" - url_source: Optional[str] = field( + url_source: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlSource"}, ) """ Source url of the card. Has to be a URL starting with http:// or https:// or null. """ - file_source: Optional[str] = field( + file_source: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fileSource"}, ) """Source file of the card.""" - id_card_source: Optional[str] = field( + id_card_source: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idCardSource"}, ) """The Id of the card to copy into a new card.""" - keep_from_source: Optional[str] = field( + keep_from_source: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "keepFromSource"}, ) """Properties of the card to copy over from the source.""" - due: Optional[str] = None + due: Optional[str] = dataclass_field(default=None, kw_only=True) """The due date of the card.""" @@ -718,25 +860,25 @@ class Label: Definition: Label """ - green: Optional[str] = None + green: Optional[str] = dataclass_field(default=None, kw_only=True) """The value of the green label.""" - yellow: Optional[str] = None + yellow: Optional[str] = dataclass_field(default=None, kw_only=True) """The value of the yellow label.""" - orange: Optional[str] = None + orange: Optional[str] = dataclass_field(default=None, kw_only=True) """The value of the orange label.""" - red: Optional[str] = None + red: Optional[str] = dataclass_field(default=None, kw_only=True) """The value of the red label.""" - purple: Optional[str] = None + purple: Optional[str] = dataclass_field(default=None, kw_only=True) """The value of the purple label.""" - blue: Optional[str] = None + blue: Optional[str] = dataclass_field(default=None, kw_only=True) """The value of the blue label.""" - sky: Optional[str] = None + sky: Optional[str] = dataclass_field(default=None, kw_only=True) """The value of the sky blue label.""" - lime: Optional[str] = None + lime: Optional[str] = dataclass_field(default=None, kw_only=True) """The value of the lime green label.""" - pink: Optional[str] = None + pink: Optional[str] = dataclass_field(default=None, kw_only=True) """The value of the pink label.""" - black: Optional[str] = None + black: Optional[str] = dataclass_field(default=None, kw_only=True) """The value of the black label.""" @@ -746,19 +888,21 @@ class Membership: Definition: Membership """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique Id of the membership.""" - id_member: Optional[str] = field( + id_member: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idMember"}, ) """The unique Id of the member.""" - member_type: Optional[str] = field( + member_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "memberType"}, ) """The type of member.""" - unconfirmed: Optional[bool] = None + unconfirmed: Optional[bool] = dataclass_field(default=None, kw_only=True) """ A boolean value (true, false) determining whether or not the membership is unconfirmed. @@ -771,94 +915,107 @@ class Perfs: Definition: Perfs """ - permission_level: Optional[str] = field( + permission_level: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "permissionLevel"}, ) """The permission level of the object.""" - voting: Optional[str] = None + voting: Optional[str] = dataclass_field(default=None, kw_only=True) """Who can vote on the object.""" - comments: Optional[str] = None + comments: Optional[str] = dataclass_field(default=None, kw_only=True) """Who can comment on the object.""" - invitations: Optional[str] = None + invitations: Optional[str] = dataclass_field(default=None, kw_only=True) """Who can invite people to the object.""" - self_join: Optional[bool] = field( + self_join: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selfJoin"}, ) """ A boolean value (true, false) determining whether or not the object can self join. """ - card_covers: Optional[bool] = field( + card_covers: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "cardCovers"}, ) """ A boolean value (true, false) determining whether or not the object has access to card covers. """ - calendar_feed_enabled: Optional[bool] = field( + calendar_feed_enabled: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "calendarFeedEnabled"}, ) """ A boolean value (true, false) determining whether or not the calendar feed enabled. """ - background: Optional[str] = None + background: Optional[str] = dataclass_field(default=None, kw_only=True) """The background of the object.""" - background_color: Optional[str] = field( + background_color: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "backgroundColor"}, ) """The background color of the object, in hex notation.""" - background_image: Optional[str] = field( + background_image: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "backgroundImage"}, ) """The background image of the object.""" - background_image_scaled: Optional[str] = field( + background_image_scaled: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "backgroundImageScaled"}, ) """The scaled version of the background image.""" - background_tile: Optional[bool] = field( + background_tile: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "backgroundTile"}, ) """The background tile of the object.""" - background_brightness: Optional[str] = field( + background_brightness: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "backgroundBrightness"}, ) """The brightness of the object background.""" - can_be_public: Optional[bool] = field( + can_be_public: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "canBePublic"}, ) """ A boolean value (true, false) determining whether or not the object can be public. """ - can_be_org: Optional[bool] = field( + can_be_org: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "canBeOrg"}, ) """ A boolean value (true, false) determining whether or not the object can be part of the organization """ - can_be_private: Optional[bool] = field( + can_be_private: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "canBePrivate"}, ) """ A boolean value (true, false) determining whether or not the object can be private. """ - can_invite: Optional[bool] = field( + can_invite: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "canInvite"}, ) """ @@ -873,52 +1030,57 @@ class UpdateBoard: Definition: UpdateBoard """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the board.""" - default_lists: Optional[str] = field( + default_lists: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "defaultLists"}, ) """ A string (true, false) determining whether or not to create default lists. """ - desc: Optional[str] = None + desc: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the board.""" - id_organization: Optional[str] = field( + id_organization: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idOrganization"}, ) """The id of the team.""" - prefs_permission_level: Optional[str] = field( + prefs_permission_level: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "prefs_permissionLevel"}, ) """The permission level of the board.""" - prefs_comments: Optional[str] = None + prefs_comments: Optional[str] = dataclass_field(default=None, kw_only=True) """ The comment preferences on the board. Valid options are 'disabled', 'members', 'observers', 'org' or 'public'. """ - prefs_invitations: Optional[str] = None + prefs_invitations: Optional[str] = dataclass_field(default=None, kw_only=True) """ The invitation preferences of the board. Valid options are 'admins' or 'members'. """ - prefs_card_covers: Optional[str] = field( + prefs_card_covers: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "prefs_cardCovers"}, ) """A string (true, false) determining whether or not to use card covers.""" - prefs_background: Optional[str] = None + prefs_background: Optional[str] = dataclass_field(default=None, kw_only=True) """The background color of the board.""" - prefs_voting: Optional[str] = None + prefs_voting: Optional[str] = dataclass_field(default=None, kw_only=True) """The voting power-up preferences of the board.""" - prefs_card_aging: Optional[str] = field( + prefs_card_aging: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "prefs_cardAging"}, ) """The card aging power-up preferences of the board.""" - enable_calendar: Optional[str] = None + enable_calendar: Optional[str] = dataclass_field(default=None, kw_only=True) """ A string (true, false) determining whether or not to enable calendar power-up @@ -931,8 +1093,9 @@ class TeamPreferences: Definition: TeamPreferences """ - permission_level: Optional[str] = field( + permission_level: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "permissionLevel"}, ) """The permission level of the team.""" @@ -944,29 +1107,33 @@ class Webhook: Definition: Webhook """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique Id of the webhook.""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Brief Description of the webhook""" - id_model: Optional[str] = field( + id_model: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idModel"}, ) """ID of the model to be monitored (i.e. card,board, etc.)""" - callback_u_r_l: Optional[str] = field( + callback_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "callbackURL"}, ) """The callbackURL to receive webhook notifications""" - active: Optional[bool] = None + active: Optional[bool] = dataclass_field(default=None, kw_only=True) """Determines whether the webhook is active and sending POST requests.""" - consecutive_failures: Optional[float] = field( + consecutive_failures: Optional[float] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "consecutiveFailures"}, ) """The number of consecutive Failures in posting webhook notifications.""" - first_consecutive_fail_date: Optional[str] = field( + first_consecutive_fail_date: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "firstConsecutiveFailDate"}, ) """The date of First Consecutive Failure.""" @@ -978,7 +1145,7 @@ class CommentPost: Definition: CommentPost """ - text: Optional[str] = None + text: Optional[str] = dataclass_field(default=None, kw_only=True) """The text of the comment.""" @@ -988,49 +1155,54 @@ class CreateBoard: Definition: CreateBoard """ - name: Optional[str] = None + name: str """The name of the board.""" - default_lists: Optional[str] = field( + default_lists: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "defaultLists"}, ) """ A string (true, false) determining whether or not to create default lists. """ - desc: Optional[str] = None + desc: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the board.""" - id_organization: Optional[str] = field( + id_organization: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idOrganization"}, ) """The id of the team.""" - prefs_permission_level: Optional[str] = field( + prefs_permission_level: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "prefs_permissionLevel"}, ) """ The permission level of the board. Valid options are 'org', 'private', or 'public'. """ - prefs_comments: Optional[str] = None + prefs_comments: Optional[str] = dataclass_field(default=None, kw_only=True) """The comment preferences of the board.""" - prefs_invitations: Optional[str] = None + prefs_invitations: Optional[str] = dataclass_field(default=None, kw_only=True) """The invitation preferences of the board.""" - prefs_card_covers: Optional[str] = field( + prefs_card_covers: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "prefs_cardCovers"}, ) """A string (true, false) determining whether or not to use card covers.""" - prefs_background: Optional[str] = None + prefs_background: Optional[str] = dataclass_field(default=None, kw_only=True) """The background color of the board.""" - prefs_voting: Optional[str] = None + prefs_voting: Optional[str] = dataclass_field(default=None, kw_only=True) """The voting power-up preferences of the board.""" - prefs_card_aging: Optional[str] = field( + prefs_card_aging: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "prefs_cardAging"}, ) """The card aging power-up preferences of the board.""" - enable_calendar: Optional[str] = None + enable_calendar: Optional[str] = dataclass_field(default=None, kw_only=True) """ A string (true, false) determining whether or not to enable calendar power-up. @@ -1043,17 +1215,15 @@ class CreateList: Definition: CreateList """ - name: Optional[str] = None + name: str """The name of the list.""" - id_board: Optional[str] = field( - default=None, - metadata={"wire_name": "idBoard"}, - ) + id_board: str = dataclass_field(metadata={"wire_name": "idBoard"}) """The unique Id of the board to create the list in.""" - pos: Optional[str] = None + pos: Optional[str] = dataclass_field(default=None, kw_only=True) """The position of the list. Specify top, bottom, or a positive number.""" - id_list_source: Optional[str] = field( + id_list_source: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idListSource"}, ) """The id of the list to copy into the new list.""" @@ -1065,24 +1235,27 @@ class Checklist: Definition: Checklist """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique Id of the checklist.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of the checklist.""" - pos: Optional[int] = None + pos: Optional[int] = dataclass_field(default=None, kw_only=True) """The position of the checklist.""" - id_board: Optional[str] = field( + id_board: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idBoard"}, ) """The unique Id of the board.""" - id_card: Optional[str] = field( + id_card: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idCard"}, ) """The unique Id of the card.""" - check_items: Optional[TypingList[Checkitem]] = field( + check_items: Optional[TypingList[Checkitem | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "checkItems"}, ) """The list of the checklist items""" @@ -1094,28 +1267,31 @@ class Checkitem: Definition: Checkitem """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique Id of the checkitem.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """The name of them checkitem.""" - name_data: Optional[Dict[str, Any]] = field( + name_data: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nameData"}, ) """The nameData of them checkitem.""" - pos: Optional[float] = None + pos: Optional[float] = dataclass_field(default=None, kw_only=True) """The position of the checkitem.""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """The state of the checkitem.""" - due: Optional[str] = None + due: Optional[str] = dataclass_field(default=None, kw_only=True) """The due date of the checkitem.""" - id_member: Optional[str] = field( + id_member: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idMember"}, ) """The unique Id of the member.""" - id_checklist: Optional[str] = field( + id_checklist: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "idChecklist"}, ) """The unique Id of the checklist.""" @@ -1127,8 +1303,7 @@ class ClientSubscription: Definition: ClientSubscription """ - notification_u_r_l: Optional[str] = field( - default=None, + notification_u_r_l: str = dataclass_field( metadata={"wire_name": "NotificationURL"}, ) """ @@ -1143,17 +1318,19 @@ class SubscriptionResponse: Definition: SubscriptionResponse """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Id of the subscription""" - notification_u_r_l: Optional[str] = field( + notification_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "NotificationURL"}, ) """Notification Url""" - resource: Optional[str] = None + resource: Optional[str] = dataclass_field(default=None, kw_only=True) """Resource of the subscription request""" - notification_type: Optional[str] = field( + notification_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notificationType"}, ) """Notification Type""" @@ -1165,7 +1342,7 @@ class SubscriptionPayload: Definition: SubscriptionPayload """ - action: Optional[Dict[str, Any]] = None + action: Dict[str, Any] """webhook action""" @@ -1177,16 +1354,16 @@ class TrelloClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -1197,8 +1374,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -1206,8 +1383,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -1219,7 +1396,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -1234,9 +1411,49 @@ def __init__( def connector_name(self) -> str: return "trello" - async def list_cards_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_cards( self, board_id: str, + *, actions: Optional[str] = None, attachments: Optional[bool] = None, attachment_fields: Optional[str] = None, @@ -1250,16 +1467,56 @@ async def list_cards_async( before: Optional[str] = None, filter: Optional[str] = None, fields: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List the cards in a board List the cards matching the query parameters in a specific board. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListCards`. + + Args: + board_id: The unique id of the board. + actions: The list the actions to return. Specify 'all' or a comma + separated list of valid values. + attachments: A boolean value (true, false) determining whether or + not to show attachments. + attachment_fields: List the attachment fields to return. Specify + 'all' or a comma separated list of valid values. + stickers: A boolean value (true, false) determining whether or not + to show stickers. + members: A boolean value (true, false) determining whether or not + to show members. + memeber_fields: List the member fields to return. Specify 'all' or + a comma separated list of valid values. + check_item_states: A boolean value (true, false) determining + whether or not to return the card states. + checklists: Specify the checklists to return. + limit: The max number of results to return, between 1 and 1000. + since: Fetch all cards after this date. + before: Fetch all cards before this date. + filter: An option on how to filter the response. The allowed values + are 'all', 'closed', 'none', 'open' or 'visible'. + fields: List the card fields to return. Specify 'all' or a comma + separated list of valid values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1333,29 +1590,50 @@ async def list_cards_async( query_params.append(f"fields={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def list_cards_simple_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_cards_simple( self, board_id: str, *, @@ -1363,42 +1641,83 @@ async def list_cards_simple_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ A simple version of the list cards A simple version of the list cards API method used by dynamic values. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListCardsSimple`. + + Args: + board_id: Board Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/simple/boards/{quote(str(board_id), safe='')}/cards" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def get_card_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_card( self, card_id: str, board_id: str, + *, actions: Optional[str] = None, actions_entities: Optional[bool] = None, actions_display: Optional[bool] = None, @@ -1422,7 +1741,6 @@ async def get_card_async( stickers: Optional[bool] = None, sticker_fields: Optional[str] = None, fields: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1432,6 +1750,70 @@ async def get_card_async( Get a card by id Get a specific card by its unique id. + + Swagger operation ID: `GetCard`. + + Args: + card_id: The id of the card to fetch. + board_id: The id of the board to fetch cards in. + actions: List the actions to return. Specify 'all' or a comma + separated list of valid values. + actions_entities: A boolean value (true, false) determining whether + or not to return action entities. + actions_display: A boolean value (true, false) determining whether + or not to return action displays. + actions_limit: Max number of actions to return. + action_fields: List of action fields to return for each action. + Specify 'all' or a comma separated list of valid values. + action_member_creator_fields: List of action member creator fields + to return. Specify 'all' or a comma separated list of valid + values. + attachments: A boolean value (true, false) determining whether or + not to return attachments. + attachment_fields: List of attachment fields to return for each + attachment. Specify 'all' or a comma separated list of valid + values. + members: A boolean value (true, false) determining whether or not + to return members. + member_fields: List of member fields to return for each member. + Specify 'all' or a comma separated list of valid values. + members_voted: A boolean value (true, false) determining whether or + not to return voted members. + member_voted_fields: List of voted member fields to return for each + voted member. Specify 'all' or a comma separated list of valid + values. + check_item_states: A boolean value (true, false) determining + whether or not to return card states. + check_item_state_fields: List of state fields to return for each of + the card item state. Specify 'all' or a comma separated list of + valid values. + checklists: Specify the checklists to return for each card. + checklist_fields: List of checklist fields to return for each + checklist. Specify 'all' or a comma separated list of valid + values. + board: A boolean value (true, false) determining whether or not to + return the board which the card belongs to. + board_fields: List the board fields to return. Specify 'all' or a + comma separated list of valid values. + list: A boolean value (true, false) determining whether or not to + return the list which the card belongs to. + list_fields: List the list fields to return. Specify 'all' or a + comma separated list of valid values. + stickers: A boolean value (true, false) determining whether or not + to return the stickers. + sticker_fields: List the sticker fields to return for each sticker. + Specify 'all' or a comma separated list of valid values. + fields: List the card fields to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1560,7 +1942,7 @@ async def get_card_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1574,6 +1956,7 @@ async def get_card_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1581,7 +1964,7 @@ async def get_card_async( return json.loads(response.text) - async def delete_card_async( + def delete_card( self, card_id: str, board_id: str, @@ -1595,6 +1978,22 @@ async def delete_card_async( Delete a card Delete an existing card from the account. + + Swagger operation ID: `DeleteCard`. + + Args: + card_id: The id of the card to delete. + board_id: The id of the board to fetch cards from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1608,7 +2007,7 @@ async def delete_card_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -1622,6 +2021,7 @@ async def delete_card_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1629,8 +2029,9 @@ async def delete_card_async( return json.loads(response.text) - async def list_boards_async( + def list_boards( self, + *, filter: Optional[str] = None, fields: Optional[str] = None, actions: Optional[str] = None, @@ -1643,16 +2044,53 @@ async def list_boards_async( organization: Optional[bool] = None, organization_fields: Optional[str] = None, lists: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List boards List the boards matching the specified query parameters. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListBoards`. + + Args: + filter: List filters to apply to board results. Specify 'all' or a + comma separated list of valid values. + fields: List the board fields to return. Specify 'all' or a comma + separated list of valid values. + actions: List the action fields to return. Specify 'all' or a comma + separated list of valid values. + actions_entities: A boolean value (true, false) determining whether + or not to return action entities. + actions_limit: The max number of actions to return. + actions_format: Specify the format of the actions to return. The + valid options are 'count', 'list', 'minimal'. + actions_since: Return actions after the specified date. + action_fields: List the fields of the action to return. Specify + 'all' or a comma separated list of valid values. + memberships: Specify membership information to return. + organization: A boolean value (true, false) determining whether or + not to return organization information. + organization_fields: List the organization fields to return. + Specify 'all' or a comma separated list of valid values. + lists: Specify whether to return lists which belong to the board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/member/me/boards" query_params = [] @@ -1718,68 +2156,129 @@ async def list_boards_async( query_params.append(f"lists={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def list_boards_simple_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_boards_simple( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ A simple version of the list boards A simple version of the list boards API call with no parameters to be used by dynamic values. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListBoardsSimple`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/simple/member/me/boards" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def get_board_async( + return ItemPaged(get_next, extract_data) + + def get_board( self, board_id: str, + *, actions: Optional[str] = None, action_entities: Optional[bool] = None, actions_display: Optional[bool] = None, @@ -1817,7 +2316,6 @@ async def get_board_async( organization_memberships: Optional[str] = None, my_perfs: Optional[bool] = None, fields: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1827,6 +2325,93 @@ async def get_board_async( Get a board by Id Get a specific board by its unique identifier. + + Swagger operation ID: `GetBoard`. + + Args: + board_id: The unique Id of the board to get. + actions: List the actions to return. Specify 'all' or a comma + separated list of valid values. + action_entities: A boolean value (true, false) determining whether + or not to return action entities. + actions_display: A boolean value (true, false) determining whether + or not to return actions display. + actions_format: Specify the format of the actions to return. Valid + options are 'count', 'list', 'minimal'. + actions_since: Only return the actions after this date. + actions_limit: Max number of actions to return. + action_fields: List the fields to return with each field. Specify + 'all' or a comma separated list of valid values. + action_member: A boolean value (true, false) determining whether or + not to return action members. + action_member_fields: List the member fields to return with each + action member. Specify 'all' or a comma separated list of valid + values. + action_member_creator: A boolean value (true, false) determining + whether or not to return action member creator. + action_member_creator_fields: List the action member creator fields + to return. Specify 'all' or a comma separated list of valid + values. + cards: Specify the cards to return. Valid options are 'all', + 'closed', 'none', 'open', or 'visible'. + card_fields: List the fields to return for each card. Specify 'all' + or a comma separated list of valid values. + card_attachments: A boolean value (true, false) determining whether + or not to return attachments on cards. + card_attachment_fields: List the attachment fields to return for + each attachment. Specify 'all' or a comma separated list of + valid values. + card_checklists: Specify the checklists to return for each card. + card_stickers: A boolean value (true, false) determining whether or + not to return card stickers. + board_stars: Specify the board stars to return. + labels: Specify the labels to return. + label_fields: List the label fields to return for each label. + Specify 'all' or a comma separated list of valid values. + labels_limit: Max number of labels to return. + lists: Specify the lists to return. + list_fields: List the list fields to return for each list. Specify + 'all' or a comma separated list of valid values. + memberships: List the memberships to return. Specify 'all' or a + comma separated list of valid values. + memberships_member: A boolean value (true, false) determining + whether or not to return membership members. + memberships_member_fields: List the member fields to return for + each membership member. Specify 'all' or a comma separated list + of valid values. + members: List the members to return. Specify 'all' or a comma + separated list of valid values. + member_fields: List the member fields to return for each member. + Specify 'all' or a comma separated list of valid values. + members_invited: Specify the invited members to return. + members_invited_fields: List the fields to return for each. Specify + 'all' or a comma separated list of valid values. + checklists: Specify the checklists to return. + checklist_fields: List the checklist fields to return for each + checklist. Specify 'all' or a comma separated list of valid + values. + organization: A boolean value (true, false) determining whether or + not to return the organization information. + organization_fields: List the organization fields to return for + each organization. Specify 'all' or a comma separated list of + valid values. + organization_memberships: List the organization memberships to + return. Specify 'all' or a comma separated list of valid + values. + my_perfs: A boolean value (true, false) determining whether or not + to return my perfs. + fields: List the fields to return. Specify 'all' or a comma + separated list of valid values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2021,7 +2606,7 @@ async def get_board_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2035,6 +2620,7 @@ async def get_board_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2042,9 +2628,9 @@ async def get_board_async( return json.loads(response.text) - async def update_board_async( + def update_board( self, - input: UpdateBoard, + input: UpdateBoard | Mapping[str, Any], board_id: str, *, timeout: Optional[float] = None, @@ -2056,13 +2642,30 @@ async def update_board_async( Update a board Update an existing board. + + Swagger operation ID: `UpdateBoard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + board_id: The unique identifier of the board to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/boards/{quote(str(board_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -2076,6 +2679,7 @@ async def update_board_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2083,23 +2687,49 @@ async def update_board_async( return json.loads(response.text) - async def list_lists_async( + def list_lists( self, board_id: str, + *, cards: Optional[str] = None, card_fields: Optional[str] = None, filter: Optional[str] = None, fields: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List the card lists in a board List the card lists and the cards within the list in a specific board. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListLists`. + + Args: + board_id: The unique id of the board to fetch lists. + cards: Specify the cards to return. + card_fields: List the card fields to return from. Specify 'all' or + a comma separated list of valid values. + filter: Specify the filter property for lists. Valid options are + 'all, 'closed', 'none', or 'open'. + fields: List the fields to return. Specify 'all' or a comma + separated list of valid values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2128,29 +2758,50 @@ async def list_lists_async( query_params.append(f"fields={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def list_lists_simple_async( + return ItemPaged(get_next, extract_data) + + def list_lists_simple( self, board_id: str, *, @@ -2158,48 +2809,88 @@ async def list_lists_simple_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ A simple version of list lists A simple version of list lists to be used by dynamic values. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListListsSimple`. + + Args: + board_id: Unique Id of the board to fetch lists. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/simple/boards/{quote(str(board_id), safe='')}/lists" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_list_async( + def get_list( self, list_id: str, board_id: str, + *, cards: Optional[str] = None, card_fields: Optional[str] = None, board: Optional[bool] = None, board_fields: Optional[str] = None, fields: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2210,6 +2901,31 @@ async def get_list_async( Get an existing list and the cards in the list by the unique identifier of the list. + + Swagger operation ID: `GetList`. + + Args: + list_id: The unique Id of the list to fetch. + board_id: The unique Id of the board to fetch the lists from. + cards: Specify the cards to return. + card_fields: List the card fields to return for each card. Specify + 'all' or a comma separated list of valid values. + board: A boolean value (true, false) determining whether or not to + return board information. + board_fields: List the board fields to return. Specify 'all' or a + comma separated list of valid values. + fields: List the list fields to return. Specify 'all' or a comma + separated list of valid values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2248,7 +2964,7 @@ async def get_list_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2262,6 +2978,7 @@ async def get_list_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2269,16 +2986,16 @@ async def get_list_async( return json.loads(response.text) - async def update_list_async( + def update_list( self, list_id: str, board_id: str, + *, name: Optional[str] = None, closed: Optional[str] = None, id_board: Optional[str] = None, pos: Optional[str] = None, subscribed: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2288,6 +3005,29 @@ async def update_list_async( Update a list Update an existing list. + + Swagger operation ID: `UpdateList`. + + Args: + list_id: The unique id of the list to update. + board_id: The unique id of the board the list is on. + name: The new list name. + closed: A string (true, false) determining whether or not to close + the list. + id_board: The unique id of the board to move the list to. + pos: The list position (top, bottom, or number). + subscribed: A boolean value (true, false) determining whether or + not to subscribe to the list. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2326,7 +3066,7 @@ async def update_list_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -2340,6 +3080,7 @@ async def update_list_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2347,10 +3088,10 @@ async def update_list_async( return json.loads(response.text) - async def get_user_profile_async( + def get_user_profile( self, - fields: Optional[str] = None, *, + fields: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -2360,6 +3101,22 @@ async def get_user_profile_async( Get your User Profile info Get information about your User Profile + + Swagger operation ID: `GetUserProfile`. + + Args: + fields: List the fields to return. Specify 'all' or a comma + separated list of valid values. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/members/me" query_params = [] @@ -2371,7 +3128,7 @@ async def get_user_profile_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2385,6 +3142,7 @@ async def get_user_profile_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2392,45 +3150,84 @@ async def get_user_profile_async( return json.loads(response.text) - async def list_teams_async( + def list_teams( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List teams you are a member of The list of teams or organizations the account is a member of. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTeams`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/members/me/organizations" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def list_team_members_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_team_members( self, team_id: str, *, @@ -2438,39 +3235,79 @@ async def list_team_members_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List members of a team List the members in a specific team. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListTeamMembers`. + + Args: + team_id: The unique Id of the team. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/organizations/{quote(str(team_id), safe='')}/members" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def list_board_members_async( + return ItemPaged(get_next, extract_data) + + def list_board_members( self, board_id: str, *, @@ -2478,39 +3315,79 @@ async def list_board_members_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List members of a board List the members of a specific board. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListBoardMembers`. + + Args: + board_id: The unique Id of the board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/boards/{quote(str(board_id), safe='')}/members" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def list_board_labels_async( + return ItemPaged(get_next, extract_data) + + def list_board_labels( self, board_id: str, *, @@ -2518,11 +3395,30 @@ async def list_board_labels_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List labels of a board List the labels of a specific board. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListBoardLabels`. + + Args: + board_id: The unique Id of the board. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2532,29 +3428,50 @@ async def list_board_labels_async( query_params.append("limit=" + quote("1000", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_team_for_board_async( + def get_team_for_board( self, board_id: str, *, @@ -2567,13 +3484,28 @@ async def get_team_for_board_async( Get the team for a board Get the team details for a specific board. + + Swagger operation ID: `GetTeamForBoard`. + + Args: + board_id: The unique Id of the board to fetch team. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/boards/{quote(str(board_id), safe='')}/organization" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2587,6 +3519,7 @@ async def get_team_for_board_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2594,7 +3527,7 @@ async def get_team_for_board_async( return json.loads(response.text) - async def list_card_members_async( + def list_card_members( self, card_id: str, board_id: str, @@ -2603,11 +3536,31 @@ async def list_card_members_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List members for a card List the members for a specific card. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListCardMembers`. + + Args: + card_id: The unique id of the card. + board_id: The unique id of the board to look for cards on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2620,29 +3573,50 @@ async def list_card_members_async( query_params.append(f"board_id={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def list_card_comments_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_card_comments( self, card_id: str, board_id: str, @@ -2651,11 +3625,31 @@ async def list_card_comments_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List comments for a card List the comments for a specific card. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListCardComments`. + + Args: + card_id: The unique id of the card. + board_id: The unique id of the board to look for comments on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2668,31 +3662,52 @@ async def list_card_comments_async( query_params.append(f"board_id={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def add_comment_to_card_async( + return ItemPaged(get_next, extract_data) + + def add_comment_to_card( self, - input: CommentPost, + input: CommentPost | Mapping[str, Any], card_id: str, board_id: str, *, @@ -2705,6 +3720,24 @@ async def add_comment_to_card_async( Add a comment to a card Add a comment to a specific card. + + Swagger operation ID: `AddCommentToCard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + card_id: The unique id of the card. + board_id: The unique id of the board to add a comment to. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2718,7 +3751,7 @@ async def add_comment_to_card_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2732,6 +3765,7 @@ async def add_comment_to_card_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2739,7 +3773,7 @@ async def add_comment_to_card_async( return json.loads(response.text) - async def add_member_to_card_async( + def add_member_to_card( self, card_id: str, board_id: str, @@ -2754,6 +3788,23 @@ async def add_member_to_card_async( Add member to a card Add a member to a specific card. + + Swagger operation ID: `AddMemberToCard`. + + Args: + card_id: The unique identifier of the card to add a member to. + board_id: The unique id of the board the card is on. + member_id: The member id or username to add to the card. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2771,7 +3822,7 @@ async def add_member_to_card_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -2785,6 +3836,7 @@ async def add_member_to_card_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2792,9 +3844,9 @@ async def add_member_to_card_async( return json.loads(response.text) - async def create_board_async( + def create_board( self, - input: CreateBoard, + input: CreateBoard | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -2805,10 +3857,26 @@ async def create_board_async( Create a board Create a new board with the specified fields. + + Swagger operation ID: `CreateBoard`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/boards" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2822,6 +3890,7 @@ async def create_board_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2829,9 +3898,9 @@ async def create_board_async( return json.loads(response.text) - async def create_list_async( + def create_list( self, - input: CreateList, + input: CreateList | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -2842,10 +3911,26 @@ async def create_list_async( Create a list Create a new list. + + Swagger operation ID: `CreateList`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/lists" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2859,6 +3944,7 @@ async def create_list_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2866,7 +3952,7 @@ async def create_list_async( return json.loads(response.text) - async def close_board_async( + def close_board( self, board_id: str, *, @@ -2879,13 +3965,28 @@ async def close_board_async( Close a board Set a specific board to closed. + + Swagger operation ID: `CloseBoard`. + + Args: + board_id: The unique id of the board to close. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/boards/{quote(str(board_id), safe='')}/closed" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -2899,6 +4000,7 @@ async def close_board_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2906,9 +4008,9 @@ async def close_board_async( return json.loads(response.text) - async def create_card_async( + def create_card( self, - input: CreateCard, + input: CreateCard | Mapping[str, Any], board_id: str, *, timeout: Optional[float] = None, @@ -2920,6 +4022,23 @@ async def create_card_async( Create a card Creates a new card with the parameters provided. + + Swagger operation ID: `CreateCard_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + board_id: The id of the board to create the card in. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/cards" query_params = [] @@ -2930,7 +4049,7 @@ async def create_card_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2944,6 +4063,7 @@ async def create_card_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2951,9 +4071,9 @@ async def create_card_async( return json.loads(response.text) - async def update_card_async( + def update_card( self, - input: UpdateCard, + input: UpdateCard | Mapping[str, Any], card_id: str, board_id: str, *, @@ -2966,6 +4086,24 @@ async def update_card_async( Update a card Update an existing card with new parameters. + + Swagger operation ID: `UpdateCard_V2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + card_id: The id of the card to update. + board_id: The id of the board to fetch cards from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2979,7 +4117,7 @@ async def update_card_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -2993,6 +4131,7 @@ async def update_card_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/twitter.py b/src/azure/connectors/twitter.py index c0cf910..b9bd018 100644 --- a/src/azure/connectors/twitter.py +++ b/src/azure/connectors/twitter.py @@ -5,21 +5,35 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "TwitterClient", + "OriginalTweetModel", + "OriginalTweetUserDetailsModel", + "OriginalTweetUserMentionsModel", + "TriggerBatchResponseTweetModel", + "TweetModel", + "TweetResponseModel", + "UserDetailsModel", + "UserMentionsModel", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,69 +43,72 @@ class TweetModel: Response for Get user timeline """ - tweet_text: Optional[str] = field( - default=None, - metadata={"wire_name": "TweetText"}, - ) + tweet_text: str = dataclass_field(metadata={"wire_name": "TweetText"}) """Text content of the tweet""" - tweet_id: Optional[str] = field( + tweet_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TweetId"}, ) """Id of the tweet""" - created_at: Optional[str] = field( + created_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CreatedAt"}, ) """Time at which the tweet was posted""" - created_at_iso: Optional[str] = field( + created_at_iso: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CreatedAtIso"}, ) """Time at which the tweet was posted""" - retweet_count: Optional[int] = field( - default=None, + retweet_count: int = dataclass_field( metadata={"wire_name": "RetweetCount"}, ) """Total number of re-tweets for the tweet""" - tweeted_by: Optional[str] = field( - default=None, - metadata={"wire_name": "TweetedBy"}, - ) + tweeted_by: str = dataclass_field(metadata={"wire_name": "TweetedBy"}) """Name of the user who has posted the tweet""" - media_urls: Optional[List[str]] = field( + media_urls: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaUrls"}, ) """Url of the media posted along with the tweet""" - tweet_language_code: Optional[str] = field( + tweet_language_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TweetLanguageCode"}, ) """Language code of the tweet""" - tweet_in_reply_to_user_id: Optional[str] = field( + tweet_in_reply_to_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TweetInReplyToUserId"}, ) """ User Id of the author of the tweet that the current tweet is a reply to """ - favorited: Optional[bool] = field( + favorited: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Favorited"}, ) """Indicates whether the tweet is marked as favorited or not""" - user_mentions: Optional[List[UserMentionsModel]] = field( + user_mentions: Optional[List[UserMentionsModel | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UserMentions"}, ) """List of users mentioned in the tweet""" - original_tweet: Optional[OriginalTweetModel] = field( + original_tweet: Optional[OriginalTweetModel | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "OriginalTweet"}, ) - user_details: Optional[UserDetailsModel] = field( + user_details: Optional[UserDetailsModel | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UserDetails"}, ) @@ -102,50 +119,47 @@ class UserDetailsModel: Response for Get followers """ - full_name: Optional[str] = field( - default=None, - metadata={"wire_name": "FullName"}, - ) + full_name: str = dataclass_field(metadata={"wire_name": "FullName"}) """Name of the user""" - location: Optional[str] = field( - default=None, - metadata={"wire_name": "Location"}, - ) + location: str = dataclass_field(metadata={"wire_name": "Location"}) """Location of the user""" - id: Optional[int] = field(default=None, metadata={"wire_name": "Id"}) - """X id (handle) of the user""" - user_name: Optional[str] = field( + id: Optional[int] = dataclass_field( default=None, - metadata={"wire_name": "UserName"}, + kw_only=True, + metadata={"wire_name": "Id"}, ) + """X id (handle) of the user""" + user_name: str = dataclass_field(metadata={"wire_name": "UserName"}) """Screen name of the user""" - followers_count: Optional[int] = field( + followers_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FollowersCount"}, ) """Number of followers""" - description: Optional[str] = field( - default=None, - metadata={"wire_name": "Description"}, - ) + description: str = dataclass_field(metadata={"wire_name": "Description"}) """User description""" - statuses_count: Optional[int] = field( + statuses_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StatusesCount"}, ) """User status count""" - friends_count: Optional[int] = field( + friends_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FriendsCount"}, ) """Number of friends""" - favourites_count: Optional[int] = field( + favourites_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FavouritesCount"}, ) """Number of tweets that the user has favorited""" - profile_image_url: Optional[str] = field( + profile_image_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ProfileImageUrl"}, ) """Url of the profile image""" @@ -157,10 +171,7 @@ class TweetResponseModel: Response for Post a tweet """ - tweet_id: Optional[str] = field( - default=None, - metadata={"wire_name": "TweetId"}, - ) + tweet_id: str = dataclass_field(metadata={"wire_name": "TweetId"}) """ID of the tweet posted""" @@ -170,7 +181,12 @@ class TriggerBatchResponseTweetModel: Response for When a new tweet is posted """ - value: Optional[List[TweetModel]] = None + value: Optional[ + List[TweetModel | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """A list of the response objects""" @@ -180,15 +196,17 @@ class UserMentionsModel: Definition: UserMentionsModel """ - id: Optional[int] = field(default=None, metadata={"wire_name": "Id"}) + id: int = dataclass_field(metadata={"wire_name": "Id"}) """X id (handle) of the user""" - full_name: Optional[str] = field( + full_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FullName"}, ) """Full name of the user""" - user_name: Optional[str] = field( + user_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UserName"}, ) """Screen name of the user""" @@ -200,66 +218,70 @@ class OriginalTweetModel: Definition: OriginalTweetModel """ - tweet_text: Optional[str] = field( - default=None, - metadata={"wire_name": "TweetText"}, - ) + tweet_text: str = dataclass_field(metadata={"wire_name": "TweetText"}) """Text content of the original retrieved tweet""" - tweet_id: Optional[str] = field( + tweet_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TweetId"}, ) """Id of the original tweet""" - created_at: Optional[str] = field( + created_at: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CreatedAt"}, ) """Time at which original tweet was posted""" - created_at_iso: Optional[str] = field( + created_at_iso: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "CreatedAtIso"}, ) """Time at which original tweet was posted""" - retweet_count: Optional[int] = field( - default=None, + retweet_count: int = dataclass_field( metadata={"wire_name": "RetweetCount"}, ) """Total number of re-tweets for this original tweet""" - tweeted_by: Optional[str] = field( - default=None, - metadata={"wire_name": "TweetedBy"}, - ) + tweeted_by: str = dataclass_field(metadata={"wire_name": "TweetedBy"}) """User name of the person who posted the original tweet""" - media_urls: Optional[List[str]] = field( + media_urls: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaUrls"}, ) """Url of the media posted along with the original tweet""" - tweet_language_code: Optional[str] = field( + tweet_language_code: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TweetLanguageCode"}, ) """Language code for the original tweet""" - tweet_in_reply_to_user_id: Optional[str] = field( + tweet_in_reply_to_user_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "TweetInReplyToUserId"}, ) """ User Id of the author of the tweet that the current original tweet is a reply to """ - favorited: Optional[bool] = field( + favorited: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Favorited"}, ) """Indicates whether the original tweet is marked as favorited""" - user_mentions: Optional[List[OriginalTweetUserMentionsModel]] = field( + user_mentions: Optional[ + List[OriginalTweetUserMentionsModel | Mapping[str, Any]] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UserMentions"}, ) """The list of user mentioned in the tweet""" - user_details: Optional[OriginalTweetUserDetailsModel] = field( + user_details: Optional[OriginalTweetUserDetailsModel | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UserDetails"}, ) @@ -270,15 +292,17 @@ class OriginalTweetUserMentionsModel: Definition: OriginalTweetUserMentionsModel """ - id: Optional[int] = field(default=None, metadata={"wire_name": "Id"}) + id: int = dataclass_field(metadata={"wire_name": "Id"}) """X id (handle) of the user""" - full_name: Optional[str] = field( + full_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FullName"}, ) """Full name of the user""" - user_name: Optional[str] = field( + user_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "UserName"}, ) """Screen name of the user""" @@ -290,50 +314,47 @@ class OriginalTweetUserDetailsModel: Definition: OriginalTweetUserDetailsModel """ - full_name: Optional[str] = field( - default=None, - metadata={"wire_name": "FullName"}, - ) + full_name: str = dataclass_field(metadata={"wire_name": "FullName"}) """Name of the user""" - location: Optional[str] = field( - default=None, - metadata={"wire_name": "Location"}, - ) + location: str = dataclass_field(metadata={"wire_name": "Location"}) """Location of the user""" - id: Optional[int] = field(default=None, metadata={"wire_name": "Id"}) - """X id (handle) of the user""" - user_name: Optional[str] = field( + id: Optional[int] = dataclass_field( default=None, - metadata={"wire_name": "UserName"}, + kw_only=True, + metadata={"wire_name": "Id"}, ) + """X id (handle) of the user""" + user_name: str = dataclass_field(metadata={"wire_name": "UserName"}) """Screen name of the user""" - followers_count: Optional[int] = field( + followers_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FollowersCount"}, ) """Number of followers""" - description: Optional[str] = field( - default=None, - metadata={"wire_name": "Description"}, - ) + description: str = dataclass_field(metadata={"wire_name": "Description"}) """User description""" - statuses_count: Optional[int] = field( + statuses_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "StatusesCount"}, ) """User status count""" - friends_count: Optional[int] = field( + friends_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FriendsCount"}, ) """Number of friends""" - favourites_count: Optional[int] = field( + favourites_count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FavouritesCount"}, ) """Number of tweets that the user has favorited""" - profile_image_url: Optional[str] = field( + profile_image_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ProfileImageUrl"}, ) """Url of the profile image""" @@ -347,16 +368,16 @@ class TwitterClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -367,8 +388,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -376,8 +397,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -389,7 +410,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -404,21 +425,80 @@ def __init__( def connector_name(self) -> str: return "twitter" - async def user_timeline_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_user_timeline( self, user_name: str, - max_results: Optional[int] = None, *, + max_results: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get user timeline This operation gets a list of the most recent tweets posted by a given user. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `UserTimeline`. + + Args: + user_name: X handle for the user. + max_results: Maximum number of tweets to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/usertimeline" query_params = [] @@ -433,42 +513,82 @@ async def user_timeline_async( query_params.append(f"maxResults={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def home_timeline_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_home_timeline( self, - max_results: Optional[int] = None, *, + max_results: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get home timeline This operation gets the most recent tweets and re-tweets posted by me and my followers. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `HomeTimeline`. + + Args: + max_results: Maximum number of tweets to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/hometimeline" query_params = [] @@ -479,44 +599,87 @@ async def home_timeline_async( query_params.append(f"maxResults={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def search_tweet_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_search_tweet( self, search_query: str, + *, max_results: Optional[int] = None, since_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Search tweets This operation gets a list of relevant tweets matching the search query. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SearchTweet`. + + Args: + search_query: Search term like \"happy hour\", #haiku, + from:@username, love OR hate. + max_results: Maximum number of tweets to return. + since_id: Return tweets after the specified tweet ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/searchtweets" query_params = [] @@ -536,42 +699,83 @@ async def search_tweet_async( query_params.append(f"sinceId={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def followers_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_followers( self, user_name: str, - max_results: Optional[int] = None, *, + max_results: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get followers This operation gets the list of users that follow a given user. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Followers`. + + Args: + user_name: X handle for the user. + max_results: Maximum number of users to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/followers" query_params = [] @@ -586,41 +790,81 @@ async def followers_async( query_params.append(f"maxResults={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def my_followers_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_my_followers( self, - max_results: Optional[int] = None, *, + max_results: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get my followers This operation gets the list of users who are following me. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `MyFollowers`. + + Args: + max_results: Maximum number of users to get. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/myfollowers" query_params = [] @@ -631,42 +875,83 @@ async def my_followers_async( query_params.append(f"maxResults={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def following_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_following( self, user_name: str, - max_results: Optional[int] = None, *, + max_results: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get following The operation gets the list of people the given user follows. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Following`. + + Args: + user_name: X handle for the user. + max_results: Maximum number of users to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/friends" query_params = [] @@ -681,41 +966,81 @@ async def following_async( query_params.append(f"maxResults={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def my_following_async( + return ItemPaged(get_next, extract_data) + + def list_my_following( self, - max_results: Optional[int] = None, *, + max_results: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get my following This operation gets the list of users that I am following. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `MyFollowing`. + + Args: + max_results: Maximum number of users to return. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/myfriends" query_params = [] @@ -726,29 +1051,50 @@ async def my_following_async( query_params.append(f"maxResults={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def user_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def user( self, user_name: str, *, @@ -762,6 +1108,21 @@ async def user_async( This operation gets the profile details for a given user, such as user name, description, followers count, and more. + + Swagger operation ID: `User`. + + Args: + user_name: X handle for the user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/user" query_params = [] @@ -772,7 +1133,7 @@ async def user_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -786,6 +1147,7 @@ async def user_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -793,11 +1155,11 @@ async def user_async( return json.loads(response.text) - async def tweet_async( + def tweet( self, input: bytes, - tweet_text: Optional[str] = None, *, + tweet_text: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -807,6 +1169,22 @@ async def tweet_async( Post a tweet This operation posts a new tweet. + + Swagger operation ID: `Tweet`. + + Args: + input: The binary request body. + tweet_text: Text to be posted. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/posttweet" query_params = [] @@ -818,7 +1196,7 @@ async def tweet_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -835,6 +1213,7 @@ async def tweet_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -842,11 +1221,11 @@ async def tweet_async( return json.loads(response.text) - async def retweet_async( + def retweet( self, tweet_id: str, - trim_user: Optional[bool] = None, *, + trim_user: Optional[bool] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -856,6 +1235,22 @@ async def retweet_async( Retweet This operation retweets a tweet. + + Swagger operation ID: `Retweet`. + + Args: + tweet_id: Tweet to be retweeted. + trim_user: Boolean to indicate whether to trim user information. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/retweet" query_params = [] @@ -871,7 +1266,7 @@ async def retweet_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -885,6 +1280,7 @@ async def retweet_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/typeform.py b/src/azure/connectors/typeform.py index 205d74b..7810953 100644 --- a/src/azure/connectors/typeform.py +++ b/src/azure/connectors/typeform.py @@ -5,21 +5,35 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "TypeformClient", + "Item", + "ItemNew", + "ListFormsResponse", + "ListFormsResponseOld", + "NewResponseWebhookInput", + "ResponseList", + "WebhookCreationResponse", + "WebhookPayload", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,9 +43,9 @@ class NewResponseWebhookInput: When a response is submitted """ - url: Optional[str] = None + url: str """Webhook URL.""" - enabled: Optional[bool] = None + enabled: bool """ Yes if you want to send responses to the webhook immediately. Otherwise, no. @@ -44,25 +58,25 @@ class WebhookCreationResponse: Response for When a response is submitted """ - id: Optional[str] = None + id: str """Unique ID of the webhook""" - form_id: Optional[str] = None + form_id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique ID of the typeform""" - tag: Optional[str] = None + tag: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique name you want to use for the webhook""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """Webhook URL""" - enabled: Optional[bool] = None + enabled: Optional[bool] = dataclass_field(default=None, kw_only=True) """ True if you want to send responses to the webhook immediately. Otherwise, false. """ - created_at: Optional[str] = None + created_at: Optional[str] = dataclass_field(default=None, kw_only=True) """ Date and time when webhook was created. In ISO 8601 format, UTC time, to the second, with T as a delimiter between the date and time. """ - updated_at: Optional[str] = None + updated_at: Optional[str] = dataclass_field(default=None, kw_only=True) """ Date of last update to webhook. In ISO 8601 format, UTC time, to the second, with T as a delimeter between the date and time. @@ -75,11 +89,11 @@ class ListFormsResponse: Response for List forms """ - total_items: Optional[int] = None + total_items: Optional[int] = dataclass_field(default=None, kw_only=True) """Total number of forms.""" - page_count: Optional[int] = None + page_count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of pages of results.""" - items: Optional[List[Dict[str, Any]]] = None + items: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Forms in response.""" @@ -92,7 +106,12 @@ class ResponseList: Definition: ResponseList """ - responses: Optional[List[Item]] = None + responses: Optional[ + List[Item | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -101,8 +120,9 @@ class Item: Definition: Item """ - item_internal_id: Optional[str] = field( + item_internal_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ItemInternalId"}, ) @@ -113,8 +133,9 @@ class ItemNew: Definition: Item-New """ - item_internal_id: Optional[str] = field( + item_internal_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ItemInternalId"}, ) @@ -125,11 +146,11 @@ class WebhookPayload: Definition: WebhookPayload """ - event_id: Optional[str] = None + event_id: str """Unique ID for the webhook. Automatically assigned by Typeform.""" - event_type: Optional[str] = None + event_type: str """Reason the webhook is being sent.""" - form_response: Optional[Dict[str, Any]] = None + form_response: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """ Object that contains information about the typeform and account associated with the webhook. @@ -144,16 +165,16 @@ class TypeformClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -164,8 +185,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -173,8 +194,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -186,7 +207,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -201,23 +222,85 @@ def __init__( def connector_name(self) -> str: return "typeform" - async def list_forms_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def list_forms( self, + *, search: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, workspace_id: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List forms Retrieves a list of JSON descriptions for all forms in your Typeform account (public and private). + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListForms_V2`. + + Args: + search: Returns items that contain the specified string. + page: The page of results to retrieve. Default is the first page. + page_size: Number of results to retrieve per page. Default is 10. + Maximum is 200. + workspace_id: Retrieve typeforms for the specified workspace. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/forms" query_params = [] @@ -243,29 +326,50 @@ async def list_forms_async( query_params.append(f"workspace_id={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() - async def get_schema_async( + return ItemPaged(get_next, extract_data) + + def get_schema( self, form_id: str, *, @@ -278,13 +382,28 @@ async def get_schema_async( Get schema Get schema + + Swagger operation ID: `GetSchema_V3`. + + Args: + form_id: Form. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v3/forms/{quote(str(form_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -298,6 +417,7 @@ async def get_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/universalprint.py b/src/azure/connectors/universalprint.py index df2b0fe..271bd89 100644 --- a/src/azure/connectors/universalprint.py +++ b/src/azure/connectors/universalprint.py @@ -5,21 +5,27 @@ from __future__ import annotations -from dataclasses import dataclass -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "UniversalprintClient", + "ListRecentSharesResponse", +] + # Type Definitions @@ -29,7 +35,7 @@ class ListRecentSharesResponse: Response for List recently used shares """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """The list of printer shares""" @@ -41,16 +47,16 @@ class UniversalprintClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -61,8 +67,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -70,8 +76,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -83,7 +89,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -98,11 +104,51 @@ def __init__( def connector_name(self) -> str: return "universalprint" - async def print_file_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def print_file( self, input: bytes, printer: str, file_name: str, + *, configuration_copies: Optional[int] = None, configuration_orientation: Optional[str] = None, configuration_color_mode: Optional[str] = None, @@ -113,7 +159,6 @@ async def print_file_async( configuration_quality: Optional[str] = None, configuration_media_type: Optional[str] = None, configuration_finishings: Optional[List[str]] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -123,6 +168,38 @@ async def print_file_async( Print PDF Prints the given pdf. + + Swagger operation ID: `PrintFile`. + + Args: + input: The binary request body. + printer: The name of the printer. + file_name: The name of file. + configuration_copies: The number of copies that should be printed. + configuration_orientation: The direction in which document is + displayed. + configuration_color_mode: The color configuration to print the job. + configuration_media_size: The page size for the paper or other + print media. + configuration_duplex_mode: The setting to print one-sided jobs or + double-sided jobs. + configuration_pages_per_sheet: The number of input Pages to impose + upon a single Impression. + configuration_dpi: The resolution to use when printing the job. + configuration_quality: The print quality to process a print job. + configuration_media_type: The type of media to use. + configuration_finishings: The finishing processes to apply to the + printed document. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/print/shares" query_params = [] @@ -198,7 +275,7 @@ async def print_file_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, @@ -215,42 +292,82 @@ async def print_file_async( request_url, response.status, response.text, + response=response, ) - async def list_recent_shares_async( + def list_recent_shares( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List recently used shares List recently used printer shares. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListRecentShares`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/beta/me/print/recentPrinterShares" ) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) + + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - return json.loads(response.text) + return ItemPaged(get_next, extract_data) diff --git a/src/azure/connectors/waywedo.py b/src/azure/connectors/waywedo.py index ede024f..0d6d8ad 100644 --- a/src/azure/connectors/waywedo.py +++ b/src/azure/connectors/waywedo.py @@ -5,21 +5,50 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "WaywedoClient", + "ChecklistComment", + "ChecklistCreateWebHookInput", + "ChecklistInstance", + "ChecklistInstancesInput", + "ChecklistStep", + "ChecklistStepCompletedWebHookInput", + "ChecklistStepsCompleteInput", + "ChecklistStepsCompleteResponse", + "CollaboratorsAddInput", + "CollaboratorsAddResponse", + "CommentAddInput", + "CompletedStep", + "FinishChecklistWebHookInput", + "GenerateAcceptancePDFWebHookInput", + "GetAllChecklistInstancesResponse", + "InviteSupervisorWebHookInput", + "NewCommentWebHookInput", + "Procedure", + "ProcedureAcceptance", + "User", + "UsersInput", + "UsersPostResponse", + "WebhookRegistered", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,24 +58,19 @@ class CommentAddInput: Add a comment to a checklist instance step """ - instance_id: Optional[str] = field( - default=None, - metadata={"wire_name": "instanceId"}, - ) + instance_id: str = dataclass_field(metadata={"wire_name": "instanceId"}) """Select the checklist instance""" - step_id: Optional[str] = field( - default=None, - metadata={"wire_name": "stepId"}, - ) + step_id: str = dataclass_field(metadata={"wire_name": "stepId"}) """Select the step of the checklist instance""" - user_id: Optional[int] = field( + user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userId"}, ) """Select the user creating the comment""" - message: Optional[str] = None + message: str """Specify the comment to add""" - bot: Optional[str] = None + bot: str """The name of the bot creating the comment""" @@ -56,46 +80,57 @@ class ChecklistComment: Response for Add a comment to a checklist instance step """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the comment.""" - type_: Optional[int] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type of comment; either 1 (standard) or 2 (attachment).""" - procedure_id: Optional[int] = field( + procedure_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "procedureId"}, ) """The unique ID of the procedure.""" - procedure_title: Optional[str] = field( + procedure_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "procedureTitle"}, ) """The title of the procedure.""" - instance_id: Optional[str] = field( + instance_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "instanceId"}, ) """The unique ID of the checklist instance.""" - step_id: Optional[str] = field( + step_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "stepId"}, ) """The unique ID of the checklist step.""" - instance_title: Optional[str] = field( + instance_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "instanceTitle"}, ) """The title of the checklist instance.""" - comment: Optional[str] = None + comment: Optional[str] = dataclass_field(default=None, kw_only=True) """The comment text added to the step.""" - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time the comment was created.""" - created_by: Optional[str] = field( + created_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdBy"}, ) """The email address of the user who created the comment.""" - image_url: Optional[str] = field( + image_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "imageUrl"}, ) """The URL to the attached file. Valid for 5 minutes.""" @@ -107,24 +142,23 @@ class ChecklistInstancesInput: Create Checklist Instance """ - procedure_id: Optional[int] = field( - default=None, - metadata={"wire_name": "procedureId"}, - ) + procedure_id: int = dataclass_field(metadata={"wire_name": "procedureId"}) """Select a checklist master""" - title: Optional[str] = None + title: str """The title of the checklist instance""" - user_id: Optional[int] = field( + user_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userId"}, ) """Select the user to add as a collaborator""" - company_role_id: Optional[int] = field( + company_role_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "companyRoleId"}, ) """Select the company role to add as a collaborator.""" - bot: Optional[str] = None + bot: str """The name of the bot creating the instance""" @@ -134,33 +168,37 @@ class ChecklistInstance: Response for Create Checklist Instance """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the checklist instance.""" - procedure_id: Optional[int] = field( + procedure_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "procedureId"}, ) """The unique ID of the procedure.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the checklist instance.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The URL to the checklist instance.""" - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time the checklist instance was started.""" - created_by: Optional[str] = field( + created_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdBy"}, ) """The email address of the user who started the checklist instance.""" - finished: Optional[str] = None + finished: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time the checklist instance was finished.""" - earliest_due: Optional[str] = field( + earliest_due: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "earliestDue"}, ) """The earliest date and time the checklist instance could be due.""" - latest_due: Optional[str] = field( + latest_due: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "latestDue"}, ) """The latest date and time the checklist instance could be due.""" @@ -172,11 +210,11 @@ class ChecklistStep: Response for Find Checklist Step """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the instance step.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the instance step.""" - ordinal: Optional[int] = None + ordinal: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of the instance step.""" @@ -186,12 +224,9 @@ class ChecklistStepsCompleteInput: Complete a Checklist Step """ - user_id: Optional[int] = field( - default=None, - metadata={"wire_name": "userId"}, - ) + user_id: int = dataclass_field(metadata={"wire_name": "userId"}) """Select the user completing the step""" - bot: Optional[str] = None + bot: str """The name of the bot that completed the checklist step""" @@ -201,7 +236,7 @@ class ChecklistStepsCompleteResponse: Response for Complete a Checklist Step """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -214,17 +249,18 @@ class CollaboratorsAddInput: Add Collaborators to a Checklist Instance """ - checklist_instance_id: Optional[str] = field( - default=None, + checklist_instance_id: str = dataclass_field( metadata={"wire_name": "checklistInstanceId"}, ) """Select the checklist instance""" - user_ids: Optional[List[int]] = field( + user_ids: Optional[List[int]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "userIds"}, ) - company_role_ids: Optional[List[int]] = field( + company_role_ids: Optional[List[int]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "companyRoleIds"}, ) @@ -235,7 +271,7 @@ class CollaboratorsAddResponse: Response for Add Collaborators to a Checklist Instance """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -248,24 +284,29 @@ class Procedure: Response for Find Checklist """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The unique ID of the procedure.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the procedure.""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The publishing status of the procedure.""" - summary: Optional[str] = None + summary: Optional[str] = dataclass_field(default=None, kw_only=True) """The summary of the procedure.""" - created_by: Optional[str] = field( + created_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdBy"}, ) """The email of the user that created the procedure.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """The URL of the procedure.""" - restricted: Optional[bool] = None + restricted: Optional[bool] = dataclass_field(default=None, kw_only=True) """Whether the procedure is restricted or not.""" - type_: Optional[int] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The type of procedure; 1 (standard) or 2 (checklist)""" @@ -275,19 +316,21 @@ class User: Response for Find User """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The unique ID of the user.""" - first_name: Optional[str] = field( + first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "firstName"}, ) """The first name of the user.""" - last_name: Optional[str] = field( + last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastName"}, ) """The last name of the user.""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """The email address of the user.""" @@ -297,31 +340,22 @@ class UsersInput: Add a New User """ - first_name: Optional[str] = field( - default=None, - metadata={"wire_name": "firstName"}, - ) + first_name: str = dataclass_field(metadata={"wire_name": "firstName"}) """The first name of the user.""" - last_name: Optional[str] = field( - default=None, - metadata={"wire_name": "lastName"}, - ) + last_name: str = dataclass_field(metadata={"wire_name": "lastName"}) """The last name of the user.""" - email: Optional[str] = None + email: str """The email address of the user.""" - security_role: Optional[int] = field( - default=None, + security_role: int = dataclass_field( metadata={"wire_name": "securityRole"}, ) """Select a security role.""" - company_roles: Optional[List[int]] = field( + company_roles: Optional[List[int]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "companyRoles"}, ) - time_zone_id: Optional[str] = field( - default=None, - metadata={"wire_name": "timeZoneId"}, - ) + time_zone_id: str = dataclass_field(metadata={"wire_name": "timeZoneId"}) """Select the user's timezone.""" @@ -331,7 +365,7 @@ class UsersPostResponse: Response for Add a New User """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -344,10 +378,7 @@ class ChecklistCreateWebHookInput: When a checklist instance is started """ - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) """The URL to call when action occurs.""" @@ -357,14 +388,15 @@ class WebhookRegistered: Response for When a checklist instance is started """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The unique ID of the Webhook registration.""" - callbackurl: Optional[str] = None + callbackurl: Optional[str] = dataclass_field(default=None, kw_only=True) """The URL to call when action occurs.""" - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time the webhook was registered.""" - web_hook_event: Optional[str] = field( + web_hook_event: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "webHookEvent"}, ) """The name of the webhook event.""" @@ -376,10 +408,7 @@ class NewCommentWebHookInput: When a comment is added to a checklist """ - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) """The URL to call when action occurs.""" @@ -389,10 +418,7 @@ class FinishChecklistWebHookInput: When a checklist is finished """ - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) """The URL to call when action occurs.""" @@ -402,10 +428,7 @@ class InviteSupervisorWebHookInput: When a supervisor is invited """ - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) """The URL to call when action occurs.""" @@ -415,10 +438,7 @@ class GenerateAcceptancePDFWebHookInput: When a procedure is accepted """ - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) """The URL to call when action occurs.""" @@ -428,10 +448,7 @@ class ChecklistStepCompletedWebHookInput: When a checklist step is completed """ - callback_url: Optional[str] = field( - default=None, - metadata={"wire_name": "callbackUrl"}, - ) + callback_url: str = dataclass_field(metadata={"wire_name": "callbackUrl"}) """The URL to call when action occurs.""" @@ -441,10 +458,16 @@ class GetAllChecklistInstancesResponse: Response for Get All Checklist Instances """ - results: Optional[List[ChecklistInstance]] = None + results: Optional[ + List[ChecklistInstance | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The list of checklist instances.""" - total: Optional[int] = field( + total: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "_total"}, ) """The total number of checklist instances.""" @@ -456,30 +479,34 @@ class CompletedStep: Definition: CompletedStep """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The unique ID of the checklist step completion.""" - instance_id: Optional[str] = field( + instance_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "instanceId"}, ) """The unique ID of the checklist instance.""" - procedure_id: Optional[int] = field( + procedure_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "procedureId"}, ) """The unique ID of the procedure.""" - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time the checklist step was completed.""" - created_by: Optional[str] = field( + created_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdBy"}, ) """The email address of the user that completed the checklist step.""" - due: Optional[str] = None + due: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time the checklist step was due.""" - step: Optional[ChecklistStep] = None - decision_choices: Optional[List[str]] = field( + step: Optional[ChecklistStep | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + decision_choices: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "decisionChoices"}, ) """The list of choices made if the step is a decision point.""" @@ -491,27 +518,31 @@ class ProcedureAcceptance: Definition: ProcedureAcceptance """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """The unique ID of the procedure acceptance""" - accepted: Optional[str] = None + accepted: Optional[str] = dataclass_field(default=None, kw_only=True) """The date and time the procedure was accepted.""" - created_by: Optional[str] = field( + created_by: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdBy"}, ) """The email address of the user that accepted the procedure.""" - file_name: Optional[str] = field( + file_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fileName"}, ) """The file name of the generated PDF.""" - attachment_url: Optional[str] = field( + attachment_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "attachmentUrl"}, ) """The URL to the generated PDF. Valid for 5 minutes.""" - procedure_title: Optional[str] = field( + procedure_title: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "procedureTitle"}, ) """The title of the accepted procedure.""" @@ -525,16 +556,16 @@ class WaywedoClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -545,8 +576,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -554,8 +585,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -567,7 +598,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -582,9 +613,48 @@ def __init__( def connector_name(self) -> str: return "waywedo" - async def comment_add_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def comment_add( self, - input: CommentAddInput, + input: CommentAddInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -595,12 +665,28 @@ async def comment_add_async( Add a comment to a checklist instance step Adds a new comment to an Activated Checklist Instance step. + + Swagger operation ID: `Comment_Add`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v1/ChecklistInstanceComments" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -614,6 +700,7 @@ async def comment_add_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -621,9 +708,9 @@ async def comment_add_async( return json.loads(response.text) - async def checklist_instances_async( + def checklist_instances( self, - input: ChecklistInstancesInput, + input: ChecklistInstancesInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -634,10 +721,26 @@ async def checklist_instances_async( Create Checklist Instance Creates a new activated checklist instance. + + Swagger operation ID: `ChecklistInstances_Post`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/ChecklistInstances" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -651,6 +754,7 @@ async def checklist_instances_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -658,7 +762,7 @@ async def checklist_instances_async( return json.loads(response.text) - async def checklist_instances_get_async( + def checklist_instances_get( self, instance_id: str, *, @@ -671,13 +775,28 @@ async def checklist_instances_get_async( Get A Checklist Instance Retrieve a specific checklist instance by ID + + Swagger operation ID: `ChecklistInstances_Get`. + + Args: + instance_id: The ID of the checklist instance. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1/ChecklistInstances/{quote(str(instance_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -691,6 +810,7 @@ async def checklist_instances_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -698,7 +818,7 @@ async def checklist_instances_get_async( return json.loads(response.text) - async def checklist_instances_activity_async( + def list_checklist_instances_activity( self, instance_id: str, *, @@ -706,11 +826,30 @@ async def checklist_instances_activity_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Checklist Instance Activity Retrieve all activity for a checklist instance + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ChecklistInstances_Activity`. + + Args: + instance_id: Select the checklist instance. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -719,42 +858,83 @@ async def checklist_instances_activity_async( f"/{quote(str(instance_id), safe='')}" f"/Activity" ) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def find_steps_async( + return ItemPaged(get_next, extract_data) + + def list_find_steps( self, instance_id: str, - query: Optional[str] = None, *, + query: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Find Checklist Step Find a step of a checklist instance + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Find_Steps`. + + Args: + instance_id: Select the checklist instance. + query: Search for a step title. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -768,29 +948,50 @@ async def find_steps_async( query_params.append(f"query={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def checklist_steps_get_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def checklist_steps_get( self, instance_id: str, step_id: str, @@ -804,6 +1005,22 @@ async def checklist_steps_get_async( Get A Checklist Step Retrieve a specific checklist step by ID + + Swagger operation ID: `ChecklistSteps_Get`. + + Args: + instance_id: The ID of the checklist instance. + step_id: The ID of the checklist step. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -814,7 +1031,7 @@ async def checklist_steps_get_async( f"/{quote(str(step_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -828,6 +1045,7 @@ async def checklist_steps_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -835,9 +1053,9 @@ async def checklist_steps_get_async( return json.loads(response.text) - async def checklist_steps_complete_async( + def checklist_steps_complete( self, - input: ChecklistStepsCompleteInput, + input: ChecklistStepsCompleteInput | Mapping[str, Any], instance_id: str, step_id: str, *, @@ -850,6 +1068,24 @@ async def checklist_steps_complete_async( Complete a Checklist Step Mark a specific step in a checklist instance as complete. + + Swagger operation ID: `ChecklistSteps_Complete`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + instance_id: Select the checklist instance. + step_id: Select the checklist step. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -861,7 +1097,7 @@ async def checklist_steps_complete_async( f"/Complete" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -875,6 +1111,7 @@ async def checklist_steps_complete_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -882,9 +1119,9 @@ async def checklist_steps_complete_async( return json.loads(response.text) - async def collaborators_add_async( + def collaborators_add( self, - input: CollaboratorsAddInput, + input: CollaboratorsAddInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -895,10 +1132,26 @@ async def collaborators_add_async( Add Collaborators to a Checklist Instance Adds one or more collaborators to a checklist instance. + + Swagger operation ID: `Collaborators_Add`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/Collaborators" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -912,6 +1165,7 @@ async def collaborators_add_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -919,19 +1173,38 @@ async def collaborators_add_async( return json.loads(response.text) - async def find_checklist_async( + def list_find_checklist( self, - query: Optional[str] = None, *, + query: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Find Checklist Search for a checklist by title + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Find_Checklist`. + + Args: + query: The title of the checklist. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/Procedures" query_params = [] @@ -943,29 +1216,50 @@ async def find_checklist_async( query_params.append(f"query={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def procedures_get_async( + return ItemPaged(get_next, extract_data) + + def procedures_get( self, procedure_id: int, *, @@ -978,13 +1272,28 @@ async def procedures_get_async( Get A Checklist Or Procedure Retrieve a specific checklist or procedure by ID + + Swagger operation ID: `Procedures_Get`. + + Args: + procedure_id: The ID of the checklist or procedure. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1/Procedures/{quote(str(procedure_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -998,6 +1307,7 @@ async def procedures_get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1005,20 +1315,40 @@ async def procedures_get_async( return json.loads(response.text) - async def find_checklist_instances_async( + def list_find_checklist_instances( self, procedure_id: int, - query: Optional[str] = None, *, + query: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Find Checklist Instance Search for a checklist instance by title. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Find_Checklist_Instances`. + + Args: + procedure_id: Select a checklist. + query: The title of the checklist instance. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1035,41 +1365,81 @@ async def find_checklist_instances_async( query_params.append(f"query={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def find_user_async( + return ItemPaged(get_next, extract_data) + + def list_find_user( self, - query: Optional[str] = None, *, + query: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Find User Search for a user by name or email. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `Find_User`. + + Args: + query: The name or email address of the user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/Users" query_params = [] @@ -1080,31 +1450,52 @@ async def find_user_async( query_params.append(f"query={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item - async def users_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def users( self, - input: UsersInput, + input: UsersInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1115,10 +1506,26 @@ async def users_async( Add a New User Creates and invites a new user. + + Swagger operation ID: `Users_Post`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/Users" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1132,6 +1539,7 @@ async def users_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1139,21 +1547,42 @@ async def users_async( return json.loads(response.text) - async def get_all_checklist_instances_async( + def list_all_checklist_instances( self, + *, limit: Optional[int] = None, offset: Optional[int] = None, status: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get All Checklist Instances Retrieve a list of all activated checklist instances. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAll_ChecklistInstances`. + + Args: + limit: Maximum number of results to fetch. + offset: The number of records skipped. + status: The status of instances returned. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/ChecklistInstances" query_params = [] @@ -1174,27 +1603,48 @@ async def get_all_checklist_instances_async( query_params.append(f"status={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("results", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/wdatp.py b/src/azure/connectors/wdatp.py index 1e14bdb..4127c68 100644 --- a/src/azure/connectors/wdatp.py +++ b/src/azure/connectors/wdatp.py @@ -5,21 +5,67 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "WdatpClient", + "AdvancedHuntingInput", + "AdvancedHuntingResponse", + "AdvancedHuntingSchemaInput", + "AdvancedHuntingSchemaResponse", + "Alert", + "CancelSingleMachineActionInput", + "CollectInvestigationPackageInput", + "CreateAlertByReferenceInput", + "DomainStats", + "FileStats", + "GetAlertsResponse", + "GetInvestigationPackageUriResponse", + "GetInvestigationsResponse", + "GetLiveResponseDownloadLinkResponse", + "GetMachineActionsResponse", + "GetMachinesResponse", + "GetRemediationActivitiesResponse", + "GetRemediationActivityMachineListResponse", + "InitiateInvestigationInput", + "InitiateInvestigationResponse", + "Investigation", + "IpStats", + "IsolateMachineInput", + "LiveResponseCommand", + "LiveResponseCommandStatus", + "Machine", + "MachineAction", + "MachineTagInput", + "OnNewRemediationActivityResponse", + "PatchAlertInput", + "RemediationActivity", + "RestrictAppExecutionInput", + "RunAntivirusScanInput", + "RunLiveResponseInput", + "StartInvestigationInput", + "UnisolateMachineInput", + "UnrestrictAppExecutionInput", + "WebHookNotification", + "WebHookSubscriptionRequest", + "WebHookSubscriptionTableEntity", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +75,7 @@ class AdvancedHuntingInput: Advanced Hunting (Deprecated) """ - query: Optional[str] = field(default=None, metadata={"wire_name": "Query"}) + query: str = dataclass_field(metadata={"wire_name": "Query"}) """The query to run""" @@ -39,13 +85,15 @@ class AdvancedHuntingResponse: Response for Advanced Hunting (Deprecated) """ - stats: Optional[Dict[str, Any]] = field( + stats: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Stats"}, ) """Stats""" - results: Optional[List[Dict[str, Any]]] = field( + results: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "Results"}, ) @@ -56,31 +104,21 @@ class CreateAlertByReferenceInput: Alerts - Create alert """ - machine_id: Optional[str] = field( - default=None, - metadata={"wire_name": "machineId"}, - ) + machine_id: str = dataclass_field(metadata={"wire_name": "machineId"}) """ID of the machine on which the event was identified""" - report_id: Optional[str] = field( - default=None, - metadata={"wire_name": "reportId"}, - ) + report_id: str = dataclass_field(metadata={"wire_name": "reportId"}) """Report Id of the event""" - event_time: Optional[str] = field( - default=None, - metadata={"wire_name": "eventTime"}, - ) + event_time: str = dataclass_field(metadata={"wire_name": "eventTime"}) """Time of the event as string, e.g. 2018-08-03T16:45:21.7115183Z""" - severity: Optional[str] = None + severity: str """Severity of the alert.""" - category: Optional[str] = None + category: str """Category of the alert""" - title: Optional[str] = None + title: str """Title of the Alert""" - description: Optional[str] = None + description: str """Description of the Alert""" - recommended_action: Optional[str] = field( - default=None, + recommended_action: str = dataclass_field( metadata={"wire_name": "recommendedAction"}, ) """Recommended action for the Alert""" @@ -92,69 +130,79 @@ class Alert: Response for Alerts - Create alert """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Alert identifier""" - incident_id: Optional[int] = field( + incident_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "incidentId"}, ) """The ID of the incident""" - investigation_id: Optional[int] = field( + investigation_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "investigationId"}, ) """The Id of the investigation""" - severity: Optional[str] = None + severity: Optional[str] = dataclass_field(default=None, kw_only=True) """Alert severity""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status of the alert""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Alert description""" - alert_creation_time: Optional[str] = field( + alert_creation_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "alertCreationTime"}, ) """The time at which the alert was created""" - category: Optional[str] = None + category: Optional[str] = dataclass_field(default=None, kw_only=True) """Alert category""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Alert title""" - threat_family_name: Optional[str] = field( + threat_family_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "threatFamilyName"}, ) """Threat family name""" - detection_source: Optional[str] = field( + detection_source: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "detectionSource"}, ) """Detection source""" - classification: Optional[str] = None + classification: Optional[str] = dataclass_field(default=None, kw_only=True) """Alert classification""" - determination: Optional[str] = None + determination: Optional[str] = dataclass_field(default=None, kw_only=True) """Alert determination""" - assigned_to: Optional[str] = field( + assigned_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignedTo"}, ) """Person to whom the alert was assigned""" - resolved_time: Optional[str] = field( + resolved_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "resolvedTime"}, ) """The time at which the alert was resolved""" - last_event_time: Optional[str] = field( + last_event_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastEventTime"}, ) """The time of the last event related to the alert""" - first_event_time: Optional[str] = field( + first_event_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "firstEventTime"}, ) """The time of the first event related to the alert""" - machine_id: Optional[str] = field( + machine_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "machineId"}, ) """The identifier of the machine related to the alert""" @@ -166,15 +214,22 @@ class GetAlertsResponse: Response for Alerts - Get list of alerts """ - count: Optional[int] = field( + count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.count"}, ) """The number of available alerts by this query""" - value: Optional[List[Alert]] = None + value: Optional[ + List[Alert | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The alerts returned""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """ @@ -189,19 +244,20 @@ class PatchAlertInput: Alerts - Update alert """ - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """Status of the alert. One of 'New', 'InProgress' and 'Resolved'""" - assigned_to: Optional[str] = field( + assigned_to: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "assignedTo"}, ) """Person to assign the alert to""" - classification: Optional[str] = None + classification: Optional[str] = dataclass_field(default=None, kw_only=True) """ Classification of the alert. One of 'Unknown', 'FalsePositive', 'TruePositive' """ - determination: Optional[str] = None + determination: Optional[str] = dataclass_field(default=None, kw_only=True) """ The determination of the alert. One of 'NotAvailable', 'Apt', 'Malware', 'SecurityPersonnel', 'SecurityTesting', 'UnwantedSoftware', 'Other' @@ -214,10 +270,7 @@ class InitiateInvestigationInput: Actions - Initiate investigation on a machine (to be deprecated) """ - comment: Optional[str] = field( - default=None, - metadata={"wire_name": "Comment"}, - ) + comment: str = dataclass_field(metadata={"wire_name": "Comment"}) """A comment to associate to the investigation""" @@ -227,7 +280,7 @@ class InitiateInvestigationResponse: Response for Actions - Initiate investigation on a machine (to be deprecated) """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the investigation""" @@ -237,10 +290,7 @@ class StartInvestigationInput: Actions - Start automated investigation on a machine """ - comment: Optional[str] = field( - default=None, - metadata={"wire_name": "Comment"}, - ) + comment: str = dataclass_field(metadata={"wire_name": "Comment"}) """A comment to associate to the investigation""" @@ -250,32 +300,37 @@ class Investigation: Response for Actions - Start automated investigation on a machine """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the investigation""" - state: Optional[str] = None + state: Optional[str] = dataclass_field(default=None, kw_only=True) """The state of the investigation (e.g. 'Benign', 'Running', etc..)""" - status_details: Optional[str] = field( + status_details: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "statusDetails"}, ) """Details on the status""" - computer_dns_name: Optional[str] = field( + computer_dns_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "computerDnsName"}, ) """The computer name""" - machine_id: Optional[str] = field( + machine_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "machineId"}, ) """The machine ID""" - start_time: Optional[str] = field( + start_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startTime"}, ) """The UTC time at which investigation was started""" - end_time: Optional[str] = field( + end_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endTime"}, ) """The UTC time at which investigation was completed""" @@ -287,42 +342,56 @@ class MachineAction: Response for Actions - Get single machine action """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The ID of the machine action""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """ The type of the action (e.g. 'Isolate', 'CollectInvestigationPackage', ...) """ - requestor: Optional[str] = None + requestor: Optional[str] = dataclass_field(default=None, kw_only=True) """The person that requested the machine action""" - requestor_comment: Optional[str] = field( + requestor_comment: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requestorComment"}, ) """The comment associated to the machine action""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status of the machine action (e.g., 'InProgress')""" - machine_id: Optional[str] = field( + machine_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "machineId"}, ) """The ID of the machine on which the action has been performed""" - creation_date_time_utc: Optional[str] = field( + creation_date_time_utc: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "creationDateTimeUtc"}, ) """The UTC time at which the action has been requested""" - last_update_date_time_utc: Optional[str] = field( + last_update_date_time_utc: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastUpdateDateTimeUtc"}, ) """The last UTC time at which the action has been updated""" - related_file_info: Optional[Dict[str, Any]] = field( + related_file_info: Optional[Dict[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "relatedFileInfo"}, ) """relatedFileInfo""" - commands: Optional[List[LiveResponseCommandStatus]] = None + commands: Optional[ + List[LiveResponseCommandStatus | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Live response machine action commands""" @@ -332,10 +401,7 @@ class CancelSingleMachineActionInput: Actions - Cancel a single machine action """ - comment: Optional[str] = field( - default=None, - metadata={"wire_name": "Comment"}, - ) + comment: str = dataclass_field(metadata={"wire_name": "Comment"}) """A comment to associate to the machine action cancellation""" @@ -345,7 +411,7 @@ class GetLiveResponseDownloadLinkResponse: Response for Actions - Get live response command result download URI """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """The live response command download URI""" @@ -355,15 +421,22 @@ class GetMachineActionsResponse: Response for Actions - Get list of machine actions """ - count: Optional[int] = field( + count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.count"}, ) """The number of available machine actions by this query""" - value: Optional[List[MachineAction]] = None + value: Optional[ + List[MachineAction | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The machine actions returned""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """ @@ -378,40 +451,47 @@ class FileStats: Response for Files - Get the statistics for the given file """ - sha1: Optional[str] = None + sha1: Optional[str] = dataclass_field(default=None, kw_only=True) """The sha1 of the file""" - globally_prevalence: Optional[int] = field( + globally_prevalence: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "globallyPrevalence"}, ) """The file global prevalence.""" - global_first_observed: Optional[str] = field( + global_first_observed: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "globalFirstObserved"}, ) """The first time the file was observed globally.""" - global_last_observed: Optional[str] = field( + global_last_observed: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "globalLastObserved"}, ) """The Last time the file was observed.""" - organization_prevalence: Optional[int] = field( + organization_prevalence: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "organizationPrevalence"}, ) """The file prevalence across organization""" - org_first_seen: Optional[str] = field( + org_first_seen: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "orgFirstSeen"}, ) """The first time the file was observed in the organization.""" - org_last_seen: Optional[str] = field( + org_last_seen: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "orgLastSeen"}, ) """The last time the file was observed in the organization.""" - top_file_names: Optional[List[str]] = field( + top_file_names: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "topFileNames"}, ) """The file names that this file has been presented.""" @@ -423,20 +503,23 @@ class DomainStats: Response for Domains - Get the statistics for the given domain name """ - host: Optional[str] = None + host: Optional[str] = dataclass_field(default=None, kw_only=True) """The domain host.""" - organization_prevalence: Optional[int] = field( + organization_prevalence: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "organizationPrevalence"}, ) """The domain prevalence across organization""" - org_first_seen: Optional[str] = field( + org_first_seen: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "orgFirstSeen"}, ) """The first time the domain was observed in the organization.""" - org_last_seen: Optional[str] = field( + org_last_seen: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "orgLastSeen"}, ) """The last time the domain was observed in the organization.""" @@ -448,23 +531,27 @@ class IpStats: Response for Ips - Get the statistics for the given ip address """ - ip_address: Optional[str] = field( + ip_address: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ipAddress"}, ) """The ip address""" - organization_prevalence: Optional[int] = field( + organization_prevalence: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "organizationPrevalence"}, ) """The ip address prevalence across organization""" - org_first_seen: Optional[str] = field( + org_first_seen: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "orgFirstSeen"}, ) """The first time the ip address was observed in the organization.""" - org_last_seen: Optional[str] = field( + org_last_seen: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "orgLastSeen"}, ) """The last time the ip address was observed in the organization.""" @@ -476,15 +563,22 @@ class GetInvestigationsResponse: Response for Actions - Get list of investigation """ - count: Optional[int] = field( + count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.count"}, ) """The number of available investigations by this query""" - value: Optional[List[Investigation]] = None + value: Optional[ + List[Investigation | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The investigations returned""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """ @@ -499,10 +593,7 @@ class CollectInvestigationPackageInput: Actions - Collect investigation package """ - comment: Optional[str] = field( - default=None, - metadata={"wire_name": "Comment"}, - ) + comment: str = dataclass_field(metadata={"wire_name": "Comment"}) """A comment to associate to the collection""" @@ -512,7 +603,7 @@ class GetInvestigationPackageUriResponse: Response for Actions - Get investigation package download URI """ - value: Optional[str] = None + value: Optional[str] = dataclass_field(default=None, kw_only=True) """The investigation package SAS URI""" @@ -522,13 +613,9 @@ class IsolateMachineInput: Actions - Isolate machine """ - comment: Optional[str] = field( - default=None, - metadata={"wire_name": "Comment"}, - ) + comment: str = dataclass_field(metadata={"wire_name": "Comment"}) """A comment to associate to the isolation""" - isolation_type: Optional[str] = field( - default=None, + isolation_type: str = dataclass_field( metadata={"wire_name": "IsolationType"}, ) """ @@ -544,10 +631,7 @@ class UnisolateMachineInput: Actions - Unisolate machine """ - comment: Optional[str] = field( - default=None, - metadata={"wire_name": "Comment"}, - ) + comment: str = dataclass_field(metadata={"wire_name": "Comment"}) """A comment to associate to the unisolation""" @@ -557,10 +641,7 @@ class RestrictAppExecutionInput: Actions - Restrict app execution """ - comment: Optional[str] = field( - default=None, - metadata={"wire_name": "Comment"}, - ) + comment: str = dataclass_field(metadata={"wire_name": "Comment"}) """A comment to associate to the restriction""" @@ -570,10 +651,7 @@ class UnrestrictAppExecutionInput: Actions - Remove app execution restriction """ - comment: Optional[str] = field( - default=None, - metadata={"wire_name": "Comment"}, - ) + comment: str = dataclass_field(metadata={"wire_name": "Comment"}) """A comment to associate to the restriction removal""" @@ -583,15 +661,9 @@ class RunAntivirusScanInput: Actions - Run antivirus scan """ - comment: Optional[str] = field( - default=None, - metadata={"wire_name": "Comment"}, - ) + comment: str = dataclass_field(metadata={"wire_name": "Comment"}) """A comment to associate to the scan request""" - scan_type: Optional[str] = field( - default=None, - metadata={"wire_name": "ScanType"}, - ) + scan_type: str = dataclass_field(metadata={"wire_name": "ScanType"}) """Type of scan to perform. Allowed values are 'Quick' or 'Full'""" @@ -601,13 +673,9 @@ class RunLiveResponseInput: Actions - Run live response """ - comment: Optional[str] = field( - default=None, - metadata={"wire_name": "Comment"}, - ) + comment: str = dataclass_field(metadata={"wire_name": "Comment"}) """A comment to associate to the isolation""" - commands: Optional[List[LiveResponseCommand]] = field( - default=None, + commands: List[LiveResponseCommand | Mapping[str, Any]] = dataclass_field( metadata={"wire_name": "Commands"}, ) """The live response commands to execute""" @@ -619,15 +687,22 @@ class GetRemediationActivitiesResponse: Response for Remediation tasks - Get list of remediation activities (Preview) """ - count: Optional[int] = field( + count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.count"}, ) """The number of remediation activities by this query""" - value: Optional[List[RemediationActivity]] = None + value: Optional[ + List[RemediationActivity | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The remediation activities returned""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """ @@ -642,124 +717,149 @@ class RemediationActivity: Response for RemediationActivities - Get single remediation activity (Preview) """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The remediation activity identifier""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the remediation activit""" - created_on: Optional[str] = field( + created_on: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "createdOn"}, ) """The time when the remediation activity was created""" - status_last_modified_on: Optional[str] = field( + status_last_modified_on: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "statusLastModifiedOn"}, ) """The time when the status was last modified""" - requester_id: Optional[str] = field( + requester_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requesterId"}, ) """The remediation activity creator id""" - requester_email: Optional[str] = field( + requester_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requesterEmail"}, ) """The remediation activity creator email address""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """the remediation activity status""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """The description of the remediation activity""" - related_component: Optional[str] = field( + related_component: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "relatedComponent"}, ) """The remediation activity related component""" - target_devices: Optional[int] = field( + target_devices: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "targetDevices"}, ) """The number of the remediation activity target machines""" - rbac_group_names: Optional[List[str]] = field( + rbac_group_names: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "rbacGroupNames"}, ) """The rbac group names associated to the remediation activity""" - fixed_devices: Optional[int] = field( + fixed_devices: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "fixedDevices"}, ) """The number of the remediation activity fixed machines""" - requester_notes: Optional[str] = field( + requester_notes: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requesterNotes"}, ) """The remediation activity creator notes""" - due_on: Optional[str] = field( + due_on: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dueOn"}, ) """The due time for the remediation activity""" - category: Optional[str] = None + category: Optional[str] = dataclass_field(default=None, kw_only=True) """the remediation activity category""" - productivity_impact_remediation_type: Optional[str] = field( + productivity_impact_remediation_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "productivityImpactRemediationType"}, ) """the remediation Productivity impact type""" - priority: Optional[str] = None + priority: Optional[str] = dataclass_field(default=None, kw_only=True) """The remediation activity priority""" - completion_method: Optional[str] = field( + completion_method: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "completionMethod"}, ) """The remediation activity completion method""" - completer_id: Optional[str] = field( + completer_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "completerId"}, ) """The remediation activity completer object id""" - completer_email: Optional[str] = field( + completer_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "completerEmail"}, ) """The remediation activity completer email address""" - scid: Optional[str] = None + scid: Optional[str] = dataclass_field(default=None, kw_only=True) """The remediation activity security configuration id""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """The remediation activity type""" - product_id: Optional[str] = field( + product_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "productId"}, ) """Product Id""" - vendor_id: Optional[str] = field( + vendor_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "vendorId"}, ) """Vendor id""" - name_id: Optional[str] = field( + name_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nameId"}, ) """Name id""" - recommended_version: Optional[str] = field( + recommended_version: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recommendedVersion"}, ) """Recommended version""" - recommended_vendor: Optional[str] = field( + recommended_vendor: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recommendedVendor"}, ) """Recommended vendor""" - recommended_program: Optional[str] = field( + recommended_program: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "recommendedProgram"}, ) """Recommended program""" - recommendation_reference: Optional[str] = field( + recommendation_reference: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "RecommendationReference"}, ) """Recommendation reference""" @@ -771,15 +871,22 @@ class GetRemediationActivityMachineListResponse: Response for Remediation activities - Get list of related machines (Preview) """ - count: Optional[int] = field( + count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.count"}, ) """The number of available machines by this query""" - value: Optional[List[Machine]] = None + value: Optional[ + List[Machine | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The machines returned""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """ @@ -794,15 +901,22 @@ class GetMachinesResponse: Response for Machines - Get list of machines """ - count: Optional[int] = field( + count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.count"}, ) """The number of available machines by this query""" - value: Optional[List[Machine]] = None + value: Optional[ + List[Machine | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The machines returned""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """ @@ -817,90 +931,107 @@ class Machine: Response for Machines - Get single machine """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """The machine identifier""" - computer_dns_name: Optional[str] = field( + computer_dns_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "computerDnsName"}, ) """The computer name""" - first_seen: Optional[str] = field( + first_seen: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "firstSeen"}, ) """The time of the first event received by the machine""" - last_seen: Optional[str] = field( + last_seen: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastSeen"}, ) """The time of the last event received by the machine""" - os_platform: Optional[str] = field( + os_platform: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "osPlatform"}, ) """The OS platform of the machine""" - os_version: Optional[str] = field( + os_version: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "osVersion"}, ) """The OS version of the machine""" - system_product_name: Optional[str] = field( + system_product_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "systemProductName"}, ) """systemProductName""" - last_ip_address: Optional[str] = field( + last_ip_address: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastIpAddress"}, ) """The last IP address of the machine""" - last_external_ip_address: Optional[str] = field( + last_external_ip_address: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastExternalIpAddress"}, ) """The last external IP address of the machine""" - agent_version: Optional[str] = field( + agent_version: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "agentVersion"}, ) """The agent version""" - os_build: Optional[int] = field( + os_build: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "osBuild"}, ) """The OS build of the machine""" - health_status: Optional[str] = field( + health_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "healthStatus"}, ) """The health status of the machine""" - is_aad_joined: Optional[bool] = field( + is_aad_joined: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isAadJoined"}, ) """A flag indicating whether the machine is joined to Microsoft Entra ID""" - machine_tags: Optional[List[str]] = field( + machine_tags: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "machineTags"}, ) """The tags associated to the machine""" - rbac_group_id: Optional[int] = field( + rbac_group_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "rbacGroupId"}, ) """The ID of the RBAC group to which the machine belongs""" - rbac_group_name: Optional[str] = field( + rbac_group_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "rbacGroupName"}, ) """The name of the RBAC group to which the machine belongs""" - risk_score: Optional[str] = field( + risk_score: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "riskScore"}, ) """A score indicating how much the machine is at risk""" - aad_device_id: Optional[str] = field( + aad_device_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "aadDeviceId"}, ) """aadDeviceId""" @@ -912,12 +1043,9 @@ class MachineTagInput: Machines - Tag machine """ - value: Optional[str] = field(default=None, metadata={"wire_name": "Value"}) + value: str = dataclass_field(metadata={"wire_name": "Value"}) """The tag to add or remove""" - action: Optional[str] = field( - default=None, - metadata={"wire_name": "Action"}, - ) + action: str = dataclass_field(metadata={"wire_name": "Action"}) """ The action to perform. Value should be one of 'Add' (to add a tag) or 'Remove' (to remove a tag) @@ -930,14 +1058,16 @@ class WebHookSubscriptionTableEntity: Response for Triggers - Trigger when new WDATP alert occurs """ - id: Optional[str] = None - notification_url: Optional[str] = field( + id: Optional[str] = dataclass_field(default=None, kw_only=True) + notification_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notificationUrl"}, ) """Gets or sets the web hook subscription notification URL.""" - client_state: Optional[str] = field( + client_state: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "clientState"}, ) @@ -948,15 +1078,22 @@ class OnNewRemediationActivityResponse: Response for Triggers when a new remediation activity is created (Preview) """ - count: Optional[int] = field( + count: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.count"}, ) """The number of remediation activities by this query""" - value: Optional[List[RemediationActivity]] = None + value: Optional[ + List[RemediationActivity | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The remediation activities returned""" - next_link: Optional[str] = field( + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """ @@ -971,7 +1108,7 @@ class AdvancedHuntingSchemaInput: Advanced Hunting Schema """ - query: Optional[str] = field(default=None, metadata={"wire_name": "Query"}) + query: str = dataclass_field(metadata={"wire_name": "Query"}) """The query to run""" @@ -981,7 +1118,7 @@ class AdvancedHuntingSchemaResponse: Response for Advanced Hunting Schema """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -994,29 +1131,37 @@ class LiveResponseCommandStatus: Definition: LiveResponseCommandStatus """ - index: Optional[int] = None + index: Optional[int] = dataclass_field(default=None, kw_only=True) """The index of the command""" - start_time: Optional[str] = field( + start_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "startTime"}, ) """The command execution start time UTC""" - end_time: Optional[str] = field( + end_time: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "endTime"}, ) """The command execution end time UTC""" - command_status: Optional[str] = field( + command_status: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "commandStatus"}, ) """The status of the command execution (e.g., 'Completed')""" - errors: Optional[List[str]] = None + errors: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """ List of command execution errors. In case no errors reported this will be an empty list. """ - command: Optional[LiveResponseCommand] = None + command: Optional[ + LiveResponseCommand | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) """The live response command""" @@ -1026,9 +1171,9 @@ class LiveResponseCommand: Definition: LiveResponseCommand """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: str = dataclass_field(metadata={"wire_name": "type"}) """The type of the command""" - params: Optional[List[Dict[str, Any]]] = None + params: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of command parameters.""" @@ -1038,28 +1183,20 @@ class WebHookSubscriptionRequest: Definition: WebHookSubscriptionRequest """ - client_state: Optional[str] = field( - default=None, - metadata={"wire_name": "clientState"}, - ) + client_state: str = dataclass_field(metadata={"wire_name": "clientState"}) """Gets or sets the client state.""" - change_type: Optional[str] = field( - default=None, - metadata={"wire_name": "changeType"}, - ) + change_type: str = dataclass_field(metadata={"wire_name": "changeType"}) """ Indicates the type of change in the subscribed resource that will raise a notification. """ - resource: Optional[str] = None + resource: str """Specifies the resource that will be monitored for changes.""" - expiration_date_time: Optional[str] = field( - default=None, + expiration_date_time: str = dataclass_field( metadata={"wire_name": "expirationDateTime"}, ) """Specifies the date and time when the webhook subscription expires.""" - notification_url: Optional[str] = field( - default=None, + notification_url: str = dataclass_field( metadata={"wire_name": "notificationUrl"}, ) """Gets or sets the web hook callback URL.""" @@ -1071,9 +1208,10 @@ class WebHookNotification: Definition: WebHookNotification """ - id: Optional[str] = None - machine_id: Optional[str] = field( + id: Optional[str] = dataclass_field(default=None, kw_only=True) + machine_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "machineId"}, ) @@ -1086,16 +1224,16 @@ class WdatpClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -1106,8 +1244,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -1115,8 +1253,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -1128,7 +1266,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -1150,7 +1288,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -1182,9 +1320,9 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def advanced_hunting_async( + def advanced_hunting( self, - input: AdvancedHuntingInput, + input: AdvancedHuntingInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1199,10 +1337,26 @@ async def advanced_hunting_async( and will be retired on February 1, 2027. Migrate to the Microsoft Graph Security API. For migration guidance, see: https://learn.microsoft.com/en-us/graph/api/resources/security-api-overview?view=graph-rest-1.0#powerplatformflow-migrationpowerapps-power-automate-logic-apps + + Swagger operation ID: `AdvancedHunting`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/advancedqueries/run" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1216,6 +1370,7 @@ async def advanced_hunting_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1223,9 +1378,9 @@ async def advanced_hunting_async( return json.loads(response.text) - async def create_alert_by_reference_async( + def create_alert_by_reference( self, - input: CreateAlertByReferenceInput, + input: CreateAlertByReferenceInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1236,12 +1391,28 @@ async def create_alert_by_reference_async( Alerts - Create alert Create Alert based on specific Event + + Swagger operation ID: `CreateAlertByReference`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/api/alerts/createAlertByReference" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1255,6 +1426,7 @@ async def create_alert_by_reference_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1262,8 +1434,9 @@ async def create_alert_by_reference_async( return json.loads(response.text) - async def get_alerts_async( + def list_alerts( self, + *, expand: Optional[str] = None, filter: Optional[str] = None, select: Optional[str] = None, @@ -1271,19 +1444,41 @@ async def get_alerts_async( top: Optional[int] = None, skip: Optional[int] = None, count: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Alerts - Get list of alerts Retrieve from Windows Defender ATP the most recent alerts - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAlerts`. + + Args: + expand: Expands related entities inline. + filter: Filters the results, using OData syntax. + select: Selects which properties to include in the response, + defaults to all. + orderby: Sorts the results. + top: Returns only the first n results. + skip: Skips the first n results. + count: Includes a count of the matching results in the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/alerts" query_params = [] @@ -1324,11 +1519,18 @@ async def get_alerts_async( query_params.append(f"$count={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1341,23 +1543,32 @@ async def get_alerts_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_single_alert_async( + return ItemPaged(get_next, extract_data) + + def get_single_alert( self, alert_id: str, *, @@ -1370,13 +1581,28 @@ async def get_single_alert_async( Alerts - Get single alert Retrieve from Windows Defender ATP a specific alert + + Swagger operation ID: `GetSingleAlert`. + + Args: + alert_id: The identifier of the alert to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/alerts/{quote(str(alert_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1390,6 +1616,7 @@ async def get_single_alert_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1397,9 +1624,9 @@ async def get_single_alert_async( return json.loads(response.text) - async def patch_alert_async( + def patch_alert( self, - input: PatchAlertInput, + input: PatchAlertInput | Mapping[str, Any], alert_id: str, *, timeout: Optional[float] = None, @@ -1411,13 +1638,30 @@ async def patch_alert_async( Alerts - Update alert Update a Windows Defender ATP alert + + Swagger operation ID: `PatchAlert`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + alert_id: The identifier of the alert to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/alerts/{quote(str(alert_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -1431,6 +1675,7 @@ async def patch_alert_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1438,9 +1683,9 @@ async def patch_alert_async( return json.loads(response.text) - async def initiate_investigation_async( + def initiate_investigation( self, - input: InitiateInvestigationInput, + input: InitiateInvestigationInput | Mapping[str, Any], machine_id: str, *, timeout: Optional[float] = None, @@ -1452,6 +1697,23 @@ async def initiate_investigation_async( Actions - Initiate investigation on a machine (to be deprecated) Initiate investigation on a machine + + Swagger operation ID: `InitiateInvestigation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to investigate. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1461,7 +1723,7 @@ async def initiate_investigation_async( f"/initiateInvestigation" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1475,6 +1737,7 @@ async def initiate_investigation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1482,9 +1745,9 @@ async def initiate_investigation_async( return json.loads(response.text) - async def start_investigation_async( + def start_investigation( self, - input: StartInvestigationInput, + input: StartInvestigationInput | Mapping[str, Any], machine_id: str, *, timeout: Optional[float] = None, @@ -1496,6 +1759,23 @@ async def start_investigation_async( Actions - Start automated investigation on a machine Start automated investigation on a machine + + Swagger operation ID: `StartInvestigation`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to investigate. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1505,7 +1785,7 @@ async def start_investigation_async( f"/startInvestigation" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1519,6 +1799,7 @@ async def start_investigation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1526,7 +1807,7 @@ async def start_investigation_async( return json.loads(response.text) - async def get_single_machine_action_async( + def get_single_machine_action( self, machine_action_id: str, *, @@ -1539,13 +1820,29 @@ async def get_single_machine_action_async( Actions - Get single machine action Retrieve from Windows Defender ATP a specific machine action + + Swagger operation ID: `GetSingleMachineAction`. + + Args: + machine_action_id: The identifier of the machine action to + retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/machineactions/{quote(str(machine_action_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1559,6 +1856,7 @@ async def get_single_machine_action_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1566,9 +1864,9 @@ async def get_single_machine_action_async( return json.loads(response.text) - async def cancel_single_machine_action_async( + def cancel_single_machine_action( self, - input: CancelSingleMachineActionInput, + input: CancelSingleMachineActionInput | Mapping[str, Any], machine_action_id: str, *, timeout: Optional[float] = None, @@ -1580,6 +1878,23 @@ async def cancel_single_machine_action_async( Actions - Cancel a single machine action Cancel a specific machine action + + Swagger operation ID: `CancelSingleMachineAction`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_action_id: The identifier of the machine action to cancel. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1589,7 +1904,7 @@ async def cancel_single_machine_action_async( f"/cancel" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1603,6 +1918,7 @@ async def cancel_single_machine_action_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1610,7 +1926,7 @@ async def cancel_single_machine_action_async( return json.loads(response.text) - async def get_live_response_download_link_async( + def get_live_response_download_link( self, machine_action_id: str, command_index: int, @@ -1624,6 +1940,23 @@ async def get_live_response_download_link_async( Actions - Get live response command result download URI Get result download URI for a completed live response command + + Swagger operation ID: `GetLiveResponseDownloadLink`. + + Args: + machine_action_id: The identifier of the machine action. + command_index: The index of the live response command to get the + results download URI for. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1635,7 +1968,7 @@ async def get_live_response_download_link_async( f")" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1649,6 +1982,7 @@ async def get_live_response_download_link_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1656,27 +1990,49 @@ async def get_live_response_download_link_async( return json.loads(response.text) - async def get_machine_actions_async( + def list_machine_actions( self, + *, filter: Optional[str] = None, select: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, count: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Actions - Get list of machine actions Retrieve from Windows Defender ATP the most recent machine actions - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMachineActions`. + + Args: + filter: Filters the results, using OData syntax. + select: Selects which properties to include in the response, + defaults to all. + orderby: Sorts the results. + top: Returns only the first n results. + skip: Skips the first n results. + count: Includes a count of the matching results in the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/machineactions" query_params = [] @@ -1712,11 +2068,18 @@ async def get_machine_actions_async( query_params.append(f"$count={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -1729,27 +2092,36 @@ async def get_machine_actions_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_file_stats_async( + return ItemPaged(get_next, extract_data) + + def get_file_stats( self, file_id: str, - look_back_hours: Optional[int] = None, *, + look_back_hours: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1760,6 +2132,23 @@ async def get_file_stats_async( Retrieve from Windows Defender ATP statistics for the given file to a given file by identifier Sha1, or Sha256 + + Swagger operation ID: `GetFileStats`. + + Args: + file_id: The file identifier - Sha1, or Sha256. + look_back_hours: The look back period in hours to look by, the + default is 24 hours. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1774,7 +2163,7 @@ async def get_file_stats_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1788,6 +2177,7 @@ async def get_file_stats_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1795,11 +2185,11 @@ async def get_file_stats_async( return json.loads(response.text) - async def get_domain_stats_async( + def get_domain_stats( self, domain_name: str, - look_back_hours: Optional[int] = None, *, + look_back_hours: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1810,6 +2200,23 @@ async def get_domain_stats_async( Retrieve from Windows Defender ATP statistics related to a given domain name + + Swagger operation ID: `GetDomainStats`. + + Args: + domain_name: The domain name. + look_back_hours: The look back period in hours to look by, the + default is 24 hours. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1824,7 +2231,7 @@ async def get_domain_stats_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1838,6 +2245,7 @@ async def get_domain_stats_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1845,11 +2253,11 @@ async def get_domain_stats_async( return json.loads(response.text) - async def get_ip_stats_async( + def get_ip_stats( self, ip_address: str, - look_back_hours: Optional[int] = None, *, + look_back_hours: Optional[int] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -1860,6 +2268,23 @@ async def get_ip_stats_async( Retrieve from Windows Defender ATP statistics related to a given ip address - given in ipv4 or ipv6 format. + + Swagger operation ID: `GetIpStats`. + + Args: + ip_address: The ip address. + look_back_hours: The look back period in hours to look by, the + default is 24 hours. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -1874,7 +2299,7 @@ async def get_ip_stats_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1888,6 +2313,7 @@ async def get_ip_stats_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1895,7 +2321,7 @@ async def get_ip_stats_async( return json.loads(response.text) - async def get_single_investigation_async( + def get_single_investigation( self, investigation_id: str, *, @@ -1908,13 +2334,28 @@ async def get_single_investigation_async( Actions - Get single investigation Retrieve from Microsoft Defender ATP a specific investigation + + Swagger operation ID: `GetSingleInvestigation`. + + Args: + investigation_id: The identifier of the investigation to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/investigations/{quote(str(investigation_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1928,6 +2369,7 @@ async def get_single_investigation_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1935,27 +2377,49 @@ async def get_single_investigation_async( return json.loads(response.text) - async def get_investigations_async( + def list_investigations( self, + *, filter: Optional[str] = None, select: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, count: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Actions - Get list of investigation Retrieve from Microsoft Defender ATP the most recent investigations - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetInvestigations`. + + Args: + filter: Filters the results, using OData syntax. + select: Selects which properties to include in the response, + defaults to all. + orderby: Sorts the results. + top: Returns only the first n results. + skip: Skips the first n results. + count: Includes a count of the matching results in the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/investigations" query_params = [] @@ -1991,11 +2455,18 @@ async def get_investigations_async( query_params.append(f"$count={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2008,25 +2479,34 @@ async def get_investigations_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def collect_investigation_package_async( + return continuation_token, items() + + return ItemPaged(get_next, extract_data) + + def collect_investigation_package( self, - input: CollectInvestigationPackageInput, + input: CollectInvestigationPackageInput | Mapping[str, Any], machine_id: str, *, timeout: Optional[float] = None, @@ -2038,6 +2518,24 @@ async def collect_investigation_package_async( Actions - Collect investigation package Collect investigation package from a machine + + Swagger operation ID: `CollectInvestigationPackage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to collect the investigation + from. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2047,7 +2545,7 @@ async def collect_investigation_package_async( f"/collectInvestigationPackage" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2061,6 +2559,7 @@ async def collect_investigation_package_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2068,7 +2567,7 @@ async def collect_investigation_package_async( return json.loads(response.text) - async def get_investigation_package_uri_async( + def get_investigation_package_uri( self, machine_action_id: str, *, @@ -2081,6 +2580,21 @@ async def get_investigation_package_uri_async( Actions - Get investigation package download URI Get a URI that allows downloading of an investigation package + + Swagger operation ID: `GetInvestigationPackageUri`. + + Args: + machine_action_id: The ID of the investigation package collection. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2090,7 +2604,7 @@ async def get_investigation_package_uri_async( f"/getPackageUri" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2104,6 +2618,7 @@ async def get_investigation_package_uri_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2111,9 +2626,9 @@ async def get_investigation_package_uri_async( return json.loads(response.text) - async def isolate_machine_async( + def isolate_machine( self, - input: IsolateMachineInput, + input: IsolateMachineInput | Mapping[str, Any], machine_id: str, *, timeout: Optional[float] = None, @@ -2125,13 +2640,30 @@ async def isolate_machine_async( Actions - Isolate machine Isolate a machine from network + + Swagger operation ID: `IsolateMachine`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to isolate. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/machines/{quote(str(machine_id), safe='')}/isolate" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2145,6 +2677,7 @@ async def isolate_machine_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2152,9 +2685,9 @@ async def isolate_machine_async( return json.loads(response.text) - async def unisolate_machine_async( + def unisolate_machine( self, - input: UnisolateMachineInput, + input: UnisolateMachineInput | Mapping[str, Any], machine_id: str, *, timeout: Optional[float] = None, @@ -2166,13 +2699,30 @@ async def unisolate_machine_async( Actions - Unisolate machine Unisolate a machine from network + + Swagger operation ID: `UnisolateMachine`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to unisolate. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/machines/{quote(str(machine_id), safe='')}/unisolate" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2186,6 +2736,7 @@ async def unisolate_machine_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2193,9 +2744,9 @@ async def unisolate_machine_async( return json.loads(response.text) - async def restrict_app_execution_async( + def restrict_app_execution( self, - input: RestrictAppExecutionInput, + input: RestrictAppExecutionInput | Mapping[str, Any], machine_id: str, *, timeout: Optional[float] = None, @@ -2208,6 +2759,23 @@ async def restrict_app_execution_async( Restrict execution of all applications on the machine except a predefined set + + Swagger operation ID: `RestrictAppExecution`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to restrict. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2217,7 +2785,7 @@ async def restrict_app_execution_async( f"/restrictCodeExecution" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2231,6 +2799,7 @@ async def restrict_app_execution_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2238,9 +2807,9 @@ async def restrict_app_execution_async( return json.loads(response.text) - async def unrestrict_app_execution_async( + def unrestrict_app_execution( self, - input: UnrestrictAppExecutionInput, + input: UnrestrictAppExecutionInput | Mapping[str, Any], machine_id: str, *, timeout: Optional[float] = None, @@ -2252,6 +2821,23 @@ async def unrestrict_app_execution_async( Actions - Remove app execution restriction Enable execution of any application on the machine + + Swagger operation ID: `UnrestrictAppExecution`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to unrestrict. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2261,7 +2847,7 @@ async def unrestrict_app_execution_async( f"/unrestrictCodeExecution" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2275,6 +2861,7 @@ async def unrestrict_app_execution_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2282,9 +2869,9 @@ async def unrestrict_app_execution_async( return json.loads(response.text) - async def run_antivirus_scan_async( + def run_antivirus_scan( self, - input: RunAntivirusScanInput, + input: RunAntivirusScanInput | Mapping[str, Any], machine_id: str, *, timeout: Optional[float] = None, @@ -2296,13 +2883,30 @@ async def run_antivirus_scan_async( Actions - Run antivirus scan Initiate Windows Defender Antivirus scan on a machine + + Swagger operation ID: `RunAntivirusScan`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to scan. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/machines/{quote(str(machine_id), safe='')}/runAntiVirusScan" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2316,6 +2920,7 @@ async def run_antivirus_scan_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2323,9 +2928,9 @@ async def run_antivirus_scan_async( return json.loads(response.text) - async def run_live_response_async( + def run_live_response( self, - input: RunLiveResponseInput, + input: RunLiveResponseInput | Mapping[str, Any], machine_id: str, *, timeout: Optional[float] = None, @@ -2337,13 +2942,30 @@ async def run_live_response_async( Actions - Run live response Run live response api commands for a single machine + + Swagger operation ID: `RunLiveResponse`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to run live response session on. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/machines/{quote(str(machine_id), safe='')}/runliveresponse" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2357,6 +2979,7 @@ async def run_live_response_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2364,27 +2987,49 @@ async def run_live_response_async( return json.loads(response.text) - async def get_remediation_activities_async( + def list_remediation_activities( self, + *, filter: Optional[str] = None, select: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, count: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Remediation tasks - Get list of remediation activities (Preview) Retrieve from Windows Defender ATP the remediation activities - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetRemediationActivities`. + + Args: + filter: Filters the results, using OData syntax. + select: Selects which properties to include in the response, + defaults to all. + orderby: Sorts the results. + top: Returns only the first n results. + skip: Skips the first n results. + count: Includes a count of the matching results in the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/remediationtasks" query_params = [] @@ -2420,11 +3065,18 @@ async def get_remediation_activities_async( query_params.append(f"$count={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2437,23 +3089,32 @@ async def get_remediation_activities_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def get_single_remediation_activity_async( + def get_single_remediation_activity( self, remediation_id: str, *, @@ -2466,13 +3127,29 @@ async def get_single_remediation_activity_async( RemediationActivities - Get single remediation activity (Preview) Retrieve from Windows Defender ATP a specific remediation activity + + Swagger operation ID: `GetSingleRemediationActivity`. + + Args: + remediation_id: The identifier of the remediation activity to + retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/remediationtasks/{quote(str(remediation_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2486,6 +3163,7 @@ async def get_single_remediation_activity_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2493,7 +3171,7 @@ async def get_single_remediation_activity_async( return json.loads(response.text) - async def get_remediation_activity_machine_list_async( + def list_get_remediation_activity_machine( self, remediation_id: str, *, @@ -2501,15 +3179,32 @@ async def get_remediation_activity_machine_list_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Remediation activities - Get list of related machines (Preview) Retrieve from Windows Defender ATP the related machines to a specific remediation activity - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetRemediationActivityMachineList`. + + Args: + remediation_id: The identifier of the remediation activity to + retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -2518,11 +3213,18 @@ async def get_remediation_activity_machine_list_async( f"/{quote(str(remediation_id), safe='')}" f"/machinereferences" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2535,43 +3237,74 @@ async def get_remediation_activity_machine_list_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_machines_async( + return ItemPaged(get_next, extract_data) + + def list_machines( self, + *, filter: Optional[str] = None, select: Optional[str] = None, orderby: Optional[str] = None, top: Optional[int] = None, skip: Optional[int] = None, count: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Machines - Get list of machines Retrieve from Windows Defender ATP the most recent machines - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMachines`. + + Args: + filter: Filters the results, using OData syntax. + select: Selects which properties to include in the response, + defaults to all. + orderby: Sorts the results. + top: Returns only the first n results. + skip: Skips the first n results. + count: Includes a count of the matching results in the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/machines" query_params = [] @@ -2607,11 +3340,18 @@ async def get_machines_async( query_params.append(f"$count={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -2624,23 +3364,32 @@ async def get_machines_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def get_single_machine_async( + def get_single_machine( self, machine_id: str, *, @@ -2653,13 +3402,28 @@ async def get_single_machine_async( Machines - Get single machine Retrieve from Windows Defender ATP a specific machine + + Swagger operation ID: `GetSingleMachine`. + + Args: + machine_id: The identifier of the machine to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/machines/{quote(str(machine_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -2673,6 +3437,7 @@ async def get_single_machine_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2680,9 +3445,9 @@ async def get_single_machine_async( return json.loads(response.text) - async def machine_tag_async( + def machine_tag( self, - input: MachineTagInput, + input: MachineTagInput | Mapping[str, Any], machine_id: str, *, timeout: Optional[float] = None, @@ -2694,13 +3459,31 @@ async def machine_tag_async( Machines - Tag machine Add or remove a tag to/from a machine + + Swagger operation ID: `MachineTag`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + machine_id: The ID of the machine to which the tag should be added + or removed. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/api/machines/{quote(str(machine_id), safe='')}/tags" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2714,6 +3497,7 @@ async def machine_tag_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -2721,9 +3505,9 @@ async def machine_tag_async( return json.loads(response.text) - async def advanced_hunting_schema_async( + def advanced_hunting_schema( self, - input: AdvancedHuntingSchemaInput, + input: AdvancedHuntingSchemaInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -2734,12 +3518,28 @@ async def advanced_hunting_schema_async( Advanced Hunting Schema Gets the schema for a Windows Defender ATP custom query + + Swagger operation ID: `AdvancedHuntingSchema`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/api/advancedqueries/schema" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -2753,6 +3553,7 @@ async def advanced_hunting_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/webex.py b/src/azure/connectors/webex.py index d212fa9..c286047 100644 --- a/src/azure/connectors/webex.py +++ b/src/azure/connectors/webex.py @@ -5,21 +5,55 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "WebexClient", + "CreateSpaceInput", + "CreateSpaceMemberInput", + "CreateSpaceMemberResponse", + "CreateSpaceResponse", + "CreateTeamMemberInput", + "CreateTeamMemberResponse", + "GetMessageDetailsResponse", + "GetMessagesResponse", + "GetMyOwnDetailsResponse", + "GetPeopleResponse", + "GetSpaceDetailResponse", + "GetSpacesResponse", + "MembershipsCreatedInput", + "MembershipsCreatedResponse", + "MembershipsDeletedInput", + "MembershipsDeletedResponse", + "MembershipsUpdatedInput", + "MembershipsUpdatedResponse", + "MessagesCreatedInput", + "MessagesCreatedResponse", + "MessagesDeletedInput", + "MessagesDeletedResponse", + "SendMessageInput", + "SendMessageResponse", + "SpaceCreatedInput", + "SpaceCreatedResponse", + "SpaceUpdatedInput", + "SpaceUpdatedResponse", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,25 +63,21 @@ class CreateSpaceMemberInput: Add Member to Space """ - is_moderator: Optional[bool] = field( - default=None, - metadata={"wire_name": "isModerator"}, - ) + is_moderator: bool = dataclass_field(metadata={"wire_name": "isModerator"}) """Is moderator?""" - person_email: Optional[str] = field( + person_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personEmail"}, ) """Email address""" - person_id: Optional[str] = field( + person_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personId"}, ) """Person ID of the new member""" - room_id: Optional[str] = field( - default=None, - metadata={"wire_name": "roomId"}, - ) + room_id: str = dataclass_field(metadata={"wire_name": "roomId"}) """Select a space""" @@ -57,42 +87,49 @@ class CreateSpaceMemberResponse: Response for Add Member to Space """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """created""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - is_moderator: Optional[bool] = field( + is_moderator: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isModerator"}, ) """isModerator""" - is_monitor: Optional[bool] = field( + is_monitor: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isMonitor"}, ) """isMonitor""" - person_display_name: Optional[str] = field( + person_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personDisplayName"}, ) """personDisplayName""" - person_email: Optional[str] = field( + person_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personEmail"}, ) """personEmail""" - person_id: Optional[str] = field( + person_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personId"}, ) """personId""" - person_org_id: Optional[str] = field( + person_org_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personOrgId"}, ) """personOrgId""" - room_id: Optional[str] = field( + room_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "roomId"}, ) """roomId""" @@ -104,7 +141,7 @@ class GetMessagesResponse: Response for Get Messages """ - items: Optional[List[Dict[str, Any]]] = None + items: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """items""" @@ -114,26 +151,29 @@ class SendMessageInput: Send a Message """ - files: Optional[List[str]] = None + files: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """files""" - markdown: Optional[str] = None + markdown: Optional[str] = dataclass_field(default=None, kw_only=True) """Message, in markdown format""" - room_id: Optional[str] = field( + room_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "roomId"}, ) """Select a recipient space""" - text: Optional[str] = None + text: Optional[str] = dataclass_field(default=None, kw_only=True) """ Message Text, in plain text, used for clients that do not support markdown """ - to_person_email: Optional[str] = field( + to_person_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "toPersonEmail"}, ) """The email address of the recipient when sending a private 1:1 message""" - to_person_id: Optional[str] = field( + to_person_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "toPersonId"}, ) """The ID of the recipient when sending a 1:1 message""" @@ -145,34 +185,39 @@ class SendMessageResponse: Response for Send a Message """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """created""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - person_email: Optional[str] = field( + person_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personEmail"}, ) """personEmail""" - person_id: Optional[str] = field( + person_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personId"}, ) """personId""" - room_id: Optional[str] = field( + room_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "roomId"}, ) """roomId""" - room_type: Optional[str] = field( + room_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "roomType"}, ) """roomType""" - text: Optional[str] = None + text: Optional[str] = dataclass_field(default=None, kw_only=True) """text""" - to_person_email: Optional[str] = field( + to_person_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "toPersonEmail"}, ) """toPersonEmail""" @@ -184,53 +229,61 @@ class GetMessageDetailsResponse: Response for Get Message Details """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """created""" - files: Optional[List[str]] = None + files: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """files""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - markdown: Optional[str] = None + markdown: Optional[str] = dataclass_field(default=None, kw_only=True) """markdown""" - mentioned_groups: Optional[List[str]] = field( + mentioned_groups: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mentionedGroups"}, ) """mentionedGroups""" - mentioned_people: Optional[List[str]] = field( + mentioned_people: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "mentionedPeople"}, ) """mentionedPeople""" - person_email: Optional[str] = field( + person_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personEmail"}, ) """personEmail""" - person_id: Optional[str] = field( + person_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personId"}, ) """personId""" - room_id: Optional[str] = field( + room_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "roomId"}, ) """roomId""" - room_type: Optional[str] = field( + room_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "roomType"}, ) """roomType""" - text: Optional[str] = None + text: Optional[str] = dataclass_field(default=None, kw_only=True) """text""" - to_person_email: Optional[str] = field( + to_person_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "toPersonEmail"}, ) """toPersonEmail""" - to_person_id: Optional[str] = field( + to_person_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "toPersonId"}, ) """toPersonId""" @@ -242,10 +295,11 @@ class GetPeopleResponse: Response for Get People """ - items: Optional[List[Dict[str, Any]]] = None + items: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """items""" - not_found_ids: Optional[List[str]] = field( + not_found_ids: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "notFoundIds"}, ) """notFoundIds""" @@ -257,52 +311,63 @@ class GetMyOwnDetailsResponse: Response for Get My Own Details """ - avatar: Optional[str] = None + avatar: Optional[str] = dataclass_field(default=None, kw_only=True) """avatar""" - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """created""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) """displayName""" - emails: Optional[List[str]] = None + emails: Optional[List[str]] = dataclass_field(default=None, kw_only=True) """emails""" - first_name: Optional[str] = field( + first_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "firstName"}, ) """firstName""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - last_activity: Optional[str] = field( + last_activity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastActivity"}, ) """lastActivity""" - last_name: Optional[str] = field( + last_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastName"}, ) """lastName""" - nick_name: Optional[str] = field( + nick_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nickName"}, ) """nickName""" - org_id: Optional[str] = field( + org_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "orgId"}, ) """orgId""" - phone_numbers: Optional[List[Dict[str, Any]]] = field( + phone_numbers: Optional[List[Dict[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "phoneNumbers"}, ) """phoneNumbers""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """status""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """type""" @@ -312,7 +377,7 @@ class GetSpacesResponse: Response for Get Spaces List """ - items: Optional[List[Dict[str, Any]]] = None + items: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """items""" @@ -322,12 +387,13 @@ class CreateSpaceInput: Create Space """ - team_id: Optional[str] = field( + team_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "teamId"}, ) """Optionally select a team""" - title: Optional[str] = None + title: str """Space Title""" @@ -337,28 +403,35 @@ class CreateSpaceResponse: Response for Create Space """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """created""" - creator_id: Optional[str] = field( + creator_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "creatorId"}, ) """creatorId""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - is_locked: Optional[bool] = field( + is_locked: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isLocked"}, ) """isLocked""" - last_activity: Optional[str] = field( + last_activity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastActivity"}, ) """lastActivity""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """title""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """type""" @@ -368,28 +441,35 @@ class GetSpaceDetailResponse: Response for Get Space Details """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """created""" - creator_id: Optional[str] = field( + creator_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "creatorId"}, ) """creatorId""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - is_locked: Optional[bool] = field( + is_locked: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isLocked"}, ) """isLocked""" - last_activity: Optional[str] = field( + last_activity: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "lastActivity"}, ) """lastActivity""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """title""" - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """type""" @@ -399,25 +479,21 @@ class CreateTeamMemberInput: Add Member to Team """ - is_moderator: Optional[bool] = field( - default=None, - metadata={"wire_name": "isModerator"}, - ) + is_moderator: bool = dataclass_field(metadata={"wire_name": "isModerator"}) """Is Moderator?""" - person_email: Optional[str] = field( + person_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personEmail"}, ) """Email address""" - person_id: Optional[str] = field( + person_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personId"}, ) """Person ID of the new member""" - team_id: Optional[str] = field( - default=None, - metadata={"wire_name": "teamId"}, - ) + team_id: str = dataclass_field(metadata={"wire_name": "teamId"}) """Select a team""" @@ -427,37 +503,43 @@ class CreateTeamMemberResponse: Response for Add Member to Team """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """created""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - is_moderator: Optional[bool] = field( + is_moderator: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isModerator"}, ) """isModerator""" - person_display_name: Optional[str] = field( + person_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personDisplayName"}, ) """personDisplayName""" - person_email: Optional[str] = field( + person_email: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personEmail"}, ) """personEmail""" - person_id: Optional[str] = field( + person_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personId"}, ) """personId""" - person_org_id: Optional[str] = field( + person_org_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "personOrgId"}, ) """personOrgId""" - team_id: Optional[str] = field( + team_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "teamId"}, ) """teamId""" @@ -469,16 +551,13 @@ class MembershipsUpdatedInput: When a membership is updated """ - event: Optional[str] = None + event: str """event""" - name: Optional[str] = None + name: str """name""" - resource: Optional[str] = None + resource: str """resource""" - target_url: Optional[str] = field( - default=None, - metadata={"wire_name": "targetUrl"}, - ) + target_url: str = dataclass_field(metadata={"wire_name": "targetUrl"}) """targetUrl""" @@ -488,26 +567,27 @@ class MembershipsUpdatedResponse: Response for When a membership is updated """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """created""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - target_url: Optional[str] = field( + target_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "targetUrl"}, ) """targetUrl""" - resource: Optional[str] = None + resource: Optional[str] = dataclass_field(default=None, kw_only=True) """resource""" - event: Optional[str] = None + event: Optional[str] = dataclass_field(default=None, kw_only=True) """event""" - filter: Optional[str] = None + filter: Optional[str] = dataclass_field(default=None, kw_only=True) """filter""" - secret: Optional[str] = None + secret: Optional[str] = dataclass_field(default=None, kw_only=True) """secret""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """status""" @@ -517,16 +597,13 @@ class MembershipsDeletedInput: When a membership is deleted """ - event: Optional[str] = None + event: str """event""" - name: Optional[str] = None + name: str """name""" - resource: Optional[str] = None + resource: str """resource""" - target_url: Optional[str] = field( - default=None, - metadata={"wire_name": "targetUrl"}, - ) + target_url: str = dataclass_field(metadata={"wire_name": "targetUrl"}) """targetUrl""" @@ -536,26 +613,27 @@ class MembershipsDeletedResponse: Response for When a membership is deleted """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """created""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - target_url: Optional[str] = field( + target_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "targetUrl"}, ) """targetUrl""" - resource: Optional[str] = None + resource: Optional[str] = dataclass_field(default=None, kw_only=True) """resource""" - event: Optional[str] = None + event: Optional[str] = dataclass_field(default=None, kw_only=True) """event""" - filter: Optional[str] = None + filter: Optional[str] = dataclass_field(default=None, kw_only=True) """filter""" - secret: Optional[str] = None + secret: Optional[str] = dataclass_field(default=None, kw_only=True) """secret""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """status""" @@ -565,16 +643,13 @@ class MembershipsCreatedInput: When a membership is created """ - event: Optional[str] = None + event: str """event""" - name: Optional[str] = None + name: str """name""" - resource: Optional[str] = None + resource: str """resource""" - target_url: Optional[str] = field( - default=None, - metadata={"wire_name": "targetUrl"}, - ) + target_url: str = dataclass_field(metadata={"wire_name": "targetUrl"}) """targetUrl""" @@ -584,26 +659,27 @@ class MembershipsCreatedResponse: Response for When a membership is created """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """created""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - target_url: Optional[str] = field( + target_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "targetUrl"}, ) """targetUrl""" - resource: Optional[str] = None + resource: Optional[str] = dataclass_field(default=None, kw_only=True) """resource""" - event: Optional[str] = None + event: Optional[str] = dataclass_field(default=None, kw_only=True) """event""" - filter: Optional[str] = None + filter: Optional[str] = dataclass_field(default=None, kw_only=True) """filter""" - secret: Optional[str] = None + secret: Optional[str] = dataclass_field(default=None, kw_only=True) """secret""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """status""" @@ -613,16 +689,13 @@ class MessagesCreatedInput: When a message is created """ - event: Optional[str] = None + event: str """event""" - name: Optional[str] = None + name: str """name""" - resource: Optional[str] = None + resource: str """resource""" - target_url: Optional[str] = field( - default=None, - metadata={"wire_name": "targetUrl"}, - ) + target_url: str = dataclass_field(metadata={"wire_name": "targetUrl"}) """targetUrl""" @@ -632,26 +705,27 @@ class MessagesCreatedResponse: Response for When a message is created """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """created""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - target_url: Optional[str] = field( + target_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "targetUrl"}, ) """targetUrl""" - resource: Optional[str] = None + resource: Optional[str] = dataclass_field(default=None, kw_only=True) """resource""" - event: Optional[str] = None + event: Optional[str] = dataclass_field(default=None, kw_only=True) """event""" - filter: Optional[str] = None + filter: Optional[str] = dataclass_field(default=None, kw_only=True) """filter""" - secret: Optional[str] = None + secret: Optional[str] = dataclass_field(default=None, kw_only=True) """secret""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """status""" @@ -661,16 +735,13 @@ class MessagesDeletedInput: When a message is deleted """ - event: Optional[str] = None + event: str """event""" - name: Optional[str] = None + name: str """name""" - resource: Optional[str] = None + resource: str """resource""" - target_url: Optional[str] = field( - default=None, - metadata={"wire_name": "targetUrl"}, - ) + target_url: str = dataclass_field(metadata={"wire_name": "targetUrl"}) """targetUrl""" @@ -680,26 +751,27 @@ class MessagesDeletedResponse: Response for When a message is deleted """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """created""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - target_url: Optional[str] = field( + target_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "targetUrl"}, ) """targetUrl""" - resource: Optional[str] = None + resource: Optional[str] = dataclass_field(default=None, kw_only=True) """resource""" - event: Optional[str] = None + event: Optional[str] = dataclass_field(default=None, kw_only=True) """event""" - filter: Optional[str] = None + filter: Optional[str] = dataclass_field(default=None, kw_only=True) """filter""" - secret: Optional[str] = None + secret: Optional[str] = dataclass_field(default=None, kw_only=True) """secret""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """status""" @@ -709,16 +781,13 @@ class SpaceCreatedInput: When a space is created """ - event: Optional[str] = None + event: str """event""" - name: Optional[str] = None + name: str """name""" - resource: Optional[str] = None + resource: str """resource""" - target_url: Optional[str] = field( - default=None, - metadata={"wire_name": "targetUrl"}, - ) + target_url: str = dataclass_field(metadata={"wire_name": "targetUrl"}) """targetUrl""" @@ -728,26 +797,27 @@ class SpaceCreatedResponse: Response for When a space is created """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """created""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - target_url: Optional[str] = field( + target_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "targetUrl"}, ) """targetUrl""" - resource: Optional[str] = None + resource: Optional[str] = dataclass_field(default=None, kw_only=True) """resource""" - event: Optional[str] = None + event: Optional[str] = dataclass_field(default=None, kw_only=True) """event""" - filter: Optional[str] = None + filter: Optional[str] = dataclass_field(default=None, kw_only=True) """filter""" - secret: Optional[str] = None + secret: Optional[str] = dataclass_field(default=None, kw_only=True) """secret""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """status""" @@ -757,16 +827,13 @@ class SpaceUpdatedInput: When a space is updated """ - event: Optional[str] = None + event: str """event""" - name: Optional[str] = None + name: str """name""" - resource: Optional[str] = None + resource: str """resource""" - target_url: Optional[str] = field( - default=None, - metadata={"wire_name": "targetUrl"}, - ) + target_url: str = dataclass_field(metadata={"wire_name": "targetUrl"}) """targetUrl""" @@ -776,26 +843,27 @@ class SpaceUpdatedResponse: Response for When a space is updated """ - created: Optional[str] = None + created: Optional[str] = dataclass_field(default=None, kw_only=True) """created""" - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """id""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """name""" - target_url: Optional[str] = field( + target_url: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "targetUrl"}, ) """targetUrl""" - resource: Optional[str] = None + resource: Optional[str] = dataclass_field(default=None, kw_only=True) """resource""" - event: Optional[str] = None + event: Optional[str] = dataclass_field(default=None, kw_only=True) """event""" - filter: Optional[str] = None + filter: Optional[str] = dataclass_field(default=None, kw_only=True) """filter""" - secret: Optional[str] = None + secret: Optional[str] = dataclass_field(default=None, kw_only=True) """secret""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """status""" @@ -807,16 +875,16 @@ class WebexClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -827,8 +895,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -836,8 +904,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -849,7 +917,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -864,9 +932,48 @@ def __init__( def connector_name(self) -> str: return "webex" - async def create_space_member_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def create_space_member( self, - input: CreateSpaceMemberInput, + input: CreateSpaceMemberInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -877,10 +984,26 @@ async def create_space_member_async( Add Member to Space Add a member to an existing space + + Swagger operation ID: `CreateSpaceMember`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/memberships" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -894,6 +1017,7 @@ async def create_space_member_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -901,23 +1025,48 @@ async def create_space_member_async( return json.loads(response.text) - async def get_messages_async( + def list_messages( self, room_id: str, + *, mentioned_people: Optional[str] = None, before_message: Optional[str] = None, before: Optional[str] = None, max: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Messages Get a list of recent messages for a space + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMessages`. + + Args: + room_id: List messages in a space for a given space ID. + mentioned_people: List messages where the caller is mentioned by + specifying \"me\" or the caller personId. + before_message: List messages sent before a message, by ID. + before: List messages sent before a date and time, in ISO8601 + format. + max: Limit the maximum number of messages in the response. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/messages" query_params = [] @@ -947,31 +1096,52 @@ async def get_messages_async( query_params.append(f"max={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item - async def send_message_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def send_message( self, - input: SendMessageInput, + input: SendMessageInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -982,10 +1152,26 @@ async def send_message_async( Send a Message Send a message to webex + + Swagger operation ID: `SendMessage`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/messages" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -999,6 +1185,7 @@ async def send_message_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1006,7 +1193,7 @@ async def send_message_async( return json.loads(response.text) - async def get_message_details_async( + def get_message_details( self, message_id: str, *, @@ -1019,13 +1206,28 @@ async def get_message_details_async( Get Message Details Shows details for a message, by message ID. + + Swagger operation ID: `GetMessageDetails`. + + Args: + message_id: The message ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1/messages/{quote(str(message_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1039,6 +1241,7 @@ async def get_message_details_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1046,20 +1249,41 @@ async def get_message_details_async( return json.loads(response.text) - async def get_people_async( + def list_people( self, + *, id: Optional[str] = None, email: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get People Lookup details and presence information for people in your organization + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetPeople`. + + Args: + id: List people by ID. Accepts up to 85 person IDs separated by + commas. + email: List people with this email address. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/people" query_params = [] @@ -1075,29 +1299,50 @@ async def get_people_async( query_params.append(f"email={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item + + return None, items() - async def get_my_own_details_async( + return ItemPaged(get_next, extract_data) + + def get_my_own_details( self, *, timeout: Optional[float] = None, @@ -1109,10 +1354,24 @@ async def get_my_own_details_async( Get My Own Details Lookup your own details + + Swagger operation ID: `GetMyOwnDetails`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/people/me" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1126,6 +1385,7 @@ async def get_my_own_details_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1133,21 +1393,44 @@ async def get_my_own_details_async( return json.loads(response.text) - async def get_spaces_async( + def list_spaces( self, + *, max: Optional[int] = None, type_: Optional[str] = None, sort_by: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get Spaces List This action retrieves a list of spaces + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetSpaces`. + + Args: + max: Maximum number of spaces to return. + type_: (group) only include group spaces, (direct) only include 1 + to 1 spaces, returns all if not specified. + sort_by: (id) the space id, (lastactivity) the last activity + timestamp, (created) space creation date. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/rooms" query_params = [] @@ -1168,31 +1451,52 @@ async def get_spaces_async( query_params.append(f"sortBy={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("items", []): + yield item - async def create_space_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def create_space( self, - input: CreateSpaceInput, + input: CreateSpaceInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1203,10 +1507,26 @@ async def create_space_async( Create Space Create space or team space + + Swagger operation ID: `CreateSpace`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/rooms" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1220,6 +1540,7 @@ async def create_space_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1227,7 +1548,7 @@ async def create_space_async( return json.loads(response.text) - async def get_space_detail_async( + def get_space_detail( self, room_id: str, *, @@ -1240,13 +1561,28 @@ async def get_space_detail_async( Get Space Details Return details of a given space + + Swagger operation ID: `GetSpaceDetail`. + + Args: + room_id: Select a space. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v1/rooms/{quote(str(room_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -1260,6 +1596,7 @@ async def get_space_detail_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -1267,9 +1604,9 @@ async def get_space_detail_async( return json.loads(response.text) - async def create_team_member_async( + def create_team_member( self, - input: CreateTeamMemberInput, + input: CreateTeamMemberInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -1280,10 +1617,26 @@ async def create_team_member_async( Add Member to Team Add a member to a team + + Swagger operation ID: `CreateTeamMember`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1/team/memberships" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -1297,6 +1650,7 @@ async def create_team_member_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/wordonlinebusiness.py b/src/azure/connectors/wordonlinebusiness.py index 74c4ab0..b89b9b6 100644 --- a/src/azure/connectors/wordonlinebusiness.py +++ b/src/azure/connectors/wordonlinebusiness.py @@ -5,21 +5,34 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "WordonlinebusinessClient", + "BlobMetadata", + "ContentBody", + "CreateFileItemInput", + "GetDrivesResponse", + "GetFileSchemaResponse", + "GetFiles", + "GetSourcesResponse", + "SensitivityLabelMetadata", +] + # Type Definitions @@ -29,7 +42,7 @@ class CreateFileItemInput: Populate a Microsoft Word template """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -42,7 +55,7 @@ class GetSourcesResponse: Response for Get sources """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -51,7 +64,7 @@ class GetDrivesResponse: Response for Get drives """ - value: Optional[List[Dict[str, Any]]] = None + value: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -60,7 +73,7 @@ class GetFileSchemaResponse: Response for Fetches the schema of the selected file """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -79,32 +92,48 @@ class BlobMetadata: Definition: BlobMetadata """ - id: Optional[str] = field(default=None, metadata={"wire_name": "Id"}) + id: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Id"}, + ) """The unique identifier of the file or folder.""" - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) """The name of the file or folder.""" - display_name: Optional[str] = field( + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) """The display name of the file or folder.""" - path: Optional[str] = field(default=None, metadata={"wire_name": "Path"}) + path: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Path"}, + ) """The path of the file or folder.""" - media_type: Optional[str] = field( + media_type: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "MediaType"}, ) """The media type of the file or folder.""" - is_folder: Optional[bool] = field( + is_folder: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "IsFolder"}, ) """ A boolean value (true, false) to indicate whether or not the blob is a folder. """ - file_locator: Optional[str] = field( + file_locator: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "FileLocator"}, ) """The file locator of the file or folder.""" @@ -116,7 +145,7 @@ class ContentBody: Definition: ContentBody """ - content: Optional[str] = None + content: str """Content of the word document""" @@ -128,16 +157,16 @@ class WordonlinebusinessClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -148,8 +177,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -157,8 +186,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -170,7 +199,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -185,9 +214,48 @@ def __init__( def connector_name(self) -> str: return "wordonlinebusiness" - async def create_file_item_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def create_file_item( self, - input: CreateFileItemInput, + input: CreateFileItemInput | Mapping[str, Any], source: str, drive: str, file: str, @@ -202,6 +270,28 @@ async def create_file_item_async( Reads a Microsoft Word template to then fill the template fields with selected dynamic values to generate a Word Document. + + Swagger operation ID: `CreateFileItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + drive: Select a document library from the drop-down. + file: Select a Word file through File Browse. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/templates/getFile" query_params = [] @@ -220,7 +310,7 @@ async def create_file_item_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -234,15 +324,16 @@ async def create_file_item_async( request_url, response.status, response.text, + response=response, ) return response.content - async def create_word_file_with_content_async( + def create_word_file_with_content( self, - input: ContentBody, - file_name: Optional[str] = None, + input: ContentBody | Mapping[str, Any], *, + file_name: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -253,6 +344,23 @@ async def create_word_file_with_content_async( Creates a Microsoft Word file with the given content in the root directory (use only from Copilot Studio) + + Swagger operation ID: `CreateWordFileWithContent`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + file_name: Name of the file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -267,7 +375,7 @@ async def create_word_file_with_content_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -281,6 +389,7 @@ async def create_word_file_with_content_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -288,14 +397,14 @@ async def create_word_file_with_content_async( return json.loads(response.text) - async def get_file_pdf_async( + def get_file_pdf( self, source: str, drive: str, file: str, + *, extract_sensitivity_label: Optional[bool] = None, fetch_sensitivity_label_metadata: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -305,6 +414,30 @@ async def get_file_pdf_async( Convert Word Document to PDF Gets a PDF version of the selected file + + Swagger operation ID: `GetFilePDF`. + + Args: + source: Select from the drop-down or specify one of the following: + - \"me\" - \"SharePoint Site URL\" - \"users/someone's UPN\" - + \"groups/group Id\" - \"sites/SharePoint Site URL:/teams/team + name:\" (colons are required). + drive: Select a document library from the drop-down. + file: Select a Word file through File Browse. + extract_sensitivity_label: Select if you want to extract + Sensitivity label ( false, true). + fetch_sensitivity_label_metadata: A boolean whether to fetch + sensitivity label Metadata for associated LabelId. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/api/templates/convertFile" @@ -336,7 +469,7 @@ async def get_file_pdf_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -350,62 +483,120 @@ async def get_file_pdf_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_sources_async( + def list_sources( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get sources Get a list of sources. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetSources`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/codeless/v1.0/sources" query_params = [] query_params.append("$top=" + quote("", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) - async def get_drives_async( + def list_drives( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get drives Get a list of drives. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetDrives`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/codeless/v1.0/drives" query_params = [] @@ -413,29 +604,50 @@ async def get_drives_async( query_params.append("$select=" + quote("", safe='')) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return None, items() - async def get_file_schema_async( + return ItemPaged(get_next, extract_data) + + def get_file_schema( self, source: str, drive: str, @@ -450,6 +662,23 @@ async def get_file_schema_async( Fetches the schema of the selected file Fetches the schema of the selected file. + + Swagger operation ID: `GetFileSchema`. + + Args: + source: source. + drive: drive. + file: file. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/api/templates/schema" query_params = [] @@ -468,7 +697,7 @@ async def get_file_schema_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -482,6 +711,7 @@ async def get_file_schema_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/wordpress.py b/src/azure/connectors/wordpress.py index bd5b0fb..8e10787 100644 --- a/src/azure/connectors/wordpress.py +++ b/src/azure/connectors/wordpress.py @@ -5,21 +5,40 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "WordpressClient", + "CreatePostModel", + "Error", + "ListPostsResponse", + "PostModel", + "PostResponse", + "PostsModel", + "Site", + "SiteInsightsModel", + "SiteList", + "SiteModel", + "SiteStatsChartModel", + "SiteStatsModel", + "TopPostModel", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +48,12 @@ class ListPostsResponse: Response for When a post is created """ - posts: Optional[List[PostResponse]] = None + posts: Optional[ + List[PostResponse | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Posts""" @@ -39,29 +63,30 @@ class SiteStatsModel: Response for Get site statistics """ - visitors_today: Optional[int] = None - visitors_yesterday: Optional[int] = None - visitors: Optional[int] = None - views_today: Optional[int] = None - views_yesterday: Optional[int] = None - views_best_day: Optional[str] = None - views_best_day_total: Optional[int] = None - views: Optional[int] = None - comments: Optional[int] = None - posts: Optional[int] = None - followers_blog: Optional[int] = None - followers_comments: Optional[int] = None - comments_per_month: Optional[int] = None - comments_most_active_recent_day: Optional[str] = None - comments_most_active_time: Optional[str] = None - comments_spam: Optional[int] = None - categories: Optional[int] = None - tags: Optional[int] = None - shares: Optional[int] = None - shares_twitter: Optional[int] = None - shares_facebook: Optional[int] = None - shares_press_this: Optional[int] = field( + visitors_today: Optional[int] = dataclass_field(default=None, kw_only=True) + visitors_yesterday: Optional[int] = dataclass_field(default=None, kw_only=True) + visitors: Optional[int] = dataclass_field(default=None, kw_only=True) + views_today: Optional[int] = dataclass_field(default=None, kw_only=True) + views_yesterday: Optional[int] = dataclass_field(default=None, kw_only=True) + views_best_day: Optional[str] = dataclass_field(default=None, kw_only=True) + views_best_day_total: Optional[int] = dataclass_field(default=None, kw_only=True) + views: Optional[int] = dataclass_field(default=None, kw_only=True) + comments: Optional[int] = dataclass_field(default=None, kw_only=True) + posts: Optional[int] = dataclass_field(default=None, kw_only=True) + followers_blog: Optional[int] = dataclass_field(default=None, kw_only=True) + followers_comments: Optional[int] = dataclass_field(default=None, kw_only=True) + comments_per_month: Optional[int] = dataclass_field(default=None, kw_only=True) + comments_most_active_recent_day: Optional[str] = dataclass_field(default=None, kw_only=True) + comments_most_active_time: Optional[str] = dataclass_field(default=None, kw_only=True) + comments_spam: Optional[int] = dataclass_field(default=None, kw_only=True) + categories: Optional[int] = dataclass_field(default=None, kw_only=True) + tags: Optional[int] = dataclass_field(default=None, kw_only=True) + shares: Optional[int] = dataclass_field(default=None, kw_only=True) + shares_twitter: Optional[int] = dataclass_field(default=None, kw_only=True) + shares_facebook: Optional[int] = dataclass_field(default=None, kw_only=True) + shares_press_this: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "shares_press-this"}, ) @@ -72,42 +97,57 @@ class PostModel: Response for Get post """ - id: Optional[int] = field(default=None, metadata={"wire_name": "ID"}) - site_id: Optional[int] = field( + id: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID"}, + ) + site_id: Optional[int] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "site_ID"}, ) - date: Optional[str] = None - modified: Optional[str] = None - title: Optional[str] = None - u_r_l: Optional[str] = field(default=None, metadata={"wire_name": "URL"}) - short_u_r_l: Optional[str] = field( + date: Optional[str] = dataclass_field(default=None, kw_only=True) + modified: Optional[str] = dataclass_field(default=None, kw_only=True) + title: Optional[str] = dataclass_field(default=None, kw_only=True) + u_r_l: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "URL"}, + ) + short_u_r_l: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "short_URL"}, ) - content: Optional[str] = None - excerpt: Optional[str] = None - slug: Optional[str] = None - guid: Optional[str] = None - status: Optional[str] = None - sticky: Optional[bool] = None - password: Optional[str] = None - parent: Optional[Any] = None - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) - likes_enabled: Optional[bool] = None - sharing_enabled: Optional[bool] = None - like_count: Optional[int] = None - i_like: Optional[bool] = None - is_reblogged: Optional[bool] = None - is_following: Optional[bool] = None - global_id: Optional[str] = field( + content: Optional[str] = dataclass_field(default=None, kw_only=True) + excerpt: Optional[str] = dataclass_field(default=None, kw_only=True) + slug: Optional[str] = dataclass_field(default=None, kw_only=True) + guid: Optional[str] = dataclass_field(default=None, kw_only=True) + status: Optional[str] = dataclass_field(default=None, kw_only=True) + sticky: Optional[bool] = dataclass_field(default=None, kw_only=True) + password: Optional[str] = dataclass_field(default=None, kw_only=True) + parent: Optional[Any] = dataclass_field(default=None, kw_only=True) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) + likes_enabled: Optional[bool] = dataclass_field(default=None, kw_only=True) + sharing_enabled: Optional[bool] = dataclass_field(default=None, kw_only=True) + like_count: Optional[int] = dataclass_field(default=None, kw_only=True) + i_like: Optional[bool] = dataclass_field(default=None, kw_only=True) + is_reblogged: Optional[bool] = dataclass_field(default=None, kw_only=True) + is_following: Optional[bool] = dataclass_field(default=None, kw_only=True) + global_id: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "global_ID"}, ) - featured_image: Optional[str] = None - post_thumbnail: Optional[Dict[str, Any]] = None - format: Optional[str] = None - geo: Optional[bool] = None + featured_image: Optional[str] = dataclass_field(default=None, kw_only=True) + post_thumbnail: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) + format: Optional[str] = dataclass_field(default=None, kw_only=True) + geo: Optional[bool] = dataclass_field(default=None, kw_only=True) @dataclass @@ -116,7 +156,12 @@ class SiteList: Response for List sites """ - sites: Optional[List[Site]] = None + sites: Optional[ + List[Site | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """List of sites""" @@ -126,33 +171,41 @@ class Site: Definition: Site """ - id: Optional[int] = field(default=None, metadata={"wire_name": "ID"}) + id: Optional[int] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "ID"}, + ) """Site ID""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Site Name""" - description: Optional[str] = None + description: Optional[str] = dataclass_field(default=None, kw_only=True) """Site Description""" - u_r_l: Optional[str] = field(default=None, metadata={"wire_name": "URL"}) + u_r_l: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "URL"}, + ) """Site URL""" - is_multisite: Optional[bool] = None + is_multisite: Optional[bool] = dataclass_field(default=None, kw_only=True) """ Whether the site is a Multisite site or not. Always true for WP.com sites. """ - post_count: Optional[int] = None + post_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of posts the site has""" - subscribers_count: Optional[int] = None + subscribers_count: Optional[int] = dataclass_field(default=None, kw_only=True) """The number of subscribers the site has""" - lang: Optional[str] = None + lang: Optional[str] = dataclass_field(default=None, kw_only=True) """Language""" - visible: Optional[bool] = None + visible: Optional[bool] = dataclass_field(default=None, kw_only=True) """Site visibility""" - is_private: Optional[bool] = None + is_private: Optional[bool] = dataclass_field(default=None, kw_only=True) """Is site private""" - single_user_site: Optional[bool] = None + single_user_site: Optional[bool] = dataclass_field(default=None, kw_only=True) """Is single user site""" - is_vip: Optional[bool] = None + is_vip: Optional[bool] = dataclass_field(default=None, kw_only=True) """Is VIP""" - is_following: Optional[bool] = None + is_following: Optional[bool] = dataclass_field(default=None, kw_only=True) """Is Following""" @@ -168,10 +221,10 @@ class SiteInsightsModel: Definition: SiteInsightsModel """ - highest_hour: Optional[int] = None - highest_hour_percent: Optional[float] = None - highest_day_of_week: Optional[int] = None - highest_day_percent: Optional[float] = None + highest_hour: Optional[int] = dataclass_field(default=None, kw_only=True) + highest_hour_percent: Optional[float] = dataclass_field(default=None, kw_only=True) + highest_day_of_week: Optional[int] = dataclass_field(default=None, kw_only=True) + highest_day_percent: Optional[float] = dataclass_field(default=None, kw_only=True) TopPostModel = List[Dict[str, Any]] @@ -183,20 +236,33 @@ class PostResponse: Definition: PostResponse """ - id: Optional[int] = field(default=None, metadata={"wire_name": "ID"}) - comment_count: Optional[int] = None - site_id: Optional[int] = field( + id: Optional[int] = dataclass_field( default=None, + kw_only=True, + metadata={"wire_name": "ID"}, + ) + comment_count: Optional[int] = dataclass_field(default=None, kw_only=True) + site_id: Optional[int] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "site_ID"}, ) - date: Optional[str] = None - modified: Optional[str] = None - title: Optional[str] = None - u_r_l: Optional[str] = field(default=None, metadata={"wire_name": "URL"}) - slug: Optional[str] = None - guid: Optional[str] = None - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) - like_count: Optional[int] = None + date: Optional[str] = dataclass_field(default=None, kw_only=True) + modified: Optional[str] = dataclass_field(default=None, kw_only=True) + title: Optional[str] = dataclass_field(default=None, kw_only=True) + u_r_l: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "URL"}, + ) + slug: Optional[str] = dataclass_field(default=None, kw_only=True) + guid: Optional[str] = dataclass_field(default=None, kw_only=True) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) + like_count: Optional[int] = dataclass_field(default=None, kw_only=True) PostsModel = List[Dict[str, Any]] @@ -208,13 +274,13 @@ class CreatePostModel: Definition: CreatePostModel """ - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """The title of the post""" - content: Optional[str] = None + content: Optional[str] = dataclass_field(default=None, kw_only=True) """The content of the post""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """The status of the post""" - tags: Optional[str] = None + tags: Optional[str] = dataclass_field(default=None, kw_only=True) """The tags for post""" @@ -224,9 +290,9 @@ class Error: Definition: Error """ - code: Optional[int] = None - message: Optional[str] = None - fields: Optional[str] = None + code: Optional[int] = dataclass_field(default=None, kw_only=True) + message: Optional[str] = dataclass_field(default=None, kw_only=True) + fields: Optional[str] = dataclass_field(default=None, kw_only=True) # Client Class @@ -237,16 +303,16 @@ class WordpressClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -257,8 +323,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -266,8 +332,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -279,7 +345,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -294,7 +360,46 @@ def __init__( def connector_name(self) -> str: return "wordpress" - async def site_stats_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def site_stats( self, site_id: str, *, @@ -307,6 +412,21 @@ async def site_stats_async( Get site statistics Get statistics for a specified site + + Swagger operation ID: `SiteStats`. + + Args: + site_id: The site's id or domain. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -317,7 +437,7 @@ async def site_stats_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -331,6 +451,7 @@ async def site_stats_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -338,7 +459,7 @@ async def site_stats_async( return json.loads(response.text) - async def get_async( + def get( self, site_id: str, post_id: str, @@ -352,6 +473,22 @@ async def get_async( Get post Get post + + Swagger operation ID: `GetPost`. + + Args: + site_id: The site's id or domain. + post_id: The post Id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -361,7 +498,7 @@ async def get_async( f"/{quote(str(post_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -375,6 +512,7 @@ async def get_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -382,9 +520,9 @@ async def get_async( return json.loads(response.text) - async def create_async( + def create( self, - input: CreatePostModel, + input: CreatePostModel | Mapping[str, Any], site_id: str, *, timeout: Optional[float] = None, @@ -396,13 +534,30 @@ async def create_async( Create post Create post + + Swagger operation ID: `CreatePost`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + site_id: The site's id or domain. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/sites/{quote(str(site_id), safe='')}/posts/new" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -416,6 +571,7 @@ async def create_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -423,18 +579,36 @@ async def create_async( return json.loads(response.text) - async def list_sites_async( + def list_sites( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ List sites List sites + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `ListSites`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/me/sites" query_params = [] @@ -447,27 +621,48 @@ async def list_sites_async( ) if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("sites", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/src/azure/connectors/yammer.py b/src/azure/connectors/yammer.py index 36b4835..15855f3 100644 --- a/src/azure/connectors/yammer.py +++ b/src/azure/connectors/yammer.py @@ -5,21 +5,37 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "YammerClient", + "LikedBy", + "Message", + "MessageBody", + "MessageList", + "Network", + "PageableMessageList", + "PostOperationRequest", + "Topic", + "User", + "YammerEntity", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,11 +45,11 @@ class Network: Response for Get my networks """ - id: Optional[str] = None + id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique identifier of the network.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Summary of the network.""" - permalink: Optional[str] = None + permalink: Optional[str] = dataclass_field(default=None, kw_only=True) """Web link to the network page.""" @@ -43,11 +59,15 @@ class YammerEntity: Response for Get groups """ - type_: Optional[str] = field(default=None, metadata={"wire_name": "type"}) + type_: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "type"}, + ) """Details of the Viva Engage entity.""" - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique identifier of the group.""" - full_name: Optional[str] = None + full_name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the Viva Engage entity.""" @@ -57,25 +77,25 @@ class User: Response for Get user details """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Username.""" - job_title: Optional[str] = None + job_title: Optional[str] = dataclass_field(default=None, kw_only=True) """User job title.""" - location: Optional[str] = None + location: Optional[str] = dataclass_field(default=None, kw_only=True) """User location.""" - full_name: Optional[str] = None + full_name: Optional[str] = dataclass_field(default=None, kw_only=True) """User full name.""" - first_name: Optional[str] = None + first_name: Optional[str] = dataclass_field(default=None, kw_only=True) """User first name.""" - last_name: Optional[str] = None + last_name: Optional[str] = dataclass_field(default=None, kw_only=True) """User last name.""" - web_url: Optional[str] = None + web_url: Optional[str] = dataclass_field(default=None, kw_only=True) """User profile url.""" - email: Optional[str] = None + email: Optional[str] = dataclass_field(default=None, kw_only=True) """User email.""" - birth_date: Optional[str] = None + birth_date: Optional[str] = dataclass_field(default=None, kw_only=True) """User birth date.""" - mugshot_url: Optional[str] = None + mugshot_url: Optional[str] = dataclass_field(default=None, kw_only=True) """User photo url.""" @@ -85,9 +105,15 @@ class PageableMessageList: Response for Get all messages """ - value: Optional[List[Message]] = None - next_link: Optional[str] = field( + value: Optional[ + List[Message | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nextLink"}, ) """The URL to retrieve the next page.""" @@ -99,7 +125,12 @@ class MessageList: Response for When there is a new message in my followed feed """ - messages: Optional[List[Message]] = None + messages: Optional[ + List[Message | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """messages""" @@ -109,45 +140,45 @@ class Message: Definition: Message """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """ID associated with the post.""" - content_excerpt: Optional[str] = None + content_excerpt: Optional[str] = dataclass_field(default=None, kw_only=True) """Text Content of the post.""" - sender_id: Optional[int] = None + sender_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique ID of user who posted the message.""" - replied_to_id: Optional[int] = None + replied_to_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ID of the message to which this message is a reply.""" - created_at: Optional[str] = None + created_at: Optional[str] = dataclass_field(default=None, kw_only=True) """Time at which the message was created.""" - network_id: Optional[int] = None + network_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Id of the network message is associated with.""" - message_type: Optional[str] = None + message_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the message type.""" - sender_type: Optional[str] = None + sender_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Description of the type of sender.""" - url: Optional[str] = None + url: Optional[str] = dataclass_field(default=None, kw_only=True) """API url of the post.""" - web_url: Optional[str] = None + web_url: Optional[str] = dataclass_field(default=None, kw_only=True) """Web url of the post.""" - group_id: Optional[int] = None + group_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique ID of group who posted the message.""" - body: Optional[MessageBody] = None - thread_id: Optional[int] = None + body: Optional[MessageBody | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + thread_id: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique ID of thread.""" - direct_message: Optional[bool] = None + direct_message: Optional[bool] = dataclass_field(default=None, kw_only=True) """Flag to specify if the post is a a direct message.""" - client_type: Optional[str] = None + client_type: Optional[str] = dataclass_field(default=None, kw_only=True) """Type of the client.""" - client_url: Optional[str] = None + client_url: Optional[str] = dataclass_field(default=None, kw_only=True) """Web link of the client.""" - language: Optional[str] = None + language: Optional[str] = dataclass_field(default=None, kw_only=True) """Language used in the message.""" - notified_user_ids: Optional[List[int]] = None + notified_user_ids: Optional[List[int]] = dataclass_field(default=None, kw_only=True) """Details of users notified.""" - privacy: Optional[str] = None + privacy: Optional[str] = dataclass_field(default=None, kw_only=True) """Details of the privacy associated with the message.""" - liked_by: Optional[LikedBy] = None - system_message: Optional[bool] = None + liked_by: Optional[LikedBy | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + system_message: Optional[bool] = dataclass_field(default=None, kw_only=True) """Flag to specify if the post is a system generated message or not.""" @@ -157,9 +188,9 @@ class Topic: Definition: Topic """ - id: Optional[int] = None + id: Optional[int] = dataclass_field(default=None, kw_only=True) """Unique identifier of the topic.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name of the topic.""" @@ -169,20 +200,20 @@ class PostOperationRequest: Definition: PostOperationRequest """ - group_id: Optional[int] = None + group_id: int """The group to post a message to (0 = All Company/Network).""" - body: Optional[str] = None + body: str """Your message to be posted into your network.""" - replied_to_id: Optional[int] = None + replied_to_id: Optional[int] = dataclass_field(default=None, kw_only=True) """The message ID this message is in reply to.""" - direct_to_id: Optional[int] = None + direct_to_id: Optional[int] = dataclass_field(default=None, kw_only=True) """ If set, a private message will be sent directly to the user with the indicated ID. """ - broadcast: Optional[bool] = None + broadcast: Optional[bool] = dataclass_field(default=None, kw_only=True) """Post message as an announcement to all users in a group.""" - title: Optional[str] = None + title: Optional[str] = dataclass_field(default=None, kw_only=True) """Title of the message to be posted.""" @@ -192,11 +223,11 @@ class MessageBody: Definition: MessageBody """ - parsed: Optional[str] = None + parsed: Optional[str] = dataclass_field(default=None, kw_only=True) """Parsed text format.""" - plain: Optional[str] = None + plain: Optional[str] = dataclass_field(default=None, kw_only=True) """Plain text format.""" - rich: Optional[str] = None + rich: Optional[str] = dataclass_field(default=None, kw_only=True) """Rich text format.""" @@ -206,9 +237,9 @@ class LikedBy: Definition: LikedBy """ - count: Optional[int] = None + count: Optional[int] = dataclass_field(default=None, kw_only=True) """Number of distinct likes.""" - names: Optional[List[Dict[str, Any]]] = None + names: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """List of people who liked the post.""" @@ -220,16 +251,16 @@ class YammerClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -240,8 +271,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -249,8 +280,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -262,7 +293,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -284,7 +315,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -316,57 +347,117 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def get_networks_async( + def list_networks( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get my networks Gets all the networks that the user belongs to. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetNetworks`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/networks.json" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url - async def get_groups_async( + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_groups( self, + *, network_id: Optional[str] = None, mine: Optional[int] = None, show_all_company_group: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get groups Gets all groups. If mine = 1, get only groups to which the user belongs + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetGroups`. + + Args: + network_id: Network ID. + mine: Used for getting groups which user is part of. + show_all_company_group: Used for showing All Company Group. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/groups.json" query_params = [] @@ -387,29 +478,50 @@ async def get_groups_async( query_params.append(f"showAllCompanyGroup={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else [] + + def items() -> Iterator[dict[str, Any]]: + for item in page: + yield item + + return None, items() - async def get_user_details_by_id_async( + return ItemPaged(get_next, extract_data) + + def get_user_details_by_id( self, user_id: int, *, @@ -422,13 +534,28 @@ async def get_user_details_by_id_async( Get user details This operation returns user profile details. + + Swagger operation ID: `GetUserDetailsById`. + + Args: + user_id: Unique identifier of the user. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/users/{quote(str(user_id), safe='')}.json" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -442,6 +569,7 @@ async def get_user_details_by_id_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -449,7 +577,7 @@ async def get_user_details_by_id_async( return json.loads(response.text) - async def like_message_async( + def like_message( self, message_id: str, *, @@ -462,6 +590,21 @@ async def like_message_async( Like message This operation is used to like the specified message. + + Swagger operation ID: `LikeMessage`. + + Args: + message_id: Unique id of the message. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/messages/liked_by/current.json" @@ -474,7 +617,7 @@ async def like_message_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -488,21 +631,22 @@ async def like_message_async( request_url, response.status, response.text, + response=response, ) - async def get_all_messages_async( + def list_all_messages( self, + *, network_id: Optional[str] = None, older_than: Optional[int] = None, newer_than: Optional[int] = None, threaded: Optional[str] = None, limit: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get all messages @@ -510,8 +654,43 @@ async def get_all_messages_async( Engage network. Corresponds to \"All\" conversations in the Viva Engage web interface. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetAllMessagesV3`. + + Args: + network_id: Network ID. + older_than: Returns messages older than the message ID specified as + a numeric string. This is useful for paginating messages. For + example, if you're currently viewing 20 messages and the oldest + is number 2912, you could append \"?older_than=2912″ to your + request to get the 20 messages prior to those you're seeing. + newer_than: Returns messages newer than the message ID specified as + a numeric string. This should be used when polling for new + messages. If you're looking at messages, and the most recent + message returned is 3516, you can make a request with the + parameter \"?newer_than=3516″ to ensure that you do not get + duplicate copies of messages already on your page. + threaded: Threaded=true will only return the thread starter (first + message) for each thread. This parameter is intended for apps + which need to display message threads collapsed. + threaded=extended will return the thread starter messages and + the two most recent messages all ordered by activity, as they + are viewed in the default view on the Viva Engage web + interface. + limit: Return only the specified number of messages. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v3/messages.json" query_params = [] @@ -542,11 +721,18 @@ async def get_all_messages_async( query_params.append(f"limit={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -559,35 +745,44 @@ async def get_all_messages_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def get_messages_following_async( + def list_messages_following( self, + *, network_id: Optional[str] = None, older_than: Optional[int] = None, newer_than: Optional[int] = None, threaded: Optional[str] = None, limit: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get the messages from my Following feed @@ -595,8 +790,43 @@ async def get_messages_following_async( conversations involving people, groups and topics that the user is following. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMessagesFollowingV3`. + + Args: + network_id: Unique identifier of the network. + older_than: Returns messages older than the message ID specified as + a numeric string. This is useful for paginating messages. For + example, if you're currently viewing 20 messages and the oldest + is number 2912, you could append \"?older_than=2912″ to your + request to get the 20 messages prior to those you're seeing. + newer_than: Returns messages newer than the message ID specified as + a numeric string. This should be used when polling for new + messages. If you're looking at messages, and the most recent + message returned is 3516, you can make a request with the + parameter \"?newer_than=3516″ to ensure that you do not get + duplicate copies of messages already on your page. + threaded: Threaded=true will only return the thread starter (first + message) for each thread. This parameter is intended for apps + which need to display message threads collapsed. + threaded=extended will return the thread starter messages and + the two most recent messages all ordered by activity, as they + are viewed in the default view on the Viva Engage web + interface. + limit: Return only the specified number of messages. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/v3/messages/following.json" @@ -629,11 +859,18 @@ async def get_messages_following_async( query_params.append(f"limit={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -646,43 +883,87 @@ async def get_messages_following_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def get_messages_in_group_async( + return ItemPaged(get_next, extract_data) + + def list_messages_in_group( self, group_id: int, + *, network_id: Optional[str] = None, older_than: Optional[int] = None, newer_than: Optional[int] = None, threaded: Optional[str] = None, limit: Optional[int] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get messages in a group This operation returns the messages posted in a group. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMessagesInGroupV3`. + + Args: + group_id: Unique identifier of the group. + network_id: Unique identifier of the network. + older_than: Returns messages in threads where the thread's latest + message is older than the specified message ID. Any thread with + a most recent message ID that is newer than or equal to the + specified ID will not have any of its messages returned by this + query. + newer_than: Returns messages in threads where the thread's latest + message is newer than the specified message ID. Any thread with + a most recent message ID that is older than or equal to the + specified ID will not have any of its messages returned by this + query. + threaded: Threaded=true will only return the thread starter (first + message) for each thread. This parameter is intended for apps + which need to display message threads collapsed. + threaded=extended will return the thread starter messages and + the two most recent messages all ordered by activity, as they + are viewed in the default view on the Viva Engage web + interface. + limit: Return only the specified number of messages. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -716,11 +997,18 @@ async def get_messages_in_group_async( query_params.append(f"limit={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -733,23 +1021,32 @@ async def get_messages_in_group_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def get_messages_in_thread_async( + def list_messages_in_thread( self, thread_id: int, *, @@ -757,24 +1054,47 @@ async def get_messages_in_thread_async( headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get messages in a thread This operation returns the messages posted in a thread. - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetMessagesInThreadV3`. + + Args: + thread_id: Unique identifier of the thread. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/v3/messages/in_thread/{quote(str(thread_id), safe='')}.json" ) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -787,27 +1107,36 @@ async def get_messages_in_thread_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return continuation_token, items() - async def post_message_async( + return ItemPaged(get_next, extract_data) + + def post_message( self, - input: PostOperationRequest, - network_id: Optional[str] = None, + input: PostOperationRequest | Mapping[str, Any], *, + network_id: Optional[str] = None, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -819,6 +1148,23 @@ async def post_message_async( This operation is used to post a Message to a Group or All Company Feed. If group ID is provided, message will be posted to the specified group else it will be posted in All Company Feed. + + Swagger operation ID: `PostMessageV2`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + network_id: Unique id of the network. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v2/messages.json" query_params = [] @@ -830,7 +1176,7 @@ async def post_message_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -844,6 +1190,7 @@ async def post_message_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/zendesk.py b/src/azure/connectors/zendesk.py index 23d33ea..639c2c9 100644 --- a/src/azure/connectors/zendesk.py +++ b/src/azure/connectors/zendesk.py @@ -5,21 +5,44 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, AsyncIterator, Dict, List, Any, Mapping -from urllib.parse import quote, urlsplit +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "ZendeskClient", + "BlobDataSetsMetadata", + "DataSet", + "DataSetsList", + "DataSetsMetadata", + "GetCurrentUserInfoResponse", + "Item", + "ItemsList", + "ObjectEntity", + "SearchResult", + "Table", + "TableCapabilitiesMetadata", + "TableFilterRestrictionsMetadata", + "TableMetadata", + "TableSelectRestrictionsMetadata", + "TableSortRestrictionsMetadata", + "TablesList", + "TabularDataSetsMetadata", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +52,12 @@ class TablesList: Response for Get tables """ - value: Optional[List[Table]] = None + value: Optional[ + List[Table | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -38,9 +66,15 @@ class ItemsList: Response for Get items """ - value: Optional[List[Item]] = None - next_link: Optional[str] = field( + value: Optional[ + List[Item | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) + next_link: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "@odata.nextLink"}, ) """The URL to retrieve the next page.""" @@ -52,8 +86,9 @@ class Item: Response for Create Item """ - dynamic_properties: Optional[Dict[str, ObjectEntity]] = field( + dynamic_properties: Optional[Dict[str, ObjectEntity | Mapping[str, Any]]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "dynamicProperties"}, ) @@ -64,7 +99,7 @@ class SearchResult: Response for Search Articles """ - results: Optional[List[Dict[str, Any]]] = None + results: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) @dataclass @@ -73,19 +108,22 @@ class TableMetadata: Response for Get item metadata """ - name: Optional[str] = None - title: Optional[str] = None - x_ms_permission: Optional[str] = field( + name: Optional[str] = dataclass_field(default=None, kw_only=True) + title: Optional[str] = dataclass_field(default=None, kw_only=True) + x_ms_permission: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-permission"}, ) - x_ms_capabilities: Optional[TableCapabilitiesMetadata] = field( + x_ms_capabilities: Optional[TableCapabilitiesMetadata | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "x-ms-capabilities"}, ) - schema: Optional[ObjectEntity] = None - referenced_entities: Optional[ObjectEntity] = field( + schema: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field(default=None, kw_only=True) + referenced_entities: Optional[ObjectEntity | Mapping[str, Any]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "referencedEntities"}, ) @@ -96,8 +134,18 @@ class DataSetsMetadata: Definition: DataSetsMetadata """ - tabular: Optional[TabularDataSetsMetadata] = None - blob: Optional[BlobDataSetsMetadata] = None + tabular: Optional[ + TabularDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) + blob: Optional[ + BlobDataSetsMetadata | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -106,21 +154,25 @@ class TabularDataSetsMetadata: Definition: TabularDataSetsMetadata """ - source: Optional[str] = None - display_name: Optional[str] = field( + source: Optional[str] = dataclass_field(default=None, kw_only=True) + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) - table_display_name: Optional[str] = field( + table_display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tableDisplayName"}, ) - table_plural_name: Optional[str] = field( + table_plural_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "tablePluralName"}, ) @@ -131,13 +183,15 @@ class BlobDataSetsMetadata: Definition: BlobDataSetsMetadata """ - source: Optional[str] = None - display_name: Optional[str] = field( + source: Optional[str] = dataclass_field(default=None, kw_only=True) + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "displayName"}, ) - url_encoding: Optional[str] = field( + url_encoding: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "urlEncoding"}, ) @@ -148,25 +202,36 @@ class TableCapabilitiesMetadata: Definition: TableCapabilitiesMetadata """ - sort_restrictions: Optional[TableSortRestrictionsMetadata] = field( + sort_restrictions: Optional[ + TableSortRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "sortRestrictions"}, ) - filter_restrictions: Optional[TableFilterRestrictionsMetadata] = field( + filter_restrictions: Optional[ + TableFilterRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterRestrictions"}, ) - select_restrictions: Optional[TableSelectRestrictionsMetadata] = field( + select_restrictions: Optional[ + TableSelectRestrictionsMetadata | Mapping[str, Any] + ] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "selectRestrictions"}, ) - is_only_server_pagable: Optional[bool] = field( + is_only_server_pagable: Optional[bool] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "isOnlyServerPagable"}, ) """Server paging restrictions""" - filter_function_support: Optional[List[str]] = field( + filter_function_support: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "filterFunctionSupport"}, ) @@ -177,7 +242,7 @@ class ObjectEntity: Definition: Object """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -190,15 +255,17 @@ class TableSortRestrictionsMetadata: Definition: TableSortRestrictionsMetadata """ - sortable: Optional[bool] = None + sortable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has sortable columns""" - unsortable_properties: Optional[List[str]] = field( + unsortable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "unsortableProperties"}, ) """List of unsortable properties""" - ascending_only_properties: Optional[List[str]] = field( + ascending_only_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "ascendingOnlyProperties"}, ) """List of properties which support ascending order only""" @@ -210,15 +277,17 @@ class TableFilterRestrictionsMetadata: Definition: TableFilterRestrictionsMetadata """ - filterable: Optional[bool] = None + filterable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has filterable columns""" - non_filterable_properties: Optional[List[str]] = field( + non_filterable_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "nonFilterableProperties"}, ) """List of non filterable properties""" - required_properties: Optional[List[str]] = field( + required_properties: Optional[List[str]] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "requiredProperties"}, ) """List of required properties""" @@ -230,7 +299,7 @@ class TableSelectRestrictionsMetadata: Definition: TableSelectRestrictionsMetadata """ - selectable: Optional[bool] = None + selectable: Optional[bool] = dataclass_field(default=None, kw_only=True) """Indicates whether this table has selectable columns""" @@ -240,7 +309,12 @@ class DataSetsList: Definition: DataSetsList """ - value: Optional[List[DataSet]] = None + value: Optional[ + List[DataSet | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) @dataclass @@ -249,9 +323,14 @@ class DataSet: Definition: DataSet """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) - display_name: Optional[str] = field( + name: Optional[str] = dataclass_field( default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) + display_name: Optional[str] = dataclass_field( + default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) @@ -262,9 +341,14 @@ class Table: Definition: Table """ - name: Optional[str] = field(default=None, metadata={"wire_name": "Name"}) - display_name: Optional[str] = field( + name: Optional[str] = dataclass_field( + default=None, + kw_only=True, + metadata={"wire_name": "Name"}, + ) + display_name: Optional[str] = dataclass_field( default=None, + kw_only=True, metadata={"wire_name": "DisplayName"}, ) @@ -275,7 +359,7 @@ class GetCurrentUserInfoResponse: Definition: GetCurrentUserInfoResponse """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -290,16 +374,16 @@ class ZendeskClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -310,8 +394,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -319,8 +403,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -332,7 +416,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -354,7 +438,7 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s return f"{self._connection_runtime_url}{next_link}" if next_link.startswith("?"): return f"{current_request_url.partition('?')[0]}{next_link}" - return f"{self._connection_runtime_url}/{next_link}" + return urljoin(current_request_url, next_link) parsed_connection = urlsplit(self._connection_runtime_url) next_link_hostname = parsed_next_link.hostname @@ -386,63 +470,125 @@ def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> s suffix += f"?{parsed_next_link.query}" return f"{self._connection_runtime_url}{suffix}" - async def get_tables_async( + def list_tables( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get tables Retrieves Zendesk tables from a site + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTables`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/datasets/default/tables" + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item - async def get_items_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def list_items( self, table: str, + *, filter: Optional[str] = None, orderby: Optional[str] = None, skip: Optional[int] = None, top: Optional[int] = None, select: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> AsyncIterator[dict[str, Any]]: + ) -> ItemPaged[dict[str, Any]]: """ Get items Retrieves Zendesk items of a certain Zendesk type (example: 'Ticket') - Yields items from every response page and automatically follows the - connector continuation URL. + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetItems`. + + Args: + table: Zendesk item type (example: 'Ticket'). + filter: An ODATA filter query to restrict the entries returned + (e.g. stringColumn eq 'string' OR numberColumn lt 123). + orderby: An ODATA orderBy query for specifying the order of + entries. + skip: Number of entries to skip (default = 0). + top: Maximum number of entries to retrieve (default = 512). + select: Specific fields to retrieve from entries (default = all). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -480,11 +626,18 @@ async def get_items_async( query_params.append(f"$select={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url request_body = None - while True: - response = await self.http_client.send_async( - "GET", request_url, body=request_body, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, timeout=timeout, headers=headers, client_request_id=client_request_id, @@ -497,25 +650,34 @@ async def get_items_async( request_url, response.status, response.text, + response=response, ) - if not response.text: - return - - page = json.loads(response.text) - for item in page.get("value", []): - yield item + return response, request_url + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} next_link = page.get("@odata.nextLink") - if not next_link: - return + continuation_token = ( + self._resolve_pagination_url(next_link, request_url) + if next_link + else None + ) + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("value", []): + yield item + + return continuation_token, items() - request_url = self._resolve_pagination_url(next_link, request_url) - request_body = None + return ItemPaged(get_next, extract_data) - async def post_item_async( + def post_item( self, - input: Item, + input: Item | Mapping[str, Any], table: str, *, timeout: Optional[float] = None, @@ -527,6 +689,23 @@ async def post_item_async( Create Item Creates a Zendesk item + + Swagger operation ID: `PostItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Zendesk item type (example: 'Ticket'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -537,7 +716,7 @@ async def post_item_async( f"/items" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -551,6 +730,7 @@ async def post_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -558,7 +738,7 @@ async def post_item_async( return json.loads(response.text) - async def get_item_async( + def get_item( self, table: str, id: str, @@ -572,6 +752,22 @@ async def get_item_async( Get item Retrieves a Zendesk item + + Swagger operation ID: `GetItem`. + + Args: + table: Zendesk item type (example: 'Ticket'). + id: Unique identifier of the item to retrieve. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -583,7 +779,7 @@ async def get_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -597,6 +793,7 @@ async def get_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -604,7 +801,7 @@ async def get_item_async( return json.loads(response.text) - async def delete_item_async( + def delete_item( self, table: str, id: str, @@ -618,6 +815,22 @@ async def delete_item_async( Delete item Deletes a Zendesk item + + Swagger operation ID: `DeleteItem`. + + Args: + table: Zendesk item type (example: 'Ticket'). + id: Unique identifier of the item to delete. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -629,7 +842,7 @@ async def delete_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "DELETE", request_url, body=None, timeout=timeout, headers=headers, @@ -643,11 +856,12 @@ async def delete_item_async( request_url, response.status, response.text, + response=response, ) - async def patch_item_async( + def patch_item( self, - input: Item, + input: Item | Mapping[str, Any], table: str, id: str, *, @@ -660,6 +874,24 @@ async def patch_item_async( Update item Updates an existing Zendesk item + + Swagger operation ID: `PatchItem`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + table: Zendesk item type (example: 'Ticket'). + id: Unique identifier of the item to update. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -671,7 +903,7 @@ async def patch_item_async( f"/{quote(quote(str(id), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PATCH", request_url, body=input, timeout=timeout, headers=headers, @@ -685,6 +917,7 @@ async def patch_item_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -692,26 +925,51 @@ async def patch_item_async( return json.loads(response.text) - async def search_articles_async( + def list_search_articles( self, query: str, + *, locale: Optional[str] = None, brand_id: Optional[int] = None, category: Optional[int] = None, section: Optional[int] = None, label_names: Optional[str] = None, multibrand: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Search Articles Returns a default number of 25 articles per page, up to a maximum of 1000 results. + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `SearchArticles`. + + Args: + query: Article to search for. + locale: The locale the item is displayed in. + brand_id: Search for articles in the specified brand. + category: Limit the search to this category id. + section: Limit the search to this section id. + label_names: A comma-separated list of label names. + multibrand: Enable search across all brands if true. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -754,29 +1012,50 @@ async def search_articles_async( query_params.append(f"multibrand={quote(value, safe='')}") if query_params: request_url += '?' + '&'.join(query_params) + initial_request_url = request_url + request_body = None - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) - - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, ) - if not response.text: - return None + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - return json.loads(response.text) + return response, request_url + + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} + + def items() -> Iterator[dict[str, Any]]: + for item in page.get("results", []): + yield item - async def get_table_async( + return None, items() + + return ItemPaged(get_next, extract_data) + + def get_table( self, table: str, *, @@ -789,6 +1068,21 @@ async def get_table_async( Get item metadata Retrieves item metadata for Zendesk object type + + Swagger operation ID: `GetTable`. + + Args: + table: Zendesk item type (example: 'Ticket'). + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -799,7 +1093,7 @@ async def get_table_async( f"/{quote(quote(str(table), safe=''), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -813,6 +1107,7 @@ async def get_table_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/zeptomail.py b/src/azure/connectors/zeptomail.py index 937d069..375d43f 100644 --- a/src/azure/connectors/zeptomail.py +++ b/src/azure/connectors/zeptomail.py @@ -5,14 +5,13 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field as dataclass_field from typing import Optional, Dict, List, Any, Mapping from urllib.parse import quote import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, @@ -20,6 +19,20 @@ ConnectorResponseHook, ) +__all__ = [ + "ZeptomailClient", + "EmailAddress", + "EmailAddressItems", + "FromAddress", + "GetMailAgentResponse", + "GetProcessedEmailsResponse", + "ProcessedMailStatsResponse", + "ReplyToAddress", + "SendMailInput", + "SendTemplateMailInput", + "SuccessMessage", +] + # Type Definitions @@ -29,9 +42,9 @@ class GetMailAgentResponse: Response for Get all Mail Agent """ - data: Optional[List[Dict[str, Any]]] = None + data: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """data""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """message""" @@ -41,9 +54,9 @@ class GetProcessedEmailsResponse: Response for Get processed email details """ - data: Optional[Dict[str, Any]] = None + data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """data""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """message""" @@ -53,32 +66,46 @@ class SendMailInput: Send mail """ - mailagent_key: Optional[str] = None + mailagent_key: str """Choose Mail Agent or enter the Mail Agent key.""" - bounce_address: Optional[str] = None + bounce_address: Optional[str] = dataclass_field(default=None, kw_only=True) """The email address to which bounced emails will be sent.""" - from_: Optional[FromAddress] = field( - default=None, + from_: FromAddress | Mapping[str, Any] = dataclass_field( metadata={"wire_name": "from"}, ) - to: Optional[List[EmailAddressItems]] = None + to: List[EmailAddressItems | Mapping[str, Any]] """Recipient email address.""" - cc: Optional[List[EmailAddressItems]] = None + cc: Optional[ + List[EmailAddressItems | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Email addresses of cc'd recipients.""" - bcc: Optional[List[EmailAddressItems]] = None + bcc: Optional[ + List[EmailAddressItems | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Email addresses of bcc'd recipients.""" - mailtype: Optional[str] = None + mailtype: Optional[str] = dataclass_field(default=None, kw_only=True) """Format of the mail to be sent""" - subject: Optional[str] = None + subject: str """Subject line of your email""" - htmlbody: Optional[str] = None + htmlbody: Optional[str] = dataclass_field(default=None, kw_only=True) """This is the body content for your email.""" - reply_to: Optional[List[ReplyToAddress]] = None + reply_to: Optional[ + List[ReplyToAddress | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """ The email address to which the recipient's email responses will be addressed. """ - attachments: Optional[List[Dict[str, Any]]] = None + attachments: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """Attachments""" @@ -88,11 +115,11 @@ class SuccessMessage: Response for Send mail """ - data: Optional[List[Dict[str, Any]]] = None + data: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) """data""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """The status of the request made.""" - request_id: Optional[str] = None + request_id: Optional[str] = dataclass_field(default=None, kw_only=True) """Unique reference ID of the request.""" @@ -102,28 +129,52 @@ class SendTemplateMailInput: Send template mail """ - mailagent_key: Optional[str] = None + mailagent_key: str """Choose Mail Agent or enter the Mail Agent key.""" - bounce_address: Optional[str] = None + bounce_address: Optional[str] = dataclass_field(default=None, kw_only=True) """the email address to which bounced emails will be sent.""" - mail_template_key: Optional[str] = None + mail_template_key: str """Choose the Mail template""" - from_: Optional[FromAddress] = field( - default=None, + from_: FromAddress | Mapping[str, Any] = dataclass_field( metadata={"wire_name": "from"}, ) - to: Optional[List[EmailAddressItems]] = None + to: Optional[ + List[EmailAddressItems | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Recipient email address.""" - cc: Optional[List[EmailAddressItems]] = None + cc: Optional[ + List[EmailAddressItems | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Email addresses of cc'd recipients.""" - bcc: Optional[List[EmailAddressItems]] = None + bcc: Optional[ + List[EmailAddressItems | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Email addresses of bcc'd recipients.""" - merge_key_detail: Optional[List[Dict[str, Any]]] = None + merge_key_detail: Optional[ + List[Dict[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """ You can use merge tags to replace the placeholders with multiple values for different recipients. """ - reply_to: Optional[List[ReplyToAddress]] = None + reply_to: Optional[ + List[ReplyToAddress | Mapping[str, Any]] + ] = dataclass_field( + default=None, + kw_only=True, + ) """Reply To""" @@ -133,11 +184,11 @@ class ProcessedMailStatsResponse: Response for Processed emails analytics """ - hb: Optional[Dict[str, Any]] = None + hb: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Emails that have hard bounced""" - sb: Optional[Dict[str, Any]] = None + sb: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """sb""" - sent: Optional[Dict[str, Any]] = None + sent: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Emails that have been sent""" @@ -147,11 +198,10 @@ class FromAddress: Definition: FromAddress """ - from_detail: Optional[Dict[str, Any]] = field( - default=None, + from_detail: Dict[str, Any] = dataclass_field( metadata={"wire_name": "from-detail"}, ) - name: Optional[str] = None + name: str """Sender's user name""" @@ -161,9 +211,9 @@ class EmailAddress: Definition: EmailAddress """ - address: Optional[str] = None + address: str """Recipient's email address.""" - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Recipient's name.""" @@ -173,12 +223,12 @@ class ReplyToAddress: Definition: ReplyToAddress """ - address: Optional[str] = None + address: Optional[str] = dataclass_field(default=None, kw_only=True) """ A valid email address containing a domain that is verified in your Mail Agent. """ - name: Optional[str] = None + name: Optional[str] = dataclass_field(default=None, kw_only=True) """Name for the reply-to.""" @@ -188,7 +238,12 @@ class EmailAddressItems: Definition: EmailAddressItems """ - email_address: Optional[EmailAddress] = None + email_address: Optional[ + EmailAddress | Mapping[str, Any] + ] = dataclass_field( + default=None, + kw_only=True, + ) # Client Class @@ -199,16 +254,16 @@ class ZeptomailClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -219,8 +274,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -228,8 +283,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -241,7 +296,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -256,7 +311,7 @@ def __init__( def connector_name(self) -> str: return "zeptomail" - async def get_mail_agent_async( + def get_mail_agent( self, *, timeout: Optional[float] = None, @@ -275,10 +330,24 @@ async def get_mail_agent_async( created.\\n- status: Status of the Mail Agent.\\n\\nExample 1: To retrieve details of all Mail Agents in the ZeptoMail account. Sample prompt 1: Get me details of all the Mail Agents in the account. + + Swagger operation ID: `GetMailAgent`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/portal/v1.0/mailagents" - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -292,6 +361,7 @@ async def get_mail_agent_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -299,9 +369,10 @@ async def get_mail_agent_async( return json.loads(response.text) - async def get_processed_emails_async( + def get_processed_emails( self, mailagent_key: str, + *, subject: Optional[str] = None, from_: Optional[str] = None, to: Optional[str] = None, @@ -310,7 +381,6 @@ async def get_processed_emails_async( request_id: Optional[str] = None, is_hb: Optional[bool] = None, is_sb: Optional[bool] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -324,6 +394,31 @@ async def get_processed_emails_async( Subject, From Address, Sent time and Request ID for emails sent for the time range. The mailagent_key parameter should match the Mail Agent key of the Mail Agent as listed in our system. + + Swagger operation ID: `Get_Processed_Emails`. + + Args: + mailagent_key: Choose Mail Agent or enter the Mail Agent key. + subject: Enter subject of the email. + from_: Enter sender address of the email. + to: Enter recipient address of the email. + date_from: Enter from date for search in the format + yyyy-MM-ddTHH:mm:sszzz. + date_to: Enter to date for search in the format + yyyy-MM-ddTHH:mm:sszzz. + request_id: Enter Request ID of the email. + is_hb: Include hardbounces in results. + is_sb: Include softbounces in results. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/email" query_params = [] @@ -374,7 +469,7 @@ async def get_processed_emails_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -388,6 +483,7 @@ async def get_processed_emails_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -395,9 +491,9 @@ async def get_processed_emails_async( return json.loads(response.text) - async def send_mail_async( + def send_mail( self, - input: SendMailInput, + input: SendMailInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -408,10 +504,26 @@ async def send_mail_async( Send mail To send an email to the desired recipient. + + Swagger operation ID: `SendMail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/email" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -425,6 +537,7 @@ async def send_mail_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -432,9 +545,9 @@ async def send_mail_async( return json.loads(response.text) - async def send_template_mail_async( + def send_template_mail( self, - input: SendTemplateMailInput, + input: SendTemplateMailInput | Mapping[str, Any], *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, @@ -445,10 +558,26 @@ async def send_template_mail_async( Send template mail Sending a single email using Templates. + + Swagger operation ID: `SendTemplateMail`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/email/template" - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -462,6 +591,7 @@ async def send_template_mail_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -469,12 +599,12 @@ async def send_template_mail_async( return json.loads(response.text) - async def processed_mail_stats_async( + def processed_mail_stats( self, mailagent: str, + *, from_time: Optional[str] = None, to_time: Optional[str] = None, - *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, @@ -488,6 +618,25 @@ async def processed_mail_stats_async( count of Hardbounce, Softbounce and Sent statistics over a period of time and each day . The mailagent parameter should match the Mail Agent name as listed in our system. + + Swagger operation ID: `Processed_Mail_Stats`. + + Args: + mailagent: Choose or enter Mail agent name. + from_time: Enter statics from date in the format + yyyy-MM-ddTHH:mm:sszzz. + to_time: Enter statics to date in the format + yyyy-MM-ddTHH:mm:sszzz. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/v1.0/stats/email" query_params = [] @@ -508,7 +657,7 @@ async def processed_mail_stats_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -522,6 +671,7 @@ async def processed_mail_stats_async( request_url, response.status, response.text, + response=response, ) if not response.text: diff --git a/src/azure/connectors/zohosign.py b/src/azure/connectors/zohosign.py index 9106ab3..b01bdf5 100644 --- a/src/azure/connectors/zohosign.py +++ b/src/azure/connectors/zohosign.py @@ -5,21 +5,36 @@ from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional, Dict, List, Any, Mapping -from urllib.parse import quote +from dataclasses import dataclass, field as dataclass_field +from typing import Optional, Iterator, Dict, List, Any, Mapping +from urllib.parse import quote, urljoin, urlsplit import json -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.paging import ItemPaged +from azure.core.credentials import AzureKeyCredential, TokenCredential +from azure.core.pipeline.transport import HttpTransport from azure.connectors.sdk import ( ConnectorClientBase, ConnectorException, ConnectorResponseHook, + ConnectorResponseSnapshot, ) +__all__ = [ + "ZohosignClient", + "GetDocumentResponse", + "GetFormDataResponse", + "GetTemplatesResponse", + "InvokeAPIInput", + "InvokeAPIResponse", + "SendSignRequestResponse", + "UpdateDocumentInput", + "UpdateDocumentResponse", + "ZohoSignTriggersInput", + "TRIGGER_OPERATIONS", +] + # Type Definitions @@ -29,7 +44,7 @@ class InvokeAPIInput: Invoke API """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -42,7 +57,7 @@ class InvokeAPIResponse: Response for Invoke API """ - additional_properties: Dict[str, Any] = field(default_factory=dict) + additional_properties: Dict[str, Any] = dataclass_field(default_factory=dict, kw_only=True) """ Dynamic properties determined at runtime (similar to .NET [JsonExtensionData]) @@ -55,13 +70,13 @@ class ZohoSignTriggersInput: Zoho Sign Triggers """ - webhook_url: Optional[str] = None + webhook_url: str """Webhook url""" - webhook_actions: Optional[str] = None + webhook_actions: str """Webhook actions""" - purpose: Optional[str] = None + purpose: str """Purpose""" - appname: Optional[str] = None + appname: str """appname""" @@ -71,11 +86,11 @@ class GetFormDataResponse: Response for Get data of completed request """ - code: Optional[int] = None + code: Optional[int] = dataclass_field(default=None, kw_only=True) """code""" - document_form_data: Optional[Dict[str, Any]] = None + document_form_data: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """Document form data""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """status""" @@ -85,13 +100,13 @@ class GetDocumentResponse: Response for Get a document """ - code: Optional[int] = None + code: Optional[int] = dataclass_field(default=None, kw_only=True) """code""" - requests: Optional[Dict[str, Any]] = None + requests: Optional[Dict[str, Any]] = dataclass_field(default=None, kw_only=True) """requests""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """message""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """status""" @@ -101,7 +116,7 @@ class UpdateDocumentInput: Update the properties of a created request """ - requests: Optional[Dict[str, Any]] = None + requests: Dict[str, Any] """requests""" @@ -111,11 +126,11 @@ class UpdateDocumentResponse: Response for Update the properties of a created request """ - code: Optional[int] = None + code: Optional[int] = dataclass_field(default=None, kw_only=True) """code""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """message""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """status""" @@ -125,11 +140,11 @@ class SendSignRequestResponse: Response for SendSignRequest """ - code: Optional[int] = None + code: Optional[int] = dataclass_field(default=None, kw_only=True) """code""" - message: Optional[str] = None + message: Optional[str] = dataclass_field(default=None, kw_only=True) """message""" - status: Optional[str] = None + status: Optional[str] = dataclass_field(default=None, kw_only=True) """status""" @@ -139,7 +154,7 @@ class GetTemplatesResponse: Response for Get list of templates """ - templates: Optional[List[Dict[str, Any]]] = None + templates: Optional[List[Dict[str, Any]]] = dataclass_field(default=None, kw_only=True) # Client Class @@ -150,16 +165,16 @@ class ZohosignClient(ConnectorClientBase): def __init__( self, connection_runtime_url: str, - credential: AsyncTokenCredential | AzureKeyCredential, + credential: TokenCredential | AzureKeyCredential, *, max_retry_attempts: int = 3, - timeout_seconds: float = 30.0, + timeout: float = 30.0, use_exponential_backoff: bool = True, initial_retry_delay_seconds: float = 0.5, maximum_retry_delay_seconds: float = 120.0, retry_jitter_factor: float = 0.1, retry_unsafe_http_methods: bool = False, - transport: Optional[AsyncHttpTransport] = None, + transport: Optional[HttpTransport] = None, **kwargs: Any, ): """ @@ -170,8 +185,8 @@ def __init__( URL from Azure Portal. credential: Caller-owned Azure Core credential. max_retry_attempts: The maximum number of request attempts. - timeout_seconds: The total network timeout for each request, - including retries, response loading, and body reads. + timeout: The network timeout in seconds for each request. + The value configures Azure Core retry and transport deadlines. Nonpositive values disable SDK and transport deadlines. use_exponential_backoff: Whether retries use exponential backoff. initial_retry_delay_seconds: The initial retry delay in seconds. @@ -179,8 +194,8 @@ def __init__( retry_jitter_factor: The jitter fraction applied to retry delays. retry_unsafe_http_methods: Whether unsafe HTTP methods may be retried. - transport: Optional Azure Core async HTTP transport closed by - the client through its asynchronous lifecycle. + transport: Optional Azure Core HTTP transport closed by + the client through its synchronous lifecycle. **kwargs: Optional Azure Core pipeline policy settings. """ if not connection_runtime_url: @@ -192,7 +207,7 @@ def __init__( super().__init__( credential, max_retry_attempts=max_retry_attempts, - timeout_seconds=timeout_seconds, + timeout=timeout, use_exponential_backoff=use_exponential_backoff, initial_retry_delay_seconds=initial_retry_delay_seconds, maximum_retry_delay_seconds=maximum_retry_delay_seconds, @@ -207,9 +222,48 @@ def __init__( def connector_name(self) -> str: return "zohosign" - async def invoke_api_async( + def _resolve_pagination_url(self, next_link: str, current_request_url: str) -> str: + parsed_next_link = urlsplit(next_link) + if not parsed_next_link.scheme or not parsed_next_link.netloc: + if next_link.startswith("/"): + return f"{self._connection_runtime_url}{next_link}" + if next_link.startswith("?"): + return f"{current_request_url.partition('?')[0]}{next_link}" + return urljoin(current_request_url, next_link) + + parsed_connection = urlsplit(self._connection_runtime_url) + next_link_hostname = parsed_next_link.hostname + connection_hostname = parsed_connection.hostname + if next_link_hostname is None or connection_hostname is None: + raise ValueError("Pagination URLs must include a hostname.") + + next_link_port = parsed_next_link.port + if next_link_port is None: + next_link_port = 443 if parsed_next_link.scheme == "https" else 80 + connection_port = parsed_connection.port + if connection_port is None: + connection_port = 443 if parsed_connection.scheme == "https" else 80 + if next_link_hostname.lower() == connection_hostname.lower(): + if ( + parsed_next_link.scheme == parsed_connection.scheme + and next_link_port == connection_port + ): + return next_link + + raise ValueError( + "Pagination URL origin " + f"'{parsed_next_link.scheme}://{next_link_hostname}:{next_link_port}' " + "must use the connection runtime scheme and port." + ) + + suffix = parsed_next_link.path + if parsed_next_link.query: + suffix += f"?{parsed_next_link.query}" + return f"{self._connection_runtime_url}{suffix}" + + def invoke_api( self, - input: InvokeAPIInput, + input: InvokeAPIInput | Mapping[str, Any], url: str, method: str, *, @@ -222,6 +276,24 @@ async def invoke_api_async( Invoke API Invoke API + + Swagger operation ID: `InvokeAPI`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + url: Provide url path. + method: Select API Method to be used. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}/{quote(str(url), safe='')}" @@ -234,7 +306,7 @@ async def invoke_api_async( if query_params: request_url += '?' + '&'.join(query_params) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=input, timeout=timeout, headers=headers, @@ -248,6 +320,7 @@ async def invoke_api_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -255,7 +328,7 @@ async def invoke_api_async( return json.loads(response.text) - async def download_completion_certificate_async( + def download_completion_certificate( self, request_id: int, *, @@ -268,6 +341,21 @@ async def download_completion_certificate_async( Download Completion Certificate Downloads the completion certificate of a specific envelope + + Swagger operation ID: `download-completion-certificate`. + + Args: + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -276,7 +364,7 @@ async def download_completion_certificate_async( f"/completioncertificate" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -290,11 +378,12 @@ async def download_completion_certificate_async( request_url, response.status, response.text, + response=response, ) return response.content - async def download_document_async( + def download_document( self, request_id: int, *, @@ -307,13 +396,28 @@ async def download_document_async( Download Document Downloads a specific envelope + + Swagger operation ID: `download-document`. + + Args: + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/requests/{quote(str(request_id), safe='')}/pdf" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -327,11 +431,12 @@ async def download_document_async( request_url, response.status, response.text, + response=response, ) return response.content - async def download_file_async( + def download_file( self, request_id: int, document_id: int, @@ -345,6 +450,22 @@ async def download_file_async( Download File Downloads a specific document or file + + Swagger operation ID: `download-file`. + + Args: + request_id: Request ID. + document_id: Document ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + bytes: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" @@ -355,7 +476,7 @@ async def download_file_async( f"/pdf" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -369,11 +490,12 @@ async def download_file_async( request_url, response.status, response.text, + response=response, ) return response.content - async def get_form_data_async( + def get_form_data( self, request_id: int, *, @@ -386,13 +508,28 @@ async def get_form_data_async( Get data of completed request Shows the details of a signed envelope + + Swagger operation ID: `get-form-data`. + + Args: + request_id: Request id. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/requests/{quote(str(request_id), safe='')}/fielddata" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -406,6 +543,7 @@ async def get_form_data_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -413,7 +551,7 @@ async def get_form_data_async( return json.loads(response.text) - async def recall_document_async( + def recall_document( self, request_id: int, *, @@ -426,13 +564,28 @@ async def recall_document_async( Recall a particular document Recall a particular document + + Swagger operation ID: `recall-document`. + + Args: + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/requests/{quote(str(request_id), safe='')}/recall" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -446,9 +599,10 @@ async def recall_document_async( request_url, response.status, response.text, + response=response, ) - async def remind_document_recipients_async( + def remind_document_recipients( self, request_id: int, *, @@ -461,13 +615,28 @@ async def remind_document_recipients_async( Reminder for recipients Send a reminder to recipients of a particular document. + + Swagger operation ID: `remind-document-recipients`. + + Args: + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/requests/{quote(str(request_id), safe='')}/remind" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -481,9 +650,10 @@ async def remind_document_recipients_async( request_url, response.status, response.text, + response=response, ) - async def delete_document_async( + def delete_document( self, request_id: int, *, @@ -496,13 +666,28 @@ async def delete_document_async( Delete Document Delete a particular document + + Swagger operation ID: `delete-document`. + + Args: + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/requests/{quote(str(request_id), safe='')}/delete" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=None, timeout=timeout, headers=headers, @@ -516,9 +701,10 @@ async def delete_document_async( request_url, response.status, response.text, + response=response, ) - async def get_document_async( + def get_document( self, request_id: int, *, @@ -531,13 +717,28 @@ async def get_document_async( Get a document Shows the details of a specific envelope + + Swagger operation ID: `get-document`. + + Args: + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/requests/{quote(str(request_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -551,6 +752,7 @@ async def get_document_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -558,9 +760,9 @@ async def get_document_async( return json.loads(response.text) - async def update_document_async( + def update_document( self, - input: UpdateDocumentInput, + input: UpdateDocumentInput | Mapping[str, Any], request_id: str, *, timeout: Optional[float] = None, @@ -572,13 +774,30 @@ async def update_document_async( Update the properties of a created request Update the properties of a created request + + Swagger operation ID: `UpdateDocument`. + + Args: + input: The request body. Mapping keys use serialized Swagger wire + names. + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/requests/{quote(str(request_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "PUT", request_url, body=input, timeout=timeout, headers=headers, @@ -592,6 +811,7 @@ async def update_document_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -599,7 +819,7 @@ async def update_document_async( return json.loads(response.text) - async def send_sign_request_async( + def send_sign_request( self, request_id: str, *, @@ -612,13 +832,28 @@ async def send_sign_request_async( SendSignRequest Send the uploaded document out for signature + + Swagger operation ID: `SendSignRequest`. + + Args: + request_id: Request ID. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + dict[str, Any] | None: The connector operation result. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/requests/{quote(str(request_id), safe='')}/submit" ) - response = await self.http_client.send_async( + response = self.http_client.send( "POST", request_url, body=None, timeout=timeout, headers=headers, @@ -632,6 +867,7 @@ async def send_sign_request_async( request_url, response.status, response.text, + response=response, ) if not response.text: @@ -639,7 +875,7 @@ async def send_sign_request_async( return json.loads(response.text) - async def get_template_details_async( + def get_template_details( self, template_id: str, *, @@ -652,13 +888,28 @@ async def get_template_details_async( Get particular template details Shows the details of a specific document template + + Swagger operation ID: `get-template-details`. + + Args: + template_id: List of Templates. + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + None: The operation completes without a response body. + + Raises: + ConnectorException: If the connector request fails. """ request_url = ( f"{self._connection_runtime_url}" f"/templates/{quote(str(template_id), safe='')}" ) - response = await self.http_client.send_async( + response = self.http_client.send( "GET", request_url, body=None, timeout=timeout, headers=headers, @@ -672,43 +923,83 @@ async def get_template_details_async( request_url, response.status, response.text, + response=response, ) - async def get_templates_async( + def list_templates( self, *, timeout: Optional[float] = None, headers: Optional[Mapping[str, str]] = None, client_request_id: Optional[str] = None, response_hook: Optional[ConnectorResponseHook] = None, - ) -> dict[str, Any] | None: + ) -> ItemPaged[dict[str, Any]]: """ Get list of templates Shows a list of all the document templates created + + Returns an Azure Core pager that follows the connector continuation + URL. + + Swagger operation ID: `GetTemplates`. + + Args: + timeout: The request timeout in seconds. + headers: Additional HTTP request headers. + client_request_id: A caller-provided request identifier. + response_hook: A callback invoked with the connector response. + + Returns: + ItemPaged[dict[str, Any]]: An Azure Core pager over connector + results. Consume it with `for`. + + Raises: + ConnectorException: If the connector request fails. """ request_url = f"{self._connection_runtime_url}/templates" + initial_request_url = request_url + request_body = None + + def get_next( + continuation_token: Optional[str], + ) -> tuple[ConnectorResponseSnapshot, str]: + request_url = initial_request_url + if continuation_token is not None: + request_url = self._resolve_pagination_url(continuation_token, initial_request_url) + body = request_body if continuation_token is None else None + response = self.http_client.send( + "GET", request_url, body=body, + timeout=timeout, + headers=headers, + client_request_id=client_request_id, + response_hook=response_hook, + ) - response = await self.http_client.send_async( - "GET", request_url, body=None, - timeout=timeout, - headers=headers, - client_request_id=client_request_id, - response_hook=response_hook, - ) + if not (200 <= response.status < 300): + raise ConnectorException( + "GET", + request_url, + response.status, + response.text, + response=response, + ) - if not (200 <= response.status < 300): - raise ConnectorException( - "GET", - request_url, - response.status, - response.text, - ) + return response, request_url - if not response.text: - return None + def extract_data( + page_response: tuple[ConnectorResponseSnapshot, str], + ) -> tuple[Optional[str], Iterator[dict[str, Any]]]: + response, request_url = page_response + page = json.loads(response.text) if response.text else {} - return json.loads(response.text) + def items() -> Iterator[dict[str, Any]]: + for item in page.get("templates", []): + yield item + + return None, items() + + return ItemPaged(get_next, extract_data) # Trigger Operations diff --git a/tests/generated_connector_test_utils.py b/tests/generated_connector_test_utils.py index 0bbbf03..1770584 100644 --- a/tests/generated_connector_test_utils.py +++ b/tests/generated_connector_test_utils.py @@ -5,13 +5,20 @@ from __future__ import annotations import dataclasses +import importlib import inspect +import re +from collections.abc import Mapping +from enum import Enum from types import ModuleType -from typing import Any, get_args, get_origin, get_type_hints +from typing import Any, Literal, get_args, get_origin, get_type_hints from unittest.mock import AsyncMock, patch import pytest +from azure.core.async_paging import AsyncItemPaged from azure.core.credentials import AzureKeyCredential +from azure.core.paging import ItemPaged +from azure.core.polling import AsyncLROPoller, LROPoller from azure.connectors.sdk import ConnectorException from azure.connectors.sdk.serialization import ( @@ -29,25 +36,80 @@ } +def _get_generated_type_hints(method: Any, module: ModuleType) -> dict[str, Any]: + """Resolve annotations from shared root models and the client module.""" + method_module = importlib.import_module(method.__module__) + return get_type_hints( + method, + globalns={**vars(module), **vars(method_module)}, + ) + + def get_generated_operations(client_type: type[Any]) -> set[str]: - """Return generated async operation names without their async suffix.""" + """Return public operations declared by a generated client.""" return { - name.removesuffix("_async") - for name in dir(client_type) - if name.endswith("_async") - and ( - inspect.iscoroutinefunction(getattr(client_type, name)) - or inspect.isasyncgenfunction(getattr(client_type, name)) - ) + name + for name, member in vars(client_type).items() + if not name.startswith("_") + and name != "close" + and callable(member) } +def generated_pager_response_text(method: Any) -> str: + """Build a one-item response matching a generated pager's wire shape.""" + method_source = inspect.getsource(method) + if "for item in page:" in method_source: + return '[{"ok": true}]' + + collection_match = re.search( + r'for item in page\.get\("([^"]+)", \[\]\):', + method_source, + ) + assert collection_match is not None, method.__qualname__ + return f'{{"{collection_match.group(1)}": [{{"ok": true}}]}}' + + +def resolve_sync_generated_result(result: Any) -> Any: + """Resolve a generated result, consuming a synchronous pager or poller.""" + if isinstance(result, ItemPaged): + return list(result) + if isinstance(result, LROPoller): + return result.result() + + return result + + async def resolve_generated_result(result: Any) -> Any: - """Resolve a generated coroutine or collect a generated async iterator.""" - if inspect.isasyncgen(result): + """Resolve an asynchronous generated result, consuming a pager or poller.""" + if isinstance(result, AsyncItemPaged): return [item async for item in result] - return await result + awaited_result = await result + if isinstance(awaited_result, AsyncLROPoller): + return await awaited_result.result() + + return awaited_result + + +def invoke_sync_generated_operation( + client: Any, + operation: str, + module: ModuleType, + include_optional_parameters: bool = False, + request_controls: dict[str, Any] | None = None, +) -> Any: + """Invoke a synchronous generated operation with representative arguments.""" + method = getattr(client, operation) + type_hints = _get_generated_type_hints(method, module) + arguments = { + parameter.name: _representative_value(type_hints[parameter.name]) + for parameter in inspect.signature(method).parameters.values() + if parameter.name not in _REQUEST_CONTROL_PARAMETER_NAMES + and (include_optional_parameters or parameter.default is inspect.Parameter.empty) + } + arguments.update(request_controls or {}) + return resolve_sync_generated_result(method(**arguments)) async def invoke_generated_operation( @@ -57,9 +119,9 @@ async def invoke_generated_operation( include_optional_parameters: bool = False, request_controls: dict[str, Any] | None = None, ) -> Any: - """Invoke a generated operation with representative arguments.""" - method = getattr(client, f"{operation}_async") - type_hints = get_type_hints(method, globalns=vars(module)) + """Invoke an asynchronous generated operation with representative arguments.""" + method = getattr(client, operation) + type_hints = _get_generated_type_hints(method, module) arguments = { parameter.name: _representative_value(type_hints[parameter.name]) for parameter in inspect.signature(method).parameters.values() @@ -70,6 +132,39 @@ async def invoke_generated_operation( return await resolve_generated_result(method(**arguments)) +def model_instance( + model_type: type[Any], + *args: Any, + **kwargs: Any, +) -> Any: + """Construct a model while filling required fields omitted by a focused test.""" + type_hints = get_type_hints(model_type) + model_fields = [ + model_field + for model_field in dataclasses.fields(model_type) + if model_field.init + ] + positional_field_names = [ + model_field.name + for model_field in model_fields + if not model_field.kw_only + ] + provided_field_names = set(positional_field_names[:len(args)]) | set(kwargs) + + for model_field in model_fields: + if ( + model_field.name not in provided_field_names + and model_field.default is dataclasses.MISSING + and model_field.default_factory is dataclasses.MISSING + ): + kwargs[model_field.name] = _representative_value( + type_hints[model_field.name], + active_model_types=frozenset({model_type}), + ) + + return model_type(*args, **kwargs) + + class GeneratedConnectorContractTests: """Shared contract tests for a generated connector client.""" @@ -98,7 +193,7 @@ def test_init_with_invalid_url_raises_error(self, connection_runtime_url: str | @pytest.mark.asyncio async def test_context_manager(self, mock_credential: Any) -> None: - """Test async context manager cleanup.""" + """Test asynchronous context manager cleanup.""" with patch.object(self.client_type, "close", new_callable=AsyncMock) as mock_close: async with self.client_type( "https://example.azure.com/connections/test", @@ -125,7 +220,7 @@ def test_generated_models_serialize_wire_names(self) -> None: assert model_types for model_type in model_types: - instance = model_type() + instance = model_instance(model_type) expected = {} wire_names = [] @@ -156,15 +251,21 @@ async def test_generated_operation_success_contracts(self, mock_credential: Any) "https://example.azure.com/connections/test", credential=mock_credential, ) - generated_method = getattr(client, f"{operation}_async") - is_pageable = inspect.isasyncgenfunction(generated_method) + generated_method = getattr(client, operation) + return_type = _get_generated_type_hints( + generated_method, + self.connector_module, + )["return"] + is_pageable = get_origin(return_type) is AsyncItemPaged response_text = ( - '{"value": [{"ok": true}]}' if is_pageable else '{"ok": true}' + generated_pager_response_text(generated_method) + if is_pageable + else '{"ok": true}' ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text=response_text), ) as mock_send: @@ -183,12 +284,8 @@ async def test_generated_operation_success_contracts(self, mock_credential: Any) body = mock_send.call_args.kwargs["body"] assert (body is not None) is expects_body, operation if expects_body: - assert to_wire(body), operation + assert to_wire(body) is not None, operation - return_type = get_type_hints( - getattr(client, f"{operation}_async"), - globalns=vars(self.connector_module), - )["return"] if return_type is type(None): assert result is None, operation elif is_pageable: @@ -209,7 +306,7 @@ async def test_non_success_responses_raise_exception(self, mock_credential: Any) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=400, text="bad request"), ): @@ -217,7 +314,10 @@ async def test_non_success_responses_raise_exception(self, mock_credential: Any) await invoke_generated_operation(client, operation, self.connector_module) -def _representative_value(annotation: Any) -> Any: +def _representative_value( + annotation: Any, + active_model_types: frozenset[type[Any]] = frozenset(), +) -> Any: """Create a representative value for a required generated parameter.""" if annotation is str: return "value" @@ -237,34 +337,89 @@ def _representative_value(annotation: Any) -> Any: origin = get_origin(annotation) if origin is list: item_types = get_args(annotation) - return [_representative_value(item_types[0])] if item_types else ["value"] + if not item_types: + return ["value"] + + if item_types[0] in active_model_types: + return [] + + return [ + _representative_value( + item_types[0], + active_model_types=active_model_types, + ) + ] if origin is dict: return {"key": "value"} + if origin is Mapping: + return {"key": "value"} + + if origin is Literal: + return get_args(annotation)[0] + non_null_types = [ item_type for item_type in get_args(annotation) if item_type is not type(None) ] if len(non_null_types) == 1: - return _representative_value(non_null_types[0]) + return _representative_value( + non_null_types[0], + active_model_types=active_model_types, + ) + + mapping_types = [ + item_type + for item_type in non_null_types + if get_origin(item_type) is Mapping + ] + if mapping_types: + return _representative_value( + mapping_types[0], + active_model_types=active_model_types, + ) + + for item_type in non_null_types: + try: + return _representative_value( + item_type, + active_model_types=active_model_types, + ) + except AssertionError: + continue if annotation is Any: return "value" - if inspect.isclass(annotation) and dataclasses.is_dataclass(annotation): - instance = annotation() - model_fields = dataclasses.fields(instance) - if model_fields: - model_field = model_fields[0] - value = ( - {"key": "value"} - if model_field.name == ADDITIONAL_PROPERTIES_FIELD - else "value" - ) - setattr(instance, model_field.name, value) + if inspect.isclass(annotation) and issubclass(annotation, Enum): + return next(iter(annotation)) - return instance + if inspect.isclass(annotation) and dataclasses.is_dataclass(annotation): + return _representative_model( + annotation, + active_model_types=active_model_types, + ) raise AssertionError(f"Unsupported generated parameter type '{annotation}'.") + + +def _representative_model( + model_type: type[Any], + active_model_types: frozenset[type[Any]], +) -> Any: + """Construct a generated model with values for every required field.""" + type_hints = get_type_hints(model_type) + nested_model_types = active_model_types | {model_type} + arguments = { + model_field.name: _representative_value( + type_hints[model_field.name], + active_model_types=nested_model_types, + ) + for model_field in dataclasses.fields(model_type) + if model_field.init + and model_field.default is dataclasses.MISSING + and model_field.default_factory is dataclasses.MISSING + } + return model_type(**arguments) diff --git a/tests/test_api_docs.py b/tests/test_api_docs.py index beab678..2b85518 100644 --- a/tests/test_api_docs.py +++ b/tests/test_api_docs.py @@ -71,9 +71,21 @@ def test_defined_public_names_handles_empty_module(tmp_path: Path) -> None: def _create_source_tree(package_root: Path) -> None: """Create a minimal connector package for validator tests.""" sdk_root = package_root / "sdk" + aio_sdk_root = sdk_root / "aio" + aio_connector_root = package_root / "aio" sdk_root.mkdir(parents=True) + aio_sdk_root.mkdir() + aio_connector_root.mkdir() (package_root / "connector.py").write_text("PUBLIC_VALUE = 1\n", encoding="utf-8") + (aio_connector_root / "connector.py").write_text( + "PUBLIC_VALUE = 1\n", + encoding="utf-8", + ) (sdk_root / "core.py").write_text("PUBLIC_VALUE = 1\n", encoding="utf-8") + (aio_sdk_root / "core.py").write_text( + "PUBLIC_VALUE = 1\n", + encoding="utf-8", + ) def _write_api_page( @@ -97,7 +109,9 @@ def documentation_tree(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path: _create_source_tree(package_root) monkeypatch.setattr(validate_api_docs, "PACKAGE_ROOT", package_root) _write_api_page(site_root, "core", "core") + _write_api_page(site_root, "core-aio", "core") _write_api_page(site_root, "connectors", "connector") + _write_api_page(site_root, "connectors-aio", "connector") api_landing_page = site_root / "api" / "index.html" api_landing_page.parent.mkdir(parents=True, exist_ok=True) api_landing_page.write_text("API reference", encoding="utf-8") @@ -118,6 +132,23 @@ def test_validate_api_docs_reports_missing_page(documentation_tree: Path) -> Non ] +def test_validate_api_docs_reports_missing_aio_page( + documentation_tree: Path, +) -> None: + """Report a missing asynchronous connector API page.""" + ( + documentation_tree + / "api" + / "connectors-aio" + / "connector" + / "index.html" + ).unlink() + + assert validate_api_docs.validate_api_docs(documentation_tree) == [ + "Missing connectors-aio API pages: connector", + ] + + @pytest.mark.parametrize("page_content", ["", ""]) def test_validate_api_docs_rejects_page_without_api_content( documentation_tree: Path, diff --git a/tests/test_arm.py b/tests/test_arm.py index 5dfdb93..2863421 100644 --- a/tests/test_arm.py +++ b/tests/test_arm.py @@ -6,8 +6,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.arm import ArmClient from azure.connectors.arm import ( - ArmClient, LocationListResult, Location, Subscription, @@ -97,7 +97,7 @@ def test_init_with_custom_settings(self, mock_credential): client = ArmClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -181,11 +181,11 @@ async def test_success_with_subscriptions(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(arm_client.subscriptions_list_async()) + result = await resolve_generated_result(arm_client.list_subscriptions()) mock_send.assert_called_once_with( "GET", @@ -211,11 +211,11 @@ async def test_success_uses_generated_api_version(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(arm_client.subscriptions_list_async()) + result = await resolve_generated_result(arm_client.list_subscriptions()) mock_send.assert_called_once_with( "GET", @@ -237,11 +237,11 @@ async def test_success_with_empty_subscriptions(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(arm_client.subscriptions_list_async()) + result = await resolve_generated_result(arm_client.list_subscriptions()) mock_send.assert_called_once() assert result is not None @@ -254,11 +254,11 @@ async def test_success_with_empty_response_body(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(arm_client.subscriptions_list_async()) + result = await resolve_generated_result(arm_client.list_subscriptions()) mock_send.assert_called_once() assert result == [] @@ -295,12 +295,12 @@ async def test_success_with_pagination(self, arm_client): with patch.object( arm_client._http_client, - "send_async", + "send", new_callable=AsyncMock, side_effect=responses, ) as mock_send: result = await resolve_generated_result( - arm_client.subscriptions_list_async() + arm_client.list_subscriptions() ) assert result == [first_subscription, second_subscription] @@ -317,12 +317,12 @@ async def test_error_unauthorized(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(arm_client.subscriptions_list_async()) + await resolve_generated_result(arm_client.list_subscriptions()) assert exc_info.value.status_code == 401 @@ -336,12 +336,12 @@ async def test_error_forbidden(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(arm_client.subscriptions_list_async()) + await resolve_generated_result(arm_client.list_subscriptions()) assert exc_info.value.status_code == 403 @@ -355,12 +355,12 @@ async def test_error_not_found(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(arm_client.subscriptions_list_async()) + await resolve_generated_result(arm_client.list_subscriptions()) assert exc_info.value.status_code == 404 @@ -374,12 +374,12 @@ async def test_error_server_error(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(arm_client.subscriptions_list_async()) + await resolve_generated_result(arm_client.list_subscriptions()) assert exc_info.value.status_code == 500 @@ -794,11 +794,11 @@ async def test_success_with_resource_groups(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(arm_client.resource_groups_list_async( + result = await resolve_generated_result(arm_client.list_resource_groups( subscription_id="sub-1" )) @@ -826,12 +826,12 @@ async def test_error_not_found(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(arm_client.resource_groups_list_async( + await resolve_generated_result(arm_client.list_resource_groups( subscription_id="sub-1" )) @@ -855,11 +855,11 @@ async def test_success(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await arm_client.resource_groups_get_async( + result = await arm_client.resource_groups_get( subscription_id="sub-1", resource_group_name="rg-1" ) @@ -880,11 +880,11 @@ async def test_success_returns_none(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await arm_client.resource_groups_delete_async( + result = await arm_client.resource_groups_delete( subscription_id="sub-1", resource_group_name="rg-1" ) @@ -908,11 +908,11 @@ async def test_success_202_accepted(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await arm_client.resource_groups_delete_async( + result = await arm_client.resource_groups_delete( subscription_id="sub-1", resource_group_name="rg-1" ) @@ -920,26 +920,26 @@ async def test_success_202_accepted(self, arm_client): assert result is None @pytest.mark.asyncio - async def test_error_not_found(self, arm_client): - """Test 404 Not Found raises ConnectorException.""" + async def test_server_error_raises_exception(self, arm_client): + """Test a server error raises ConnectorException.""" mock_response = MockResponse( - status=404, - text='{"error": {"code": "NotFound", "message": "Resource group not found"}}' + status=500, + text='{"error": {"code": "ServerError", "message": "Request failed"}}' ) with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await arm_client.resource_groups_delete_async( + await arm_client.resource_groups_delete( subscription_id="sub-1", resource_group_name="rg-1" ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestDeploymentsGetAsync: @@ -963,11 +963,11 @@ async def test_success(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await arm_client.deployments_get_async( + result = await arm_client.deployments_get( subscription_id="sub-1", resource_group_name="rg-1", deployment_name="deploy-1" @@ -988,11 +988,11 @@ async def test_success_returns_none(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await arm_client.deployments_delete_async( + result = await arm_client.deployments_delete( subscription_id="sub-1", resource_group_name="rg-1", deployment_name="deploy-1" @@ -1011,11 +1011,11 @@ async def test_success_returns_none(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await arm_client.deployments_cancel_async( + result = await arm_client.deployments_cancel( subscription_id="sub-1", resource_group_name="rg-1", deployment_name="deploy-1" @@ -1058,11 +1058,11 @@ async def test_success_with_providers(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(arm_client.providers_list_async( + result = await resolve_generated_result(arm_client.list_providers( subscription_id="sub-1" )) @@ -1085,11 +1085,11 @@ async def test_success(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await arm_client.providers_register_async( + result = await arm_client.providers_register( subscription_id="sub-1", resource_provider_namespace="Microsoft.Compute" ) @@ -1123,12 +1123,14 @@ async def test_success_with_locations(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await arm_client.subscriptions_list_locations_async( - subscription_id="sub-1" + result = await resolve_generated_result( + arm_client.list_subscriptions_list_locations( + subscription_id="sub-1" + ) ) mock_send.assert_called_once_with( @@ -1141,8 +1143,7 @@ async def test_success_with_locations(self, arm_client): client_request_id=None, response_hook=None, ) - assert result is not None - assert len(result["value"]) == 2 + assert result == mock_response_data["value"] class TestSubscriptionsGetAsync: @@ -1161,11 +1162,11 @@ async def test_success(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await arm_client.subscriptions_get_async( + result = await arm_client.subscriptions_get( subscription_id="sub-1" ) @@ -1193,11 +1194,11 @@ async def test_success_returns_none(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await arm_client.tags_delete_value_async( + result = await arm_client.tags_delete_value( subscription_id="sub-1", tag_name="environment", tag_value="deprecated" @@ -1216,11 +1217,11 @@ async def test_success_returns_none(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await arm_client.tags_delete_async( + result = await arm_client.tags_delete( subscription_id="sub-1", tag_name="obsolete-tag" ) @@ -1238,11 +1239,11 @@ async def test_success_returns_none(self, arm_client): with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await arm_client.resources_delete_by_id_async( + result = await arm_client.resources_delete_by_id( x_ms_api_version=RESOURCE_API_VERSION, subscription_id="sub-1", resource_group_name="rg-1", @@ -1253,21 +1254,21 @@ async def test_success_returns_none(self, arm_client): assert result is None @pytest.mark.asyncio - async def test_error_not_found(self, arm_client): - """Test 404 Not Found raises ConnectorException.""" + async def test_server_error_raises_exception(self, arm_client): + """Test a server error raises ConnectorException.""" mock_response = MockResponse( - status=404, - text='{"error": {"code": "NotFound", "message": "Resource not found"}}' + status=500, + text='{"error": {"code": "ServerError", "message": "Request failed"}}' ) with patch.object( arm_client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await arm_client.resources_delete_by_id_async( + await arm_client.resources_delete_by_id( x_ms_api_version=RESOURCE_API_VERSION, subscription_id="sub-1", resource_group_name="rg-1", @@ -1275,4 +1276,4 @@ async def test_error_not_found(self, arm_client): short_resource_id="virtualMachines/vm-1" ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 diff --git a/tests/test_azuread.py b/tests/test_azuread.py index b7299fc..761310e 100644 --- a/tests/test_azuread.py +++ b/tests/test_azuread.py @@ -6,8 +6,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.azuread import AzureadClient from azure.connectors.azuread import ( - AzureadClient, CreateOffice365GroupInput, CreateSecurityGroupInput, CreateUserRequest, @@ -26,7 +26,7 @@ ConnectorException, ) from tests.conftest import MockResponse -from tests.generated_connector_test_utils import resolve_generated_result +from tests.generated_connector_test_utils import model_instance, resolve_generated_result class TestAzureadClientInitialization: @@ -62,7 +62,7 @@ def test_init_with_custom_settings(self, mock_credential): client = AzureadClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -141,11 +141,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_office365_group_async(input=group_input) + result = await client.create_office365_group(input=group_input) mock_send.assert_called_once() call_args = mock_send.call_args @@ -163,15 +163,18 @@ async def test_empty_response_returns_none(self, mock_credential): ) mock_response = MockResponse(status=201, text="") - group_input = CreateOffice365GroupInput(display_name="Test Group") + group_input = model_instance( + CreateOffice365GroupInput, + display_name="Test Group", + ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.create_office365_group_async(input=group_input) + result = await client.create_office365_group(input=group_input) assert result is None @pytest.mark.asyncio @@ -183,16 +186,16 @@ async def test_error_response_raises_exception(self, mock_credential): ) mock_response = MockResponse(status=400, text='{"error": "Invalid group configuration"}') - group_input = CreateOffice365GroupInput(display_name="") + group_input = model_instance(CreateOffice365GroupInput, display_name="") with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_office365_group_async(input=group_input) + await client.create_office365_group(input=group_input) assert exc_info.value.status_code == 400 @@ -222,11 +225,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_security_group_async(input=group_input) + result = await client.create_security_group(input=group_input) mock_send.assert_called_once() call_args = mock_send.call_args @@ -244,16 +247,19 @@ async def test_error_response_raises_exception(self, mock_credential): ) mock_response = MockResponse(status=403, text='{"error": "Insufficient permissions"}') - group_input = CreateSecurityGroupInput(display_name="Test Security Group") + group_input = model_instance( + CreateSecurityGroupInput, + display_name="Test Security Group", + ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_security_group_async(input=group_input) + await client.create_security_group(input=group_input) assert exc_info.value.status_code == 403 @@ -266,15 +272,18 @@ async def test_empty_response_returns_none(self, mock_credential): ) mock_response = MockResponse(status=201, text="") - group_input = CreateSecurityGroupInput(display_name="Empty Response Group") + group_input = model_instance( + CreateSecurityGroupInput, + display_name="Empty Response Group", + ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.create_security_group_async(input=group_input) + result = await client.create_security_group(input=group_input) assert result is None @@ -308,11 +317,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_user_async(input=user_input) + result = await client.create_user(input=user_input) mock_send.assert_called_once() call_args = mock_send.call_args @@ -334,6 +343,7 @@ async def test_with_all_optional_fields(self, mock_credential): account_enabled=True, display_name="Jane Smith", mail_nickname="janesmith", + password_profile={"password": "SecurePass123!"}, user_principal_name="jane.smith@contoso.com", given_name="Jane", surname="Smith", @@ -347,11 +357,11 @@ async def test_with_all_optional_fields(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.create_user_async(input=user_input) + result = await client.create_user(input=user_input) assert result["id"] == "user-full" @pytest.mark.asyncio @@ -363,19 +373,20 @@ async def test_error_response_raises_exception(self, mock_credential): ) mock_response = MockResponse(status=409, text='{"error": "User already exists"}') - user_input = CreateUserRequest( + user_input = model_instance( + CreateUserRequest, display_name="Existing User", user_principal_name="existing@contoso.com" ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_user_async(input=user_input) + await client.create_user(input=user_input) assert exc_info.value.status_code == 409 @@ -388,15 +399,18 @@ async def test_empty_response_returns_none(self, mock_credential): ) mock_response = MockResponse(status=201, text="") - user_input = CreateUserRequest(display_name="Empty Response User") + user_input = model_instance( + CreateUserRequest, + display_name="Empty Response User", + ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.create_user_async(input=user_input) + result = await client.create_user(input=user_input) assert result is None @@ -415,11 +429,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.remove_member_from_group_async( + await client.remove_member_from_group( group_id="group-abc123", member_id="user-xyz789" ) @@ -441,11 +455,11 @@ async def test_with_different_ids(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.remove_member_from_group_async( + await client.remove_member_from_group( group_id="5e6cf5c7-b511-4842-6aae-3f6b8ae5e95b", member_id="8a9bf2d1-c322-5933-7bbf-4g7c9bf6f06c" ) @@ -462,21 +476,21 @@ async def test_error_response_raises_exception(self, mock_credential): credential=mock_credential ) - mock_response = MockResponse(status=404, text='{"error": "Member not found"}') + mock_response = MockResponse(status=500, text='{"error": "Server error"}') with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.remove_member_from_group_async( + await client.remove_member_from_group( group_id="group-abc123", member_id="nonexistent-user" ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestCreateGroup: @@ -505,11 +519,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_group_async(input=group_input) + result = await client.create_group(input=group_input) mock_send.assert_called_once() call_args = mock_send.call_args @@ -528,16 +542,16 @@ async def test_error_response_raises_exception(self, mock_credential): ) mock_response = MockResponse(status=400, text='{"error": "Invalid request"}') - group_input = CreateGroupInput(display_name="") + group_input = model_instance(CreateGroupInput, display_name="") with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_group_async(input=group_input) + await client.create_group(input=group_input) assert exc_info.value.status_code == 400 @@ -550,15 +564,18 @@ async def test_empty_response_returns_none(self, mock_credential): ) mock_response = MockResponse(status=201, text="") - group_input = CreateGroupInput(display_name="Empty Response Group") + group_input = model_instance( + CreateGroupInput, + display_name="Empty Response Group", + ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.create_group_async(input=group_input) + result = await client.create_group(input=group_input) assert result is None @@ -603,6 +620,7 @@ def test_create_user_request_creation(self): account_enabled=True, display_name="Test User", mail_nickname="testuser", + password_profile={"password": "SecurePass123!"}, user_principal_name="test@contoso.com", given_name="Test", surname="User", @@ -720,11 +738,11 @@ async def test_special_characters_in_group_id(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.remove_member_from_group_async( + await client.remove_member_from_group( group_id="5e6cf5c7-b511-4842-6aae-3f6b8ae5e95b", member_id="8a9bf2d1-c322-5933-7bbf-4g7c9bf6f06c" ) @@ -744,15 +762,15 @@ async def test_multiple_consecutive_calls(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - group_input = CreateGroupInput(display_name="Group 1") - await client.create_group_async(input=group_input) + group_input = model_instance(CreateGroupInput, display_name="Group 1") + await client.create_group(input=group_input) - group_input2 = CreateGroupInput(display_name="Group 2") - await client.create_group_async(input=group_input2) + group_input2 = model_instance(CreateGroupInput, display_name="Group 2") + await client.create_group(input=group_input2) assert mock_send.call_count == 2 @@ -775,11 +793,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_group_async(id="group-123") + result = await client.get_group(id="group-123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -800,11 +818,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_group_async(id="group-123") + result = await client.get_group(id="group-123") assert result is None @pytest.mark.asyncio @@ -819,12 +837,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_group_async(id="nonexistent-group") + await client.get_group(id="nonexistent-group") assert exc_info.value.status_code == 404 @@ -850,11 +868,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_user_async(id="user-456") + result = await client.get_user(id="user-456") mock_send.assert_called_once() call_args = mock_send.call_args @@ -875,11 +893,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_user_async(id="user-456") + result = await client.get_user(id="user-456") assert result is None @pytest.mark.asyncio @@ -894,12 +912,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_user_async(id="nonexistent-user") + await client.get_user(id="nonexistent-user") assert exc_info.value.status_code == 404 @@ -923,11 +941,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.update_user_async(input=user_input, id="user-123") + await client.update_user(input=user_input, id="user-123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -961,11 +979,11 @@ async def test_with_all_fields(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - await client.update_user_async(input=user_input, id="user-123") + await client.update_user(input=user_input, id="user-123") @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -980,12 +998,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.update_user_async(input=user_input, id="user-123") + await client.update_user(input=user_input, id="user-123") assert exc_info.value.status_code == 400 @@ -1005,11 +1023,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.refresh_tokens_async(id="user-123") + await client.refresh_tokens(id="user-123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -1028,12 +1046,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.refresh_tokens_async(id="nonexistent-user") + await client.refresh_tokens(id="nonexistent-user") assert exc_info.value.status_code == 404 @@ -1059,11 +1077,11 @@ async def test_success_with_members(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.get_group_members_async(id="group-123")) + result = await resolve_generated_result(client.list_group_members(id="group-123")) mock_send.assert_called_once() call_args = mock_send.call_args @@ -1096,12 +1114,12 @@ async def test_with_top_parameter(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, side_effect=responses, ) as mock_send: result = await resolve_generated_result( - client.get_group_members_async(id="group-123", top="10") + client.list_group_members(id="group-123", top="10") ) assert "$top=10" in mock_send.call_args_list[0].args[1] @@ -1121,11 +1139,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await resolve_generated_result(client.get_group_members_async(id="group-123")) + result = await resolve_generated_result(client.list_group_members(id="group-123")) assert result == [] @pytest.mark.asyncio @@ -1140,13 +1158,13 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: await resolve_generated_result( - client.get_group_members_async(id="nonexistent-group") + client.list_group_members(id="nonexistent-group") ) assert exc_info.value.status_code == 404 @@ -1168,11 +1186,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.add_user_to_group_async(input=user_ref, id="group-123") + await client.add_user_to_group(input=user_ref, id="group-123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -1192,12 +1210,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.add_user_to_group_async(input=user_ref, id="group-123") + await client.add_user_to_group(input=user_ref, id="group-123") assert exc_info.value.status_code == 400 @@ -1218,11 +1236,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.assign_manager_async(input=manager_ref, id="user-123") + await client.assign_manager(input=manager_ref, id="user-123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -1242,12 +1260,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.assign_manager_async(input=manager_ref, id="nonexistent-user") + await client.assign_manager(input=manager_ref, id="nonexistent-user") assert exc_info.value.status_code == 404 @@ -1271,17 +1289,19 @@ async def test_success_user_is_member(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.check_member_groups_async(input=check_input, id="user-123") + result = await resolve_generated_result( + client.check_member_groups(input=check_input, id="user-123") + ) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "POST" assert "/v2/v1.0/users/user-123/checkMemberGroups" in call_args[0][1] - assert "group-123" in result["value"] + assert result == {"value": ["group-123"]} @pytest.mark.asyncio async def test_success_user_is_not_member(self, mock_credential): @@ -1296,16 +1316,18 @@ async def test_success_user_is_not_member(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.check_member_groups_async(input=check_input, id="user-123") - assert result["value"] == [] + result = await resolve_generated_result( + client.check_member_groups(input=check_input, id="user-123") + ) + assert result == {"value": []} @pytest.mark.asyncio - async def test_empty_response_returns_none(self, mock_credential): - """Test that empty response returns None.""" + async def test_empty_response_returns_empty_page(self, mock_credential): + """Test that an empty response returns an empty page.""" client = AzureadClient( "https://example.azure.com/connections/test", credential=mock_credential @@ -1316,11 +1338,13 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.check_member_groups_async(input=check_input, id="user-123") + result = await resolve_generated_result( + client.check_member_groups(input=check_input, id="user-123") + ) assert result is None @pytest.mark.asyncio @@ -1336,12 +1360,17 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.check_member_groups_async(input=check_input, id="nonexistent-user") + await resolve_generated_result( + client.check_member_groups( + input=check_input, + id="nonexistent-user", + ) + ) assert exc_info.value.status_code == 404 @@ -1365,17 +1394,19 @@ async def test_success_with_groups(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_member_groups_async(input=member_input, id="user-123") + result = await resolve_generated_result( + client.list_member_groups(input=member_input, id="user-123") + ) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "POST" assert "/v2/v1.0/users/user-123/getMemberGroups" in call_args[0][1] - assert len(result["value"]) == 3 + assert result == ["group-1", "group-2", "group-3"] @pytest.mark.asyncio async def test_with_security_enabled_only(self, mock_credential): @@ -1390,32 +1421,36 @@ async def test_with_security_enabled_only(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_member_groups_async(input=member_input, id="user-123") - assert len(result["value"]) == 1 + result = await resolve_generated_result( + client.list_member_groups(input=member_input, id="user-123") + ) + assert result == ["sec-group-1"] @pytest.mark.asyncio - async def test_empty_response_returns_none(self, mock_credential): - """Test that empty response returns None.""" + async def test_empty_response_returns_empty_page(self, mock_credential): + """Test that an empty response returns an empty page.""" client = AzureadClient( "https://example.azure.com/connections/test", credential=mock_credential ) mock_response = MockResponse(status=200, text="") - member_input = GetMemberGroupsRequest() + member_input = model_instance(GetMemberGroupsRequest) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_member_groups_async(input=member_input, id="user-123") - assert result is None + result = await resolve_generated_result( + client.list_member_groups(input=member_input, id="user-123") + ) + assert result == [] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -1426,16 +1461,18 @@ async def test_error_response_raises_exception(self, mock_credential): ) mock_response = MockResponse(status=403, text='{"error": "Insufficient permissions"}') - member_input = GetMemberGroupsRequest() + member_input = model_instance(GetMemberGroupsRequest) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_member_groups_async(input=member_input, id="user-123") + await resolve_generated_result( + client.list_member_groups(input=member_input, id="user-123") + ) assert exc_info.value.status_code == 403 @@ -1502,7 +1539,7 @@ async def test_group_members_continuation_yields_later_members( ) as client: with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, side_effect=[ MockResponse(status=200, text=json.dumps({ @@ -1516,7 +1553,7 @@ async def test_group_members_continuation_yields_later_members( ], ) as transport: members = [ - member async for member in client.get_group_members_async( + member async for member in client.list_group_members( id="group-123" ) ] @@ -1553,12 +1590,12 @@ async def test_group_members_empty_response_yields_no_items(mock_credential): ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text=""), ): members = [ - member async for member in client.get_group_members_async( + member async for member in client.list_group_members( id="group-123" ) ] diff --git a/tests/test_azureautomation.py b/tests/test_azureautomation.py index 99a4c81..67f6aaf 100644 --- a/tests/test_azureautomation.py +++ b/tests/test_azureautomation.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.azureautomation import AzureautomationClient from azure.connectors.azureautomation import ( - AzureautomationClient, CreateJobInput, CreateJobResponse, AutomationAccountResponse, @@ -65,7 +65,7 @@ def test_init_with_custom_settings(self, mock_credential): client = AzureautomationClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -271,11 +271,11 @@ async def test_success_returns_content(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_job_output_async( + result = await client.get_job_output( subscription_id="sub123", resource_group_name="rg-test", automation_account="myAutomation", @@ -306,12 +306,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_job_output_async( + await client.get_job_output( subscription_id="sub123", resource_group_name="rg-test", automation_account="myAutomation", @@ -328,8 +328,8 @@ async def test_method_exists(self, mock_credential): credential=mock_credential ) - assert hasattr(client, 'get_job_output_async') - assert callable(client.get_job_output_async) + assert hasattr(client, 'get_job_output') + assert callable(client.get_job_output) class TestGetStatusOfJobAsync: @@ -350,11 +350,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_status_of_job_async( + result = await client.get_status_of_job( subscription_id="sub123", resource_group_name="rg-test", automation_account="myAutomation", @@ -383,11 +383,11 @@ async def test_success_with_empty_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_status_of_job_async( + result = await client.get_status_of_job( subscription_id="sub123", resource_group_name="rg-test", automation_account="myAutomation", @@ -411,12 +411,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_status_of_job_async( + await client.get_status_of_job( subscription_id="sub123", resource_group_name="rg-test", automation_account="myAutomation", @@ -433,8 +433,8 @@ async def test_method_exists(self, mock_credential): credential=mock_credential ) - assert hasattr(client, 'get_status_of_job_async') - assert callable(client.get_status_of_job_async) + assert hasattr(client, 'get_status_of_job') + assert callable(client.get_status_of_job) class TestCreateJobAsync: @@ -458,11 +458,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_job_async( + result = await client.create_job( input=CreateJobInput(), subscription_id="sub123", resource_group_name="rg-test", @@ -496,11 +496,11 @@ async def test_success_with_wait_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_job_async( + result = await client.create_job( input=CreateJobInput(), subscription_id="sub123", resource_group_name="rg-test", @@ -526,11 +526,11 @@ async def test_success_with_empty_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.create_job_async( + result = await client.create_job( input=CreateJobInput(), subscription_id="sub123", resource_group_name="rg-test", @@ -554,12 +554,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_job_async( + await client.create_job( input=CreateJobInput(), subscription_id="sub123", resource_group_name="rg-test", @@ -576,8 +576,8 @@ async def test_method_exists(self, mock_credential): credential=mock_credential ) - assert hasattr(client, 'create_job_async') - assert callable(client.create_job_async) + assert hasattr(client, 'create_job') + assert callable(client.create_job) @pytest.mark.asyncio async def test_wait_parameter_is_optional(self, mock_credential): @@ -594,12 +594,12 @@ async def test_wait_parameter_is_optional(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: # Call without wait parameter - await client.create_job_async( + await client.create_job( input=CreateJobInput(), subscription_id="sub123", resource_group_name="rg-test", @@ -611,7 +611,7 @@ async def test_wait_parameter_is_optional(self, mock_credential): mock_send.reset_mock() # Call with wait parameter - await client.create_job_async( + await client.create_job( input=CreateJobInput(), subscription_id="sub123", resource_group_name="rg-test", diff --git a/tests/test_azureblob.py b/tests/test_azureblob.py index dc7fbd4..e7cce2e 100644 --- a/tests/test_azureblob.py +++ b/tests/test_azureblob.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.azureblob import AzureblobClient from azure.connectors.azureblob import ( - AzureblobClient, SharedAccessSignatureBlobPolicy, ) from azure.connectors.sdk import ( @@ -49,7 +49,7 @@ def test_init_with_custom_settings(self, mock_credential): client = AzureblobClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -120,11 +120,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.copy_file_async( + result = await client.copy_file( dataset="mycontainer", source="/source/file.txt", destination="/dest/file.txt" @@ -150,11 +150,11 @@ async def test_with_overwrite_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.copy_file_async( + await client.copy_file( dataset="mycontainer", source="/source/file.txt", destination="/dest/file.txt", @@ -176,11 +176,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.copy_file_async( + result = await client.copy_file( dataset="mycontainer", source="/source/file.txt", destination="/dest/file.txt" @@ -199,12 +199,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.copy_file_async( + await client.copy_file( dataset="mycontainer", source="/source/file.txt", destination="/dest/file.txt" @@ -229,11 +229,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.create_block_blob_async( + await client.create_block_blob( input=blob_input, storage_account_name="mystorageaccount", folder_path="/uploads", @@ -267,11 +267,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_file_async( + result = await client.create_file( input=file_input, dataset="mycontainer", folder_path="/uploads", @@ -296,12 +296,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_file_async( + await client.create_file( input=b"file content", dataset="mycontainer", folder_path="/uploads", @@ -330,11 +330,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_share_link_by_path_async( + result = await client.create_share_link_by_path( input=policy_input, storage_account_name="mystorageaccount", path="/container/file.txt" @@ -358,12 +358,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_share_link_by_path_async( + await client.create_share_link_by_path( input=SharedAccessSignatureBlobPolicy(), storage_account_name="mystorageaccount", path="/container/file.txt" @@ -387,11 +387,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.delete_file_async( + await client.delete_file( dataset="mycontainer", id="blob123" ) @@ -415,26 +415,28 @@ async def test_success_with_json_response(self, mock_credential): mock_response = MockResponse( status=200, - text='{"extractedFiles": ["file1.txt", "file2.txt"]}' + text='["file1.txt", "file2.txt"]' ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.extract_folder_async( - dataset="mycontainer", - source="/archive.zip", - destination="/extracted" + result = await resolve_generated_result( + client.extract_folder( + dataset="mycontainer", + source="/archive.zip", + destination="/extracted" + ) ) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "POST" assert "extractFolderV2" in call_args[0][1] - assert "extractedFiles" in result + assert result == ["file1.txt", "file2.txt"] @pytest.mark.asyncio async def test_with_overwrite_parameter(self, mock_credential): @@ -448,15 +450,17 @@ async def test_with_overwrite_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.extract_folder_async( - dataset="mycontainer", - source="/archive.zip", - destination="/extracted", - overwrite="true" + await resolve_generated_result( + client.extract_folder( + dataset="mycontainer", + source="/archive.zip", + destination="/extracted", + overwrite="true" + ) ) call_args = mock_send.call_args @@ -474,15 +478,17 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.extract_folder_async( - dataset="mycontainer", - source="/archive.zip", - destination="/extracted" + await resolve_generated_result( + client.extract_folder( + dataset="mycontainer", + source="/archive.zip", + destination="/extracted" + ) ) assert exc_info.value.status_code == 400 @@ -501,29 +507,31 @@ async def test_success_with_json_response(self, mock_credential): mock_response = MockResponse( status=200, - text='{"policies": [{"id": "policy1", "permissions": "rwd"}]}' + text='[{"id": "policy1", "permissions": "rwd"}]' ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_access_policies_async( - storage_account_name="mystorageaccount", - path="/container/file.txt" + result = await resolve_generated_result( + client.list_access_policies( + storage_account_name="mystorageaccount", + path="/container/file.txt" + ) ) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/policies" in call_args[0][1] - assert "policies" in result + assert result == [{"id": "policy1", "permissions": "rwd"}] @pytest.mark.asyncio - async def test_empty_response_returns_none(self, mock_credential): - """Test that empty response returns None.""" + async def test_empty_response_returns_empty_page(self, mock_credential): + """Test that an empty response returns an empty page.""" client = AzureblobClient( "https://example.azure.com/connections/test", credential=mock_credential @@ -533,15 +541,17 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_access_policies_async( - storage_account_name="mystorageaccount", - path="/container/file.txt" + result = await resolve_generated_result( + client.list_access_policies( + storage_account_name="mystorageaccount", + path="/container/file.txt" + ) ) - assert result is None + assert result == [] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -555,14 +565,16 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_access_policies_async( - storage_account_name="mystorageaccount", - path="/container/file.txt" + await resolve_generated_result( + client.list_access_policies( + storage_account_name="mystorageaccount", + path="/container/file.txt" + ) ) assert exc_info.value.status_code == 404 @@ -585,11 +597,11 @@ async def test_success_returns_binary_content(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_file_content_async( + result = await client.get_file_content( dataset="mycontainer", id="blob123" ) @@ -613,11 +625,11 @@ async def test_with_infer_content_type_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_file_content_async( + await client.get_file_content( dataset="mycontainer", id="blob123", infer_content_type="true" @@ -638,12 +650,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_file_content_async( + await client.get_file_content( dataset="mycontainer", id="nonexistent" ) @@ -668,11 +680,11 @@ async def test_success_returns_binary_content(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_file_content_by_path_async( + result = await client.get_file_content_by_path( dataset="mycontainer", path="/folder/file.txt" ) @@ -695,12 +707,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_file_content_by_path_async( + await client.get_file_content_by_path( dataset="mycontainer", path="/nonexistent/path.txt" ) @@ -726,11 +738,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_file_metadata_async( + result = await client.get_file_metadata( dataset="mycontainer", id="blob123" ) @@ -754,11 +766,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_file_metadata_async( + result = await client.get_file_metadata( dataset="mycontainer", id="blob123" ) @@ -776,12 +788,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_file_metadata_async( + await client.get_file_metadata( dataset="mycontainer", id="nonexistent" ) @@ -807,11 +819,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_file_metadata_by_path_async( + result = await client.get_file_metadata_by_path( dataset="mycontainer", path="/folder/file.txt" ) @@ -834,11 +846,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_file_metadata_by_path_async( + result = await client.get_file_metadata_by_path( dataset="mycontainer", path="/folder/file.txt" ) @@ -856,12 +868,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_file_metadata_by_path_async( + await client.get_file_metadata_by_path( dataset="mycontainer", path="/nonexistent/path.txt" ) @@ -887,11 +899,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.list_folder_async( + result = await resolve_generated_result(client.list_folder( dataset="mycontainer", id="folder123" )) @@ -903,8 +915,8 @@ async def test_success_with_json_response(self, mock_credential): assert len(result) == 2 @pytest.mark.asyncio - async def test_with_pagination_parameters(self, mock_credential): - """Test GET request with pagination parameters.""" + async def test_with_optional_parameters(self, mock_credential): + """Test GET request with public optional parameters.""" client = AzureblobClient( "https://example.azure.com/connections/test", credential=mock_credential @@ -914,19 +926,18 @@ async def test_with_pagination_parameters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.list_folder_async( + await resolve_generated_result(client.list_folder( dataset="mycontainer", id="folder123", - next_page_marker="marker123", use_flat_listing="true" )) call_args = mock_send.call_args - assert "nextPageMarker=" in call_args[0][1] + assert "nextPageMarker=" not in call_args[0][1] assert "useFlatListing=true" in call_args[0][1] @pytest.mark.asyncio @@ -941,11 +952,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await resolve_generated_result(client.list_folder_async( + result = await resolve_generated_result(client.list_folder( dataset="mycontainer", id="folder123" )) @@ -963,12 +974,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(client.list_folder_async( + await resolve_generated_result(client.list_folder( dataset="mycontainer", id="nonexistent" )) @@ -994,12 +1005,12 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: result = await resolve_generated_result( - client.list_root_folder_async(dataset="mycontainer") + client.list_root_folder(dataset="mycontainer") ) mock_send.assert_called_once() @@ -1009,8 +1020,8 @@ async def test_success_with_json_response(self, mock_credential): assert len(result) == 2 @pytest.mark.asyncio - async def test_with_pagination_parameters(self, mock_credential): - """Test GET request with pagination parameters.""" + async def test_hides_continuation_parameter(self, mock_credential): + """Test that paging continuation is managed internally.""" client = AzureblobClient( "https://example.azure.com/connections/test", credential=mock_credential @@ -1020,17 +1031,16 @@ async def test_with_pagination_parameters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.list_root_folder_async( - dataset="mycontainer", - next_page_marker="marker456" + await resolve_generated_result(client.list_root_folder( + dataset="mycontainer" )) call_args = mock_send.call_args - assert "nextPageMarker=marker456" in call_args[0][1] + assert "nextPageMarker=" not in call_args[0][1] @pytest.mark.asyncio async def test_empty_response_returns_none(self, mock_credential): @@ -1044,12 +1054,12 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): result = await resolve_generated_result( - client.list_root_folder_async(dataset="mycontainer") + client.list_root_folder(dataset="mycontainer") ) assert result == [] @@ -1065,12 +1075,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(client.list_root_folder_async(dataset="mycontainer")) + await resolve_generated_result(client.list_root_folder(dataset="mycontainer")) assert exc_info.value.status_code == 403 @@ -1090,11 +1100,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.set_blob_tier_by_path_async( + await client.set_blob_tier_by_path( storage_account_name="mystorageaccount", path="/container/file.txt", new_tier="Cool" @@ -1126,11 +1136,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.update_file_async( + result = await client.update_file( input=update_input, dataset="mycontainer", id="blob123" @@ -1154,11 +1164,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.update_file_async( + result = await client.update_file( input=b"updated content", dataset="mycontainer", id="blob123" @@ -1177,12 +1187,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.update_file_async( + await client.update_file( input=b"updated content", dataset="mycontainer", id="nonexistent" diff --git a/tests/test_azuredatafactory.py b/tests/test_azuredatafactory.py index 6cfaa25..692272c 100644 --- a/tests/test_azuredatafactory.py +++ b/tests/test_azuredatafactory.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.azuredatafactory import AzuredatafactoryClient from azure.connectors.azuredatafactory import ( - AzuredatafactoryClient, CreatePipelineRunResponse, PipelineRun, DataFactoryListResult, @@ -27,6 +27,7 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import model_instance class TestAzuredatafactoryClientInitialization: @@ -72,7 +73,7 @@ def test_init_with_custom_settings(self, mock_credential): client = AzuredatafactoryClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -151,14 +152,14 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = ParameterValueSpecification( additional_properties={"param1": "value1"} ) - result = await client.create_pipeline_run_async( + result = await client.create_pipeline_run( input=input_data, subscription_id="sub-123", resource_group_name="rg-test", @@ -189,12 +190,12 @@ async def test_success_with_reference_pipeline_run_id( with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = ParameterValueSpecification() - result = await client.create_pipeline_run_async( + result = await client.create_pipeline_run( input=input_data, subscription_id="sub-123", resource_group_name="rg-test", @@ -219,12 +220,12 @@ async def test_success_with_empty_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): input_data = ParameterValueSpecification() - result = await client.create_pipeline_run_async( + result = await client.create_pipeline_run( input=input_data, subscription_id="sub-123", resource_group_name="rg-test", @@ -249,14 +250,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): input_data = ParameterValueSpecification() with pytest.raises(ConnectorException) as exc_info: - await client.create_pipeline_run_async( + await client.create_pipeline_run( input=input_data, subscription_id="sub-123", resource_group_name="rg-test", @@ -274,8 +275,8 @@ async def test_method_exists(self, mock_credential): credential=mock_credential ) - assert hasattr(client, 'create_pipeline_run_async') - assert callable(client.create_pipeline_run_async) + assert hasattr(client, 'create_pipeline_run') + assert callable(client.create_pipeline_run) class TestCancelPipelineRunAsync: @@ -293,11 +294,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.cancel_pipeline_run_async( + await client.cancel_pipeline_run( subscription_id="sub-123", resource_group_name="rg-test", data_factory_name="adf-test", @@ -317,8 +318,8 @@ async def test_method_exists(self, mock_credential): credential=mock_credential ) - assert hasattr(client, 'cancel_pipeline_run_async') - assert callable(client.cancel_pipeline_run_async) + assert hasattr(client, 'cancel_pipeline_run') + assert callable(client.cancel_pipeline_run) class TestGetPipelineRunAsync: @@ -340,11 +341,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_pipeline_run_async( + result = await client.get_pipeline_run( subscription_id="sub-123", resource_group_name="rg-test", data_factory_name="adf-test", @@ -370,11 +371,11 @@ async def test_success_with_empty_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_pipeline_run_async( + result = await client.get_pipeline_run( subscription_id="sub-123", resource_group_name="rg-test", data_factory_name="adf-test", @@ -398,12 +399,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_pipeline_run_async( + await client.get_pipeline_run( subscription_id="sub-123", resource_group_name="rg-test", data_factory_name="adf-test", @@ -420,8 +421,8 @@ async def test_method_exists(self, mock_credential): credential=mock_credential ) - assert hasattr(client, 'get_pipeline_run_async') - assert callable(client.get_pipeline_run_async) + assert hasattr(client, 'get_pipeline_run') + assert callable(client.get_pipeline_run) class TestDataClasses: @@ -576,7 +577,7 @@ def test_resource_group(self): def test_resource_group_list_result(self): """Test ResourceGroupListResult dataclass creation.""" - rg = ResourceGroup(name="rg1") + rg = model_instance(ResourceGroup, name="rg1") result = ResourceGroupListResult( value=[rg], next_link=None diff --git a/tests/test_azuredigitaltwins.py b/tests/test_azuredigitaltwins.py index e2a3733..c1e7268 100644 --- a/tests/test_azuredigitaltwins.py +++ b/tests/test_azuredigitaltwins.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.azuredigitaltwins import AzuredigitaltwinsClient from azure.connectors.azuredigitaltwins import ( - AzuredigitaltwinsClient, AddTwinInput, AddRelationshipInput, ListModelsResponse, @@ -115,7 +115,7 @@ def test_init_with_custom_settings(self, mock_credential): client = AzuredigitaltwinsClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -187,12 +187,14 @@ async def test_uses_current_signature_and_internal_api_version( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text="{}"), ) as mock_send: - method = getattr(client, f"{operation}_async") - await method(input=input_value, **operation_args) + method = getattr(client, f"{operation}") + await resolve_generated_result( + method(input=input_value, **operation_args) + ) mock_send.assert_called_once_with( http_method, @@ -226,13 +228,15 @@ async def test_error_response_raises_exception( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=400, text="Invalid update"), ): - method = getattr(client, f"{operation}_async") + method = getattr(client, f"{operation}") with pytest.raises(ConnectorException) as exc_info: - await method(input=input_value, **operation_args) + await resolve_generated_result( + method(input=input_value, **operation_args) + ) assert exc_info.value.status_code == 400 @@ -269,11 +273,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.list_models_async()) + result = await resolve_generated_result(client.list_models()) mock_send.assert_called_once() call_args = mock_send.call_args @@ -293,11 +297,11 @@ async def test_with_optional_parameters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.list_models_async( + await resolve_generated_result(client.list_models( dependencies_for="dtmi:example:Room;1", include_model_definition="true" )) @@ -318,12 +322,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(client.list_models_async()) + await resolve_generated_result(client.list_models()) assert exc_info.value.status_code == 401 @@ -346,11 +350,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_model_by_id_async( + result = await client.get_model_by_id( modelid="dtmi:example:Room;1" ) @@ -369,12 +373,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_model_by_id_async( + await client.get_model_by_id( modelid="nonexistent" ) @@ -396,11 +400,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.delete_model_async( + await client.delete_model( modelid="dtmi:example:Room;1" ) @@ -427,11 +431,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_twin_by_id_async( + result = await client.get_twin_by_id( twinid="room1" ) @@ -450,12 +454,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_twin_by_id_async( + await client.get_twin_by_id( twinid="nonexistent" ) @@ -480,12 +484,12 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = AddTwinInput(value='{"$dtId": "room1"}') - result = await client.add_twin_async( + result = await client.add_twin( input=input_data, twinid="room1" ) @@ -511,11 +515,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.delete_twin_async( + await client.delete_twin( twinid="room1" ) @@ -542,11 +546,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_component_async( + result = await client.get_component( twinid="room1", component_path="thermostat" ) @@ -575,11 +579,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_relationship_by_id_async( + result = await client.get_relationship_by_id( twinid="room1", relationship_id="rel1" ) @@ -606,12 +610,12 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = AddRelationshipInput(value='{"$targetId": "floor1"}') - result = await client.add_relationship_async( + result = await client.add_relationship( input=input_data, twinid="room1", relationship_id="rel1" @@ -638,11 +642,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.delete_relationship_async( + await client.delete_relationship( twinid="room1", relationship_id="rel1" ) @@ -670,11 +674,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.list_relationships_async( + result = await resolve_generated_result(client.list_relationships( twinid="room1" )) @@ -700,11 +704,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.list_incoming_relationships_async( + result = await resolve_generated_result(client.list_incoming_relationships( twinid="room1" )) @@ -731,14 +735,14 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: query_input = QueryTwinsInput( query="SELECT * FROM digitaltwins WHERE $dtId = 'room1'" ) - result = await client.query_twins_async( + result = await client.query_twins( input=query_input ) @@ -760,14 +764,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): query_input = QueryTwinsInput(query="INVALID") with pytest.raises(ConnectorException) as exc_info: - await client.query_twins_async( + await client.query_twins( input=query_input ) @@ -789,12 +793,12 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: telemetry = SendTelemetryInput(value='{"temperature": 72}') - await client.send_telemetry_async( + await client.send_telemetry( input=telemetry, twinid="room1" ) @@ -818,12 +822,12 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: telemetry = SendComponentTelemetryInput(value='{"temperature": 72}') - await client.send_component_telemetry_async( + await client.send_component_telemetry( input=telemetry, twinid="room1", component_path="thermostat" diff --git a/tests/test_azureeventgrid.py b/tests/test_azureeventgrid.py index 241bc8b..14a1620 100644 --- a/tests/test_azureeventgrid.py +++ b/tests/test_azureeventgrid.py @@ -6,8 +6,8 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.azureeventgrid import AzureeventgridClient from azure.connectors.azureeventgrid import ( - AzureeventgridClient, EventRequest, EventSchema, EventTypesResponse, @@ -21,21 +21,17 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import model_instance, resolve_generated_result async def _invoke_operation(client: AzureeventgridClient, operation: str): """Invoke an Event Grid operation by name for shared error-handling tests.""" - if operation == "subscriptions_list": - return await client.subscriptions_list_async() - if operation == "topic_types_list": - return await client.topic_types_list_async() - - raise ValueError(f"Unsupported operation '{operation}'.") + return await resolve_generated_result(getattr(client, operation)()) ALL_OPERATIONS = [ - "subscriptions_list", - "topic_types_list", + "list_subscriptions", + "list_topic_types", ] @@ -72,7 +68,7 @@ def test_init_with_custom_settings(self, mock_credential): client = AzureeventgridClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -139,13 +135,13 @@ async def test_subscriptions_list_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.subscriptions_list_async() + result = await resolve_generated_result(client.list_subscriptions()) - assert result["value"][0]["subscriptionId"] == "sub-1" + assert result == [{"subscriptionId": "sub-1"}] assert mock_send.call_args[0][0] == "GET" assert "/subscriptions" in mock_send.call_args[0][1] assert "x-ms-api-version=2015-11-01" in mock_send.call_args[0][1] @@ -161,20 +157,20 @@ async def test_topic_types_list_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.topic_types_list_async() + result = await resolve_generated_result(client.list_topic_types()) - assert "value" in result + assert result == [] request_url = mock_send.call_args[0][1] assert "/providers/Microsoft.EventGrid/topicTypes" in request_url assert "x-ms-api-version=2017-09-15-preview" in request_url @pytest.mark.asyncio - async def test_topic_types_list_empty_body_returns_none(self, mock_credential): - """Test topic_types_list_async returns None when the body is empty.""" + async def test_topic_types_list_empty_body_returns_empty_page(self, mock_credential): + """Test topic_types_list_async returns an empty page for an empty body.""" client = AzureeventgridClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -183,13 +179,13 @@ async def test_topic_types_list_empty_body_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.topic_types_list_async() + result = await resolve_generated_result(client.list_topic_types()) - assert result is None + assert result == [] class TestAzureeventgridClientErrorHandling: @@ -211,7 +207,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -230,7 +226,7 @@ def test_dataclass_instances_initialize_expected_defaults(self): topic_types = TopicTypesResponse() event_types = EventTypesResponse() resource_names = ResourceNameResponse() - event_request = EventRequest() + event_request = model_instance(EventRequest) event_schema: EventSchema = [] subscription = Subscription() @@ -238,7 +234,7 @@ def test_dataclass_instances_initialize_expected_defaults(self): assert topic_types.value is None assert event_types.value is None assert resource_names.value is None - assert event_request.properties is None + assert event_request.properties == {"key": "value"} assert event_schema == [] assert subscription.subscription_id is None diff --git a/tests/test_azureiotcentral.py b/tests/test_azureiotcentral.py index e98fdaf..7463957 100644 --- a/tests/test_azureiotcentral.py +++ b/tests/test_azureiotcentral.py @@ -6,8 +6,8 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.azureiotcentral import AzureiotcentralClient from azure.connectors.azureiotcentral import ( - AzureiotcentralClient, Device, DeviceCloudProperties, DeviceCommand, @@ -24,7 +24,7 @@ ConnectorException, ) from tests.conftest import MockResponse -from tests.generated_connector_test_utils import resolve_generated_result +from tests.generated_connector_test_utils import model_instance, resolve_generated_result BASE_URL = "https://example.azure.com/connections/test" @@ -34,11 +34,11 @@ # keyword arguments required to invoke it. The "input" body argument is passed # as an empty dict since send_async is mocked in every test. OPERATION_ARGS = { - "device_groups_list": {"application": "app-1"}, + "list_device_groups": {"application": "app-1"}, "device_groups_get": {"device_group_id": "dg-1", "application": "app-1"}, "device_groups_set": {"input": {}, "device_group_id": "dg-1", "application": "app-1"}, "device_groups_remove": {"device_group_id": "dg-1", "application": "app-1"}, - "device_groups_get_devices": {"device_group_id": "dg-1", "application": "app-1"}, + "list_device_groups_get_devices": {"device_group_id": "dg-1", "application": "app-1"}, "devices_get_cloud_properties": {"device_id": "d-1", "application": "app-1"}, "devices_update_cloud_properties": {"input": {}, "device_id": "d-1", "application": "app-1"}, "devices_execute_component_command": { @@ -48,7 +48,7 @@ "command_name": "cmd-1", "application": "app-1", }, - "device_relationships_list": {"device_id": "d-1", "application": "app-1"}, + "list_device_relationships": {"device_id": "d-1", "application": "app-1"}, "device_relationships_get": { "device_id": "d-1", "relationship_id": "r-1", @@ -71,14 +71,14 @@ "relationship_id": "r-1", "application": "app-1", }, - "jobs_list": {"application": "app-1"}, + "list_jobs": {"application": "app-1"}, "jobs_get": {"job_id": "j-1", "application": "app-1"}, "jobs_set": {"input": {}, "job_id": "j-1", "application": "app-1"}, - "jobs_get_devices": {"job_id": "j-1", "application": "app-1"}, + "list_jobs_get_devices": {"job_id": "j-1", "application": "app-1"}, "jobs_stop": {"job_id": "j-1", "application": "app-1"}, "jobs_resume": {"job_id": "j-1", "application": "app-1"}, "jobs_rerun": {"job_id": "j-1", "rerun_id": "rr-1", "application": "app-1"}, - "organizations_list": {"application": "app-1"}, + "list_organizations": {"application": "app-1"}, "organizations_get": {"organization_id": "o-1", "application": "app-1"}, "organizations_set": { "input": {}, @@ -86,7 +86,7 @@ "application": "app-1", }, "organizations_remove": {"organization_id": "o-1", "application": "app-1"}, - "scheduled_jobs_list": {"application": "app-1"}, + "list_scheduled_jobs": {"application": "app-1"}, "scheduled_jobs_get": {"scheduled_job_id": "sj-1", "application": "app-1"}, "scheduled_jobs_set": { "input": {}, @@ -99,7 +99,7 @@ "application": "app-1", }, "scheduled_jobs_remove": {"scheduled_job_id": "sj-1", "application": "app-1"}, - "scheduled_jobs_list_jobs": {"scheduled_job_id": "sj-1", "application": "app-1"}, + "list_scheduled_jobs_list_jobs": {"scheduled_job_id": "sj-1", "application": "app-1"}, "devices_get": {"device_id": "d-1", "application": "app-1"}, "devices_get_command_response": { "device_id": "d-1", @@ -151,7 +151,7 @@ "telemetry_name": "t-1", "application": "app-1", }, - "devices_list": {"application": "app-1"}, + "list_devices": {"application": "app-1"}, "devices_remove": {"device_id": "d-1", "application": "app-1"}, "devices_run_command": { "input": {}, @@ -190,22 +190,22 @@ }, "devices_update_properties": {"input": {}, "device_id": "d-1", "application": "app-1"}, "device_templates_get": {"template_id": "tpl-1", "application": "app-1"}, - "device_templates_list": {"application": "app-1"}, - "device_templates_list_2": {"application": "app-1"}, + "list_device_templates": {"application": "app-1"}, + "list_device_templates_2": {"application": "app-1"}, "device_templates_remove": {"template_id": "tpl-1", "application": "app-1"}, "roles_get": {"role_id": "role-1", "application": "app-1"}, - "roles_list": {"application": "app-1"}, + "list_roles": {"application": "app-1"}, "users_create": {"input": {}, "user_id": "u-1", "application": "app-1"}, "users_get": {"user_id": "u-1", "application": "app-1"}, - "users_list": {"application": "app-1"}, + "list_users": {"application": "app-1"}, "users_remove": {"user_id": "u-1", "application": "app-1"}, "users_update": {"input": {}, "user_id": "u-1", "application": "app-1"}, - "applications_list": {}, - "workflow_get_components": {"application": "app-1", "template": "tpl-1"}, - "workflow_get_capabilities": {"application": "app-1", "template": "tpl-1"}, - "workflow_get_capabilities_v1": {"application": "app-1", "template": "tpl-1"}, - "workflow_get_components_v1": {"application": "app-1", "template": "tpl-1"}, - "workflow_get_modules": {"application": "app-1", "template": "tpl-1"}, + "list_applications": {}, + "list_workflow_get_components": {"application": "app-1", "template": "tpl-1"}, + "list_workflow_get_capabilities": {"application": "app-1", "template": "tpl-1"}, + "list_workflow_get_capabilities_v1": {"application": "app-1", "template": "tpl-1"}, + "list_workflow_get_components_v1": {"application": "app-1", "template": "tpl-1"}, + "list_workflow_get_modules": {"application": "app-1", "template": "tpl-1"}, "schema_device_cloud_properties": {"application": "app-1"}, "schema_device_command": {"application": "app-1"}, "schema_device_command_v1": {"application": "app-1"}, @@ -232,7 +232,7 @@ async def _invoke_operation(client: AzureiotcentralClient, operation: str): """Invoke an IoT Central operation by name for shared method tests.""" - method = getattr(client, f"{operation}_async") + method = getattr(client, f"{operation}") return await resolve_generated_result(method(**OPERATION_ARGS[operation])) @@ -271,7 +271,7 @@ def test_init_with_custom_settings(self, mock_credential): client = AzureiotcentralClient( BASE_URL, credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -329,11 +329,11 @@ async def test_devices_list_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await resolve_generated_result(client.devices_list_async(application="app-1")) + result = await resolve_generated_result(client.list_devices(application="app-1")) assert result[0]["id"] == "d-1" assert mock_send.call_args[0][0] == "GET" @@ -349,11 +349,11 @@ async def test_devices_get_targets_device_path(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.devices_get_async(device_id="d-1", application="app-1") + result = await client.devices_get(device_id="d-1", application="app-1") assert result["id"] == "d-1" assert "/devices/d-1" in mock_send.call_args[0][1] @@ -363,15 +363,15 @@ async def test_device_groups_set_sends_put_and_body(self, mock_credential): """Test device_groups_set_async issues a PUT and forwards the body.""" client = _make_client(mock_credential) mock_response = MockResponse(status=200, text='{"id":"dg-1"}') - body = DeviceGroup(display_name="group") + body = model_instance(DeviceGroup, display_name="group") with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.device_groups_set_async( + result = await client.device_groups_set( input=body, device_group_id="dg-1", application="app-1", @@ -394,11 +394,11 @@ async def test_execute_component_command_sends_post_and_body( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.devices_execute_component_command_async( + await client.devices_execute_component_command( input=body, device_id="d-1", component_name="component-1", @@ -417,15 +417,15 @@ async def test_device_relationships_update_sends_patch_and_body( """Test device_relationships_update_async forwards the PATCH body.""" client = _make_client(mock_credential) mock_response = MockResponse(status=200, text="{}") - body = DeviceRelationship() + body = model_instance(DeviceRelationship) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.device_relationships_update_async( + await client.device_relationships_update( input=body, device_id="d-1", relationship_id="relationship-1", @@ -443,11 +443,11 @@ async def test_device_groups_remove_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.device_groups_remove_async( + result = await client.device_groups_remove( device_group_id="dg-1", application="app-1", ) @@ -463,12 +463,12 @@ async def test_jobs_set_appends_optional_job_type(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.jobs_set_async( - input=Job(display_name="job"), + await client.jobs_set( + input=model_instance(Job, display_name="job"), job_id="j-1", application="app-1", job_type="cloudProperty", @@ -485,11 +485,11 @@ async def test_devices_get_command_response_encodes_query_value(self, mock_crede with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.devices_get_command_response_async( + await client.devices_get_command_response( device_id="d-1", command_name="cmd-1", application="app one", @@ -508,11 +508,11 @@ async def test_empty_body_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await resolve_generated_result(client.devices_list_async(application="app-1")) + result = await resolve_generated_result(client.list_devices(application="app-1")) assert result == [] @@ -525,7 +525,7 @@ async def test_all_operations_success(self, mock_credential, operation): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: @@ -551,7 +551,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -566,16 +566,16 @@ class TestAzureiotcentralTypeSerialization: def test_dataclass_instances_initialize_expected_defaults(self): """Test generated dataclasses initialize with expected default values.""" - device_group = DeviceGroup() - device = Device() - device_command = DeviceCommand() - cloud_properties = DeviceCloudProperties() - relationship = DeviceRelationship() - job = Job() - organization = Organization() - scheduled_job = ScheduledJob() - user = User() - trigger = WorkflowTrigger() + device_group = model_instance(DeviceGroup) + device = model_instance(Device) + device_command = model_instance(DeviceCommand) + cloud_properties = model_instance(DeviceCloudProperties) + relationship = model_instance(DeviceRelationship) + job = model_instance(Job) + organization = model_instance(Organization) + scheduled_job = model_instance(ScheduledJob) + user = model_instance(User) + trigger = model_instance(WorkflowTrigger) assert device_group.id is None assert device.id is None diff --git a/tests/test_azuremonitorlogs.py b/tests/test_azuremonitorlogs.py index 764791e..824dd17 100644 --- a/tests/test_azuremonitorlogs.py +++ b/tests/test_azuremonitorlogs.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.azuremonitorlogs import AzuremonitorlogsClient from azure.connectors.azuremonitorlogs import ( - AzuremonitorlogsClient, QueryDataInput, QuerySchemaInput, VisualizeQueryInput, @@ -20,7 +20,7 @@ ConnectorException, ) from tests.conftest import MockResponse -from tests.generated_connector_test_utils import resolve_generated_result +from tests.generated_connector_test_utils import model_instance, resolve_generated_result class TestAzuremonitorlogsClientInitialization: @@ -66,7 +66,7 @@ def test_init_with_custom_settings(self, mock_credential): client = AzuremonitorlogsClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -189,11 +189,11 @@ async def test_success_returns_json(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await resolve_generated_result(client.list_subscriptions_async()) + result = await resolve_generated_result(client.list_subscriptions()) mock_send.assert_called_once_with( "GET", @@ -216,12 +216,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=500, text="Server error"), ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(client.list_subscriptions_async()) + await resolve_generated_result(client.list_subscriptions()) assert exc_info.value.status_code == 500 @@ -239,12 +239,12 @@ async def test_success_appends_query_params(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"value": []}'), ) as mock_send: await resolve_generated_result( - client.list_resource_groups_async(subscriptions="sub-id") + client.list_resource_groups(subscriptions="sub-id") ) call_args = mock_send.call_args @@ -273,11 +273,11 @@ async def test_success_appends_multiple_query_params( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"value": []}'), ) as mock_send: - await resolve_generated_result(client.list_resources_async( + await resolve_generated_result(client.list_resources( subscriptions="sub-id", resourcegroups="rg1", resourcetype="Microsoft.OperationalInsights/workspaces", @@ -301,18 +301,19 @@ async def test_success_sends_body_and_returns_json(self, mock_credential): credential=mock_credential, ) - request_body = QueryDataInput( + request_body = model_instance( + QueryDataInput, query="Heartbeat | take 1", timerangetype="SetInQuery", ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"value": [{"Computer": "vm1"}]}'), ) as mock_send: - result = await client.query_data_async( + result = await client.query_data( input=request_body, subscriptions="sub-id", resourcegroups="rg1", @@ -334,12 +335,12 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text=""), ): - result = await client.query_data_async( - input=QueryDataInput(), + result = await client.query_data( + input=model_instance(QueryDataInput), subscriptions="sub-id", resourcegroups="rg1", resourcetype="type", @@ -365,14 +366,14 @@ async def test_success_returns_dynamic_schema_payload( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse( status=200, text='{"type": "object", "properties": {"Computer": {"type": "string"}}}' ), ): - result = await client.query_schema_async( + result = await client.query_schema( input=QuerySchemaInput(), subscriptions="sub-id", resourcegroups="rg1", @@ -395,18 +396,19 @@ async def test_success_with_vis_type(self, mock_credential): credential=mock_credential, ) - body = VisualizeQueryInput( + body = model_instance( + VisualizeQueryInput, query="Heartbeat | summarize count() by bin(TimeGenerated, 1h)", timerangetype="SetInQuery", ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"body": "ok"}'), ) as mock_send: - result = await client.visualize_query_async( + result = await client.visualize_query( input=body, subscriptions="sub-id", resourcegroups="rg1", @@ -430,7 +432,7 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse( status=400, @@ -438,8 +440,8 @@ async def test_error_response_raises_exception(self, mock_credential): ), ): with pytest.raises(ConnectorException) as exc_info: - await client.visualize_query_async( - input=VisualizeQueryInput(), + await client.visualize_query( + input=model_instance(VisualizeQueryInput), subscriptions="sub-id", resourcegroups="rg1", resourcetype="type", @@ -463,14 +465,14 @@ async def test_success_returns_control_schema(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse( status=200, text='{"type": "Relative"}', ), ) as mock_send: - result = await client.get_time_range_selection_control_async( + result = await client.get_time_range_selection_control( timerangetype="Relative range", ) @@ -496,12 +498,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=400, text="Invalid time range"), ): with pytest.raises(ConnectorException) as exc_info: - await client.get_time_range_selection_control_async( + await client.get_time_range_selection_control( timerangetype="invalid", ) diff --git a/tests/test_azurequeues.py b/tests/test_azurequeues.py index fc8b614..d046d86 100644 --- a/tests/test_azurequeues.py +++ b/tests/test_azurequeues.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.azurequeues import AzurequeuesClient from azure.connectors.azurequeues import ( - AzurequeuesClient, Messages, QueueArray, PutMessageInput, @@ -22,6 +22,7 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestAzurequeuesClientInitialization: @@ -57,7 +58,7 @@ def test_init_with_custom_settings(self, mock_credential): client = AzurequeuesClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -125,11 +126,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.delete_message_async( + await client.delete_message( storage_account_name="mystorageaccount", queue_name="myqueue", message_id="msg-123", @@ -152,7 +153,7 @@ async def test_popreceipt_is_required(self, mock_credential): ) with pytest.raises(TypeError): - await client.delete_message_async( + await client.delete_message( storage_account_name="mystorageaccount", queue_name="myqueue", message_id="msg-123" @@ -166,23 +167,23 @@ async def test_error_response_raises_exception(self, mock_credential): credential=mock_credential ) - mock_response = MockResponse(status=404, text='{"error": "Message not found"}') + mock_response = MockResponse(status=500, text='{"error": "Server error"}') with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.delete_message_async( + await client.delete_message( storage_account_name="mystorageaccount", queue_name="myqueue", message_id="nonexistent", popreceipt="receipt-abc" ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestGetMessages: @@ -203,11 +204,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_messages_async( + result = await client.get_messages( storage_account_name="mystorageaccount", queue_name="myqueue" ) @@ -230,11 +231,11 @@ async def test_with_query_parameters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_messages_async( + await client.get_messages( storage_account_name="mystorageaccount", queue_name="myqueue", numofmessages="10", @@ -258,12 +259,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_messages_async( + await client.get_messages( storage_account_name="mystorageaccount", queue_name="nonexistent" ) @@ -284,24 +285,24 @@ async def test_success_with_json_response(self, mock_credential): mock_response = MockResponse( status=200, - text='{"value": [{"name": "queue1"}, {"name": "queue2"}]}' + text='[{"name": "queue1"}, {"name": "queue2"}]' ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.list_queues_async( + result = await resolve_generated_result(client.list_queues( storage_account_name="mystorageaccount" - ) + )) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/storageAccounts/mystorageaccount/queues/list" in call_args[0][1] - assert len(result["value"]) == 2 + assert len(result) == 2 @pytest.mark.asyncio async def test_empty_response_returns_none(self, mock_credential): @@ -315,14 +316,14 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.list_queues_async( + result = await resolve_generated_result(client.list_queues( storage_account_name="mystorageaccount" - ) - assert result is None + )) + assert result == [] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -336,14 +337,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.list_queues_async( + await resolve_generated_result(client.list_queues( storage_account_name="nonexistent" - ) + )) assert exc_info.value.status_code == 404 @@ -375,11 +376,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.put_message_async( + await client.put_message( input=message_input, storage_account_name="mystorageaccount", queue_name="myqueue" @@ -407,12 +408,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.put_message_async( + await client.put_message( input=message_input, storage_account_name="mystorageaccount", queue_name="myqueue" @@ -439,11 +440,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.put_queue_async( + result = await client.put_queue( storage_account_name="mystorageaccount", queue_name="newqueue" ) @@ -467,12 +468,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.put_queue_async( + await client.put_queue( storage_account_name="mystorageaccount", queue_name="existingqueue" ) @@ -581,16 +582,16 @@ async def test_multiple_consecutive_calls(self, mock_credential): credential=mock_credential ) - mock_response = MockResponse(status=200, text='{"value": []}') + mock_response = MockResponse(status=200, text='[]') with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.list_queues_async(storage_account_name="account1") - await client.list_queues_async(storage_account_name="account2") + await resolve_generated_result(client.list_queues(storage_account_name="account1")) + await resolve_generated_result(client.list_queues(storage_account_name="account2")) assert mock_send.call_count == 2 @@ -606,11 +607,11 @@ async def test_special_characters_in_queue_name(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_messages_async( + await client.get_messages( storage_account_name="mystorageaccount", queue_name="my-queue-name" ) diff --git a/tests/test_azuretables.py b/tests/test_azuretables.py index cbec479..39eea3e 100644 --- a/tests/test_azuretables.py +++ b/tests/test_azuretables.py @@ -6,8 +6,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.azuretables import AzuretablesClient from azure.connectors.azuretables import ( - AzuretablesClient, CreateEntityInput, InsertEntityResponse, CreateTableInput, @@ -63,7 +63,7 @@ def test_init_with_custom_settings(self, mock_credential): client = AzuretablesClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -137,11 +137,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_entity_async( + result = await client.create_entity( input=entity_input, storage_account_name="mystorageaccount", table_name="mytable" @@ -166,12 +166,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_entity_async( + await client.create_entity( input=entity_input, storage_account_name="mystorageaccount", table_name="mytable" @@ -199,11 +199,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_table_async( + result = await client.create_table( input=table_input, storage_account_name="mystorageaccount" ) @@ -227,12 +227,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_table_async( + await client.create_table( input=table_input, storage_account_name="mystorageaccount" ) @@ -255,11 +255,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.delete_entity_async( + await client.delete_entity( storage_account_name="mystorageaccount", table_name="mytable", partition_key="pk1", @@ -279,23 +279,23 @@ async def test_error_response_raises_exception(self, mock_credential): credential=mock_credential ) - mock_response = MockResponse(status=404, text='{"error": "Entity not found"}') + mock_response = MockResponse(status=500, text='{"error": "Server error"}') with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.delete_entity_async( + await client.delete_entity( storage_account_name="mystorageaccount", table_name="mytable", partition_key="nonexistent", row_key="nonexistent" ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestDeleteTable: @@ -313,11 +313,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.delete_table_async( + await client.delete_table( storage_account_name="mystorageaccount", table_name="mytable" ) @@ -335,21 +335,21 @@ async def test_error_response_raises_exception(self, mock_credential): credential=mock_credential ) - mock_response = MockResponse(status=404, text='{"error": "Table not found"}') + mock_response = MockResponse(status=500, text='{"error": "Server error"}') with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.delete_table_async( + await client.delete_table( storage_account_name="mystorageaccount", table_name="nonexistent" ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestGetEntities: @@ -373,11 +373,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.get_entities_async( + result = await resolve_generated_result(client.list_entities( storage_account_name="mystorageaccount", table_name="mytable" )) @@ -400,11 +400,11 @@ async def test_with_query_parameters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.get_entities_async( + await resolve_generated_result(client.list_entities( storage_account_name="mystorageaccount", table_name="mytable", filter="PartitionKey eq 'pk1'", @@ -428,12 +428,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(client.get_entities_async( + await resolve_generated_result(client.list_entities( storage_account_name="mystorageaccount", table_name="nonexistent" )) @@ -459,11 +459,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_entity_async( + result = await client.get_entity( storage_account_name="mystorageaccount", table_name="mytable", partition_key="pk1", @@ -488,11 +488,11 @@ async def test_with_select_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_entity_async( + await client.get_entity( storage_account_name="mystorageaccount", table_name="mytable", partition_key="pk1", @@ -516,12 +516,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_entity_async( + await client.get_entity( storage_account_name="mystorageaccount", table_name="mytable", partition_key="nonexistent", @@ -549,11 +549,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_table_async( + result = await client.get_table( storage_account_name="mystorageaccount", table_name="mytable" ) @@ -576,12 +576,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_table_async( + await client.get_table( storage_account_name="mystorageaccount", table_name="nonexistent" ) @@ -590,7 +590,7 @@ async def test_error_response_raises_exception(self, mock_credential): class TestGetTables: - """Tests for get_tables_async method.""" + """Tests for list_tables method.""" @pytest.mark.asyncio async def test_success_with_json_response(self, mock_credential): @@ -607,19 +607,19 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_tables_async( - storage_account_name="mystorageaccount" + result = await resolve_generated_result( + client.list_tables(storage_account_name="mystorageaccount") ) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/storageAccounts/mystorageaccount/tables" in call_args[0][1] - assert len(result["value"]) == 2 + assert len(result) == 2 @pytest.mark.asyncio async def test_empty_response_returns_none(self, mock_credential): @@ -633,14 +633,14 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_tables_async( - storage_account_name="mystorageaccount" + result = await resolve_generated_result( + client.list_tables(storage_account_name="mystorageaccount") ) - assert result is None + assert result == [] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -654,13 +654,13 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_tables_async( - storage_account_name="nonexistent" + await resolve_generated_result( + client.list_tables(storage_account_name="nonexistent") ) assert exc_info.value.status_code == 404 @@ -684,11 +684,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.insert_merge_entity_async( + await client.insert_merge_entity( input=entity_input, storage_account_name="mystorageaccount", table_name="mytable", @@ -714,12 +714,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.insert_merge_entity_async( + await client.insert_merge_entity( input=entity_input, storage_account_name="mystorageaccount", table_name="mytable", @@ -748,11 +748,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.insert_replace_entity_async( + await client.insert_replace_entity( input=entity_input, storage_account_name="mystorageaccount", table_name="mytable", @@ -778,12 +778,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.insert_replace_entity_async( + await client.insert_replace_entity( input=entity_input, storage_account_name="mystorageaccount", table_name="mytable", @@ -812,11 +812,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.merge_entity_async( + await client.merge_entity( input=entity_input, storage_account_name="mystorageaccount", table_name="mytable", @@ -842,12 +842,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.merge_entity_async( + await client.merge_entity( input=entity_input, storage_account_name="mystorageaccount", table_name="mytable", @@ -876,11 +876,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.replace_entity_async( + await client.replace_entity( input=entity_input, storage_account_name="mystorageaccount", table_name="mytable", @@ -906,12 +906,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.replace_entity_async( + await client.replace_entity( input=entity_input, storage_account_name="mystorageaccount", table_name="mytable", @@ -1087,12 +1087,16 @@ async def test_multiple_consecutive_calls(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_tables_async(storage_account_name="account1") - await client.get_tables_async(storage_account_name="account2") + await resolve_generated_result( + client.list_tables(storage_account_name="account1") + ) + await resolve_generated_result( + client.list_tables(storage_account_name="account2") + ) assert mock_send.call_count == 2 @@ -1108,11 +1112,11 @@ async def test_special_characters_in_keys(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_entity_async( + await client.get_entity( storage_account_name="mystorageaccount", table_name="mytable", partition_key="pk-1", @@ -1136,14 +1140,14 @@ async def test_success_returns_storage_accounts(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=MockResponse( status=200, text='{"value": [{"name": "account1"}]}' ) ) as mock_send: - result = await client.get_storage_accounts_async() + result = await resolve_generated_result(client.list_storage_accounts()) mock_send.assert_called_once_with( "GET", @@ -1154,7 +1158,7 @@ async def test_success_returns_storage_accounts(self, mock_credential): client_request_id=None, response_hook=None, ) - assert result["value"][0]["name"] == "account1" + assert result == [{"name": "account1"}] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -1166,12 +1170,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=MockResponse(status=500, text="Server error") ): with pytest.raises(ConnectorException) as exc_info: - await client.get_storage_accounts_async() + await resolve_generated_result(client.list_storage_accounts()) assert exc_info.value.status_code == 500 @@ -1195,7 +1199,7 @@ async def test_entities_continuation_yields_later_entities( ) as client: with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, side_effect=[ MockResponse(status=200, text=json.dumps({ @@ -1209,7 +1213,7 @@ async def test_entities_continuation_yields_later_entities( ], ) as transport: entities = [ - entity async for entity in client.get_entities_async( + entity async for entity in client.list_entities( storage_account_name="mystorageaccount", table_name="mytable", ) diff --git a/tests/test_azurevm.py b/tests/test_azurevm.py index f68e3ac..4c11784 100644 --- a/tests/test_azurevm.py +++ b/tests/test_azurevm.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.azurevm import AzurevmClient from azure.connectors.azurevm import ( - AzurevmClient, VirtualMachine, VirtualMachineProperties, VirtualMachineInScaleSet, @@ -70,7 +70,7 @@ def test_init_with_custom_settings(self, mock_credential): client = AzurevmClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -151,11 +151,11 @@ async def test_success_returns_vm_data(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.virtual_machine_get_async( + result = await client.virtual_machine_get( subscription_id="sub1", resource_group_name="rg1", virtual_machine_name="vm1" @@ -182,11 +182,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.virtual_machine_get_async( + result = await client.virtual_machine_get( subscription_id="sub1", resource_group_name="rg1", virtual_machine_name="vm1" @@ -209,12 +209,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.virtual_machine_get_async( + await client.virtual_machine_get( subscription_id="sub1", resource_group_name="rg1", virtual_machine_name="vm1" @@ -238,11 +238,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.virtual_machine_start_async( + await client.virtual_machine_start( subscription_id="sub1", resource_group_name="rg1", virtual_machine_name="vm1" @@ -269,11 +269,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.virtual_machine_deallocate_async( + await client.virtual_machine_deallocate( subscription_id="sub1", resource_group_name="rg1", virtual_machine_name="vm1" @@ -300,11 +300,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.virtual_machine_poweroff_async( + await client.virtual_machine_poweroff( subscription_id="sub1", resource_group_name="rg1", virtual_machine_name="vm1" @@ -331,11 +331,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.virtual_machine_reapply_async( + await client.virtual_machine_reapply( subscription_id="sub1", resource_group_name="rg1", virtual_machine_name="vm1" @@ -362,11 +362,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.virtual_machine_redeploy_async( + await client.virtual_machine_redeploy( subscription_id="sub1", resource_group_name="rg1", virtual_machine_name="vm1" @@ -393,11 +393,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.virtual_machine_restart_async( + await client.virtual_machine_restart( subscription_id="sub1", resource_group_name="rg1", virtual_machine_name="vm1" @@ -430,11 +430,11 @@ async def test_success_returns_vm_data(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.virtual_machine_in_scale_set_get_async( + result = await client.virtual_machine_in_scale_set_get( subscription_id="sub1", resource_group_name="rg1", virtual_machine_scale_set_name="vmss1", @@ -463,12 +463,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.virtual_machine_in_scale_set_get_async( + await client.virtual_machine_in_scale_set_get( subscription_id="sub1", resource_group_name="rg1", virtual_machine_scale_set_name="vmss1", @@ -493,11 +493,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.virtual_machine_in_scale_set_deallocate_async( + await client.virtual_machine_in_scale_set_deallocate( subscription_id="sub1", resource_group_name="rg1", virtual_machine_scale_set_name="vmss1", @@ -525,11 +525,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.virtual_machine_in_scale_set_power_off_async( + await client.virtual_machine_in_scale_set_power_off( subscription_id="sub1", resource_group_name="rg1", virtual_machine_scale_set_name="vmss1", @@ -557,11 +557,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.virtual_machine_in_scale_set_redeploy_async( + await client.virtual_machine_in_scale_set_redeploy( subscription_id="sub1", resource_group_name="rg1", virtual_machine_scale_set_name="vmss1", @@ -589,11 +589,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.virtual_machine_in_scale_set_reimage_async( + await client.virtual_machine_in_scale_set_reimage( subscription_id="sub1", resource_group_name="rg1", virtual_machine_scale_set_name="vmss1", @@ -621,11 +621,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.virtual_machine_in_scale_set_restart_async( + await client.virtual_machine_in_scale_set_restart( subscription_id="sub1", resource_group_name="rg1", virtual_machine_scale_set_name="vmss1", @@ -653,11 +653,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.virtual_machine_in_scale_set_start_async( + await client.virtual_machine_in_scale_set_start( subscription_id="sub1", resource_group_name="rg1", virtual_machine_scale_set_name="vmss1", diff --git a/tests/test_box.py b/tests/test_box.py index 2fc8e4a..5374da1 100644 --- a/tests/test_box.py +++ b/tests/test_box.py @@ -6,50 +6,53 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.box import BoxClient from azure.connectors.box import ( BlobMetadata, BlobMetadataPage, - BoxClient, ) from azure.connectors.sdk import ( ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result async def _invoke_operation(client: BoxClient, operation: str): """Invoke a Box operation by name for shared parameterized tests.""" if operation == "get_file_metadata": - return await client.get_file_metadata_async(id="file123") + return await client.get_file_metadata(id="file123") if operation == "update_file": - return await client.update_file_async(input=b"updated content", id="file123") + return await client.update_file(input=b"updated content", id="file123") if operation == "delete_file": - return await client.delete_file_async(id="file123") + return await client.delete_file(id="file123") if operation == "get_file_metadata_by_path": - return await client.get_file_metadata_by_path_async(path="/Documents/file.txt") + return await client.get_file_metadata_by_path(path="/Documents/file.txt") if operation == "get_file_content_by_path": - return await client.get_file_content_by_path_async(path="/Documents/file.txt") + return await client.get_file_content_by_path(path="/Documents/file.txt") if operation == "get_file_content": - return await client.get_file_content_async(id="file123") + return await client.get_file_content(id="file123") if operation == "create_file": - return await client.create_file_async( + return await client.create_file( input=b"file content", folder_path="/Documents", name="created.txt", ) if operation == "copy_file": - return await client.copy_file_async( + return await client.copy_file( source="/Documents/source.txt", destination="/Documents/copy.txt", ) if operation == "list_folder": - return await client.list_folder_async(id="folder123") + return await resolve_generated_result(client.list_folder(id="folder123")) if operation == "list_root_folder": - return await client.list_root_folder_async() + return await resolve_generated_result(client.list_root_folder()) if operation == "extract_folder": - return await client.extract_folder_async( - source="/Documents/archive.zip", - destination="/Documents/extracted", + return await resolve_generated_result( + client.extract_folder( + source="/Documents/archive.zip", + destination="/Documents/extracted", + ) ) raise ValueError(f"Unsupported operation '{operation}'.") @@ -87,7 +90,7 @@ def test_init_with_custom_settings(self, mock_credential): client = BoxClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -154,11 +157,11 @@ async def test_get_file_metadata_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_file_metadata_async(id="file123") + result = await client.get_file_metadata(id="file123") assert result["name"] == "doc.txt" call_args = mock_send.call_args @@ -176,11 +179,11 @@ async def test_update_file_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.update_file_async(input=b"updated content", id="file123") + result = await client.update_file(input=b"updated content", id="file123") assert result["name"] == "updated.txt" call_args = mock_send.call_args @@ -198,11 +201,11 @@ async def test_delete_file_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.delete_file_async(id="file123") + result = await client.delete_file(id="file123") assert result is None call_args = mock_send.call_args @@ -219,11 +222,11 @@ async def test_get_file_content_by_path_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_file_content_by_path_async(path="/Documents/file.txt") + result = await client.get_file_content_by_path(path="/Documents/file.txt") assert result == b"box file content" assert "path=%2FDocuments%2Ffile.txt" in mock_send.call_args[0][1] @@ -239,11 +242,11 @@ async def test_create_file_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_file_async( + result = await client.create_file( input=b"file content", folder_path="/Documents", name="created.txt", @@ -264,19 +267,18 @@ async def test_list_root_folder_success(self, mock_credential): ) mock_response = MockResponse( status=200, - text='{"value":[{"id":"1","name":"Docs"}]}' + text='[{"id":"1","name":"Docs"}]' ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.list_root_folder_async() + result = await resolve_generated_result(client.list_root_folder()) - assert len(result["value"]) == 1 - assert result["value"][0]["name"] == "Docs" + assert result == [{"id": "1", "name": "Docs"}] class TestBoxClientErrorHandling: @@ -313,7 +315,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): diff --git a/tests/test_campfire.py b/tests/test_campfire.py index 5a123e9..73f3e05 100644 --- a/tests/test_campfire.py +++ b/tests/test_campfire.py @@ -7,9 +7,9 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.campfire import CampfireClient from azure.connectors.campfire import ( Account, - CampfireClient, Room, TRIGGER_OPERATIONS, Upload, @@ -19,6 +19,7 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestCampfireClientInitialization: @@ -54,7 +55,7 @@ def test_init_with_custom_settings(self, mock_credential): client = CampfireClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -121,11 +122,11 @@ async def test_create_message_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_message_async( + result = await client.create_message( room_id="R1", account="acct1", message="hello" ) @@ -147,11 +148,11 @@ async def test_get_user_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_user_async(user_id="5", account="acct1") + result = await client.get_user(user_id="5", account="acct1") method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" @@ -170,17 +171,19 @@ async def test_list_accounts_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_accounts_async(parent_operation="op1") + result = await resolve_generated_result( + client.list_accounts(parent_operation="op1") + ) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert "/authorization.json" in url assert "parentOperation=op1" in url - assert result == {"accounts": []} + assert result == [] @pytest.mark.asyncio async def test_list_rooms_success(self, mock_credential): @@ -193,21 +196,23 @@ async def test_list_rooms_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_rooms_async(account="acct1") + result = await resolve_generated_result( + client.list_rooms(account="acct1") + ) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert "/rooms.json" in url assert "account=acct1" in url - assert result == {"rooms": []} + assert result == [] @pytest.mark.asyncio - async def test_empty_response_body_returns_none(self, mock_credential): - """Test a 2xx response with no body returns None.""" + async def test_empty_response_body_returns_empty_page(self, mock_credential): + """Test a 2xx response with no body returns an empty page.""" client = CampfireClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -216,13 +221,15 @@ async def test_empty_response_body_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.list_rooms_async(account="acct1") + result = await resolve_generated_result( + client.list_rooms(account="acct1") + ) - assert result is None + assert result == [] class TestCampfireClientErrorHandling: @@ -248,21 +255,23 @@ async def test_error_response_raises_exception(self, mock_credential, operation) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: if operation == "create_message": - await client.create_message_async( + await client.create_message( room_id="R1", account="acct1", message="hello" ) elif operation == "get_user": - await client.get_user_async(user_id="5", account="acct1") + await client.get_user(user_id="5", account="acct1") elif operation == "list_accounts": - await client.list_accounts_async() + await resolve_generated_result(client.list_accounts()) else: - await client.list_rooms_async(account="acct1") + await resolve_generated_result( + client.list_rooms(account="acct1") + ) assert exc_info.value.status_code == 500 diff --git a/tests/test_clicksendsms.py b/tests/test_clicksendsms.py index 1318c42..3ff9787 100644 --- a/tests/test_clicksendsms.py +++ b/tests/test_clicksendsms.py @@ -7,8 +7,8 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.clicksendsms import ClicksendsmsClient from azure.connectors.clicksendsms import ( - ClicksendsmsClient, CreateListContactInput, CreateListInput, DeleteListResponse, @@ -26,6 +26,7 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import model_instance class TestClicksendsmsClientInitialization: @@ -61,7 +62,7 @@ def test_init_with_custom_settings(self, mock_credential): client = ClicksendsmsClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -131,10 +132,10 @@ async def test_sms_send_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"data": {}}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.sms_send_async(input=payload) + result = await client.sms_send(input=payload) assert mock_send.call_args[0][0] == "POST" assert "/sms/send" in mock_send.call_args[0][1] @@ -149,10 +150,10 @@ async def test_create_list_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"data": {}}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_list_async(input=payload) + result = await client.create_list(input=payload) assert mock_send.call_args[0][0] == "POST" assert "/lists" in mock_send.call_args[0][1] @@ -166,10 +167,10 @@ async def test_get_contact_lists_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"data": {}}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_contact_lists_async(page="2", limit="10") + result = await client.get_contact_lists(page="2", limit="10") url = mock_send.call_args[0][1] assert mock_send.call_args[0][0] == "GET" @@ -186,10 +187,10 @@ async def test_send_voice_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"data": {}}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.send_voice_async(input=payload) + result = await client.send_voice(input=payload) assert mock_send.call_args[0][0] == "POST" assert "/voice/send" in mock_send.call_args[0][1] @@ -203,10 +204,10 @@ async def test_delete_list_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"data": {}}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.delete_list_async(list_id="123") + result = await client.delete_list(list_id="123") assert mock_send.call_args[0][0] == "DELETE" assert "/lists/123" in mock_send.call_args[0][1] @@ -216,14 +217,18 @@ async def test_delete_list_success(self, mock_credential): async def test_create_list_contact_success(self, mock_credential): """Test create_list_contact issues a POST to the list contacts route.""" client = self._make_client(mock_credential) - payload = CreateListContactInput(first_name="Ada", phone_number="+61411111111") + payload = model_instance( + CreateListContactInput, + first_name="Ada", + phone_number="+61411111111", + ) mock_response = MockResponse(status=200, text='{"data": {}}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_list_contact_async(input=payload, list_id="123") + result = await client.create_list_contact(input=payload, list_id="123") assert mock_send.call_args[0][0] == "POST" assert "/lists/123/contacts" in mock_send.call_args[0][1] @@ -237,10 +242,10 @@ async def test_view_list_contacts_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"data": {}}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.view_list_contacts_async(list_id="123") + result = await client.view_list_contacts(list_id="123") assert mock_send.call_args[0][0] == "GET" assert "/lists/123/contacts" in mock_send.call_args[0][1] @@ -253,10 +258,10 @@ async def test_delete_list_contact_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"data": {}}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.delete_list_contact_async(list_id="123", contact_id="456") + result = await client.delete_list_contact(list_id="123", contact_id="456") assert mock_send.call_args[0][0] == "DELETE" assert "/lists/123/contacts/456" in mock_send.call_args[0][1] @@ -270,10 +275,10 @@ async def test_send_mms_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"data": {}}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.send_mms_async(input=payload) + result = await client.send_mms(input=payload) assert mock_send.call_args[0][0] == "POST" assert "/mms/send" in mock_send.call_args[0][1] @@ -288,10 +293,10 @@ async def test_send_fax_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"data": {}}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.send_fax_async(input=payload) + result = await client.send_fax(input=payload) assert mock_send.call_args[0][0] == "POST" assert "/fax/send" in mock_send.call_args[0][1] @@ -306,10 +311,10 @@ async def test_upload_media_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"data": {}}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.upload_media_async(input=payload, convert="mms") + result = await client.upload_media(input=payload, convert="mms") url = mock_send.call_args[0][1] assert mock_send.call_args[0][0] == "POST" @@ -325,10 +330,10 @@ async def test_search_contact_list_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"data": {}}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.search_contact_list_async(q="friends") + result = await client.search_contact_list(q="friends") url = mock_send.call_args[0][1] assert mock_send.call_args[0][0] == "GET" @@ -340,14 +345,18 @@ async def test_search_contact_list_success(self, mock_credential): async def test_send_letter_success(self, mock_credential): """Test send_letter issues a POST to the letters route with the input body.""" client = self._make_client(mock_credential) - payload = SendLetterInput(file_url="url", recipients=[{"address_name": "Ada"}]) + payload = model_instance( + SendLetterInput, + file_url="url", + recipients=[{"address_name": "Ada"}], + ) mock_response = MockResponse(status=200, text='{"data": {}}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.send_letter_async(input=payload) + result = await client.send_letter(input=payload) assert mock_send.call_args[0][0] == "POST" assert "/post/letters/send" in mock_send.call_args[0][1] @@ -362,10 +371,10 @@ async def test_send_postcard_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"data": {}}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.send_postcard_async(input=payload) + result = await client.send_postcard(input=payload) assert mock_send.call_args[0][0] == "POST" assert "/post/postcards/send" in mock_send.call_args[0][1] @@ -379,10 +388,10 @@ async def test_empty_response_body_returns_none(self, mock_credential): mock_response = MockResponse(status=200, text="") with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.view_list_contacts_async(list_id="123") + result = await client.view_list_contacts(list_id="123") assert result is None @@ -419,40 +428,44 @@ async def test_error_response_raises_exception(self, mock_credential, operation) mock_response = MockResponse(status=500, text='{"error":"server failure"}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: if operation == "sms_send": - await client.sms_send_async(input=SmsSendInput()) + await client.sms_send(input=model_instance(SmsSendInput)) elif operation == "create_list": - await client.create_list_async(input=CreateListInput()) + await client.create_list(input=model_instance(CreateListInput)) elif operation == "get_contact_lists": - await client.get_contact_lists_async() + await client.get_contact_lists() elif operation == "send_voice": - await client.send_voice_async(input=SendVoiceInput()) + await client.send_voice(input=model_instance(SendVoiceInput)) elif operation == "delete_list": - await client.delete_list_async(list_id="123") + await client.delete_list(list_id="123") elif operation == "create_list_contact": - await client.create_list_contact_async( - input=CreateListContactInput(), list_id="123" + await client.create_list_contact( + input=model_instance(CreateListContactInput), + list_id="123", ) elif operation == "view_list_contacts": - await client.view_list_contacts_async(list_id="123") + await client.view_list_contacts(list_id="123") elif operation == "delete_list_contact": - await client.delete_list_contact_async(list_id="123", contact_id="456") + await client.delete_list_contact(list_id="123", contact_id="456") elif operation == "send_mms": - await client.send_mms_async(input=SendMmsInput()) + await client.send_mms(input=model_instance(SendMmsInput)) elif operation == "send_fax": - await client.send_fax_async(input=SendFaxInput()) + await client.send_fax(input=model_instance(SendFaxInput)) elif operation == "upload_media": - await client.upload_media_async(input=UploadMediaInput(), convert="mms") + await client.upload_media( + input=model_instance(UploadMediaInput), + convert="mms", + ) elif operation == "search_contact_list": - await client.search_contact_list_async(q="friends") + await client.search_contact_list(q="friends") elif operation == "send_letter": - await client.send_letter_async(input=SendLetterInput()) + await client.send_letter(input=model_instance(SendLetterInput)) else: - await client.send_postcard_async(input=SendPostcardInput()) + await client.send_postcard(input=model_instance(SendPostcardInput)) assert exc_info.value.status_code == 500 @@ -488,6 +501,11 @@ def test_dataclass_defaults(self): assert SmsSendResponse().http_code is None assert SmsSendResponse().response_msg is None assert DeleteListResponse().response_msg is None - assert CreateListContactInput().first_name is None - assert CreateListContactInput().custom1 is None - assert CreateListContactInput().address_line1 is None + contact = CreateListContactInput( + first_name="Ada", + last_name="Lovelace", + phone_number="+61411111111", + ) + assert contact.first_name == "Ada" + assert contact.custom1 is None + assert contact.address_line1 is None diff --git a/tests/test_cloudconvert.py b/tests/test_cloudconvert.py index 7db4902..1e14397 100644 --- a/tests/test_cloudconvert.py +++ b/tests/test_cloudconvert.py @@ -3,7 +3,7 @@ """Contract tests for CloudconvertClient.""" import azure.connectors.cloudconvert as cloudconvert_module -from azure.connectors.cloudconvert import CloudconvertClient +from azure.connectors.aio.cloudconvert import CloudconvertClient from tests.generated_connector_test_utils import GeneratedConnectorContractTests diff --git a/tests/test_cloudmersiveconvert.py b/tests/test_cloudmersiveconvert.py index 8873916..34d5ec3 100644 --- a/tests/test_cloudmersiveconvert.py +++ b/tests/test_cloudmersiveconvert.py @@ -7,8 +7,8 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.cloudmersiveconvert import CloudmersiveconvertClient from azure.connectors.cloudmersiveconvert import ( - CloudmersiveconvertClient, GetDocxBodyRequest, GetDocxGetCommentsHierarchicalRequest, ) @@ -51,7 +51,7 @@ def test_init_with_custom_settings(self, mock_credential): client = CloudmersiveconvertClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -119,11 +119,11 @@ async def test_success_forwards_request_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.edit_document_docx_body_async(input=request) + result = await client.edit_document_docx_body(input=request) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -144,12 +144,12 @@ async def test_error_response_raises_connector_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.edit_document_docx_body_async(input=GetDocxBodyRequest()) + await client.edit_document_docx_body(input=GetDocxBodyRequest()) assert exc_info.value.status_code == 400 @@ -169,11 +169,11 @@ async def test_success_forwards_request_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.edit_document_docx_get_comments_hierarchical_async( + result = await client.edit_document_docx_get_comments_hierarchical( input=request ) @@ -195,12 +195,12 @@ async def test_server_error_raises_connector_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.edit_document_docx_get_comments_hierarchical_async( + await client.edit_document_docx_get_comments_hierarchical( input=GetDocxGetCommentsHierarchicalRequest() ) @@ -269,12 +269,12 @@ async def test_server_error_raises_connector_exception(self, mock_credential): def test_generated_operation_inventory_matches_contract(): """Test all 53 supported operations are represented without multipart APIs.""" assert len(ALL_OPERATIONS) == 53 - assert not hasattr(CloudmersiveconvertClient, "create_document_async") + assert not hasattr(CloudmersiveconvertClient, "create_document") async def _invoke_operation(client: CloudmersiveconvertClient, operation: str): """Invoke a Cloudmersive Convert operation by name for shared method tests.""" - method = getattr(client, f"{operation}_async") + method = getattr(client, f"{operation}") return await method(**OPERATION_ARGS[operation]) @@ -290,7 +290,7 @@ async def test_all_operations_success(self, mock_credential, operation): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: @@ -316,7 +316,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): diff --git a/tests/test_code_quality.py b/tests/test_code_quality.py index a412500..d0162d0 100644 --- a/tests/test_code_quality.py +++ b/tests/test_code_quality.py @@ -64,11 +64,11 @@ def test_flake8(self): raise AssertionError( f'flake8 validation failed:\n{output}') from None - def test_no_unchecked_send_async_calls(self): - """Verify all send_async calls capture their response. + def test_no_unchecked_send_calls(self): + """Verify all sync and aio send calls capture their response. - Generated connector code must not discard send_async responses. - This check catches the most egregious error: calling send_async + Generated connector code must not discard send responses. + This check catches the most egregious error: calling send without capturing the response at all (fire-and-forget). It does NOT validate that the captured response is checked with the correct status guard pattern — that requires manual review or regeneration. @@ -80,34 +80,129 @@ def test_no_unchecked_send_async_calls(self): violations: list[LintViolation] = [] - for filepath in connector_dir.glob('*.py'): + connector_paths = [ + *connector_dir.glob('*.py'), + *(connector_dir / 'aio').glob('*.py'), + ] + for filepath in connector_paths: if filepath.name in skip_files: continue - violations.extend(self._find_unchecked_send_async(filepath)) + violations.extend(self._find_unchecked_send(filepath)) if violations: messages = [ f" {v.file}:{v.line}: {v.message}" - for v in sorted(violations, key=lambda x: (x.file, x.line)) + for v in sorted( + violations, + key=lambda violation: (violation.file, violation.line), + ) ] violation_text = "\n".join(messages) raise AssertionError( - f"Found {len(violations)} unchecked send_async call(s).\n" - f"All send_async calls must capture the response.\n" + f"Found {len(violations)} unchecked send call(s).\n" + f"All sync and aio send calls must capture the response.\n" f"Fix the generator (see GENERATION.md) and regenerate, " f"or regenerate with the latest generator.\n\n" f"{violation_text}" ) - def _find_unchecked_send_async( + def test_only_explicit_resource_deletes_accept_not_found(self): + """Verify only explicitly idempotent resource deletes accept HTTP 404.""" + connector_dir = ROOT_PATH / 'src' / 'azure' / 'connectors' + expected_operations = { + ('aio/arm.py', 'deployments_delete'), + ('arm.py', 'deployments_delete'), + } + connector_paths = [ + *connector_dir.glob('*.py'), + *(connector_dir / 'aio').glob('*.py'), + ] + actual_operations: set[tuple[str, str]] = set() + + for filepath in connector_paths: + if filepath.name.startswith('_'): + continue + + tree = ast.parse(filepath.read_text(encoding='utf-8')) + for function in ( + node for node in ast.walk(tree) + if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) + ): + if not self._sends_request(function): + continue + + accepts_not_found = self._accepts_not_found(function) + if accepts_not_found: + relative_path = filepath.relative_to(connector_dir).as_posix() + actual_operations.add((relative_path, function.name)) + assert self._uses_http_method(function, 'DELETE'), ( + f'{relative_path}:{function.lineno}: ' + f'{function.name} accepts 404 without using HTTP DELETE' + ) + + assert actual_operations == expected_operations, ( + 'Generated HTTP 404 guards do not match the explicit idempotent ' + f'resource-delete policy: {sorted(actual_operations)}' + ) + + @staticmethod + def _sends_request(function: ast.AST) -> bool: + """Return whether a function sends an HTTP request.""" + return any( + isinstance(node, ast.Call) + and isinstance(node.func, ast.Attribute) + and node.func.attr == 'send' + for node in ast.walk(function) + ) + + @staticmethod + def _uses_http_method(function: ast.AST, method: str) -> bool: + """Return whether a function sends the specified HTTP method.""" + return any( + isinstance(node, ast.Call) + and isinstance(node.func, ast.Attribute) + and node.func.attr == 'send' + and node.args + and isinstance(node.args[0], ast.Constant) + and node.args[0].value == method + for node in ast.walk(function) + ) + + @staticmethod + def _accepts_not_found(function: ast.AST) -> bool: + """Return whether a function returns None for HTTP 404.""" + for node in ast.walk(function): + if not isinstance(node, ast.If) or not isinstance(node.test, ast.Compare): + continue + + comparison = node.test + if ( + len(comparison.ops) == 1 + and isinstance(comparison.ops[0], ast.Eq) + and len(comparison.comparators) == 1 + and isinstance(comparison.comparators[0], ast.Constant) + and comparison.comparators[0].value == 404 + and any( + isinstance(statement, ast.Return) + and isinstance(statement.value, ast.Constant) + and statement.value.value is None + for statement in node.body + ) + ): + return True + + return False + + def _find_unchecked_send( self, filepath: pathlib.Path ) -> list[LintViolation]: - """Find send_async calls whose result is not captured. + """Find sync or aio send calls whose result is not captured. Detects the pattern: - await self.http_client.send_async(...) # Result discarded! + self.http_client.send(...) # Result discarded! + await self.http_client.send(...) # Result discarded! This is a minimal check that catches discarded responses. It does NOT validate that captured responses are checked with the correct @@ -124,20 +219,27 @@ def _find_unchecked_send_async( for node in ast.walk(tree): # NOTE(victoriahall): ast.Expr means the value is discarded, not assigned. - if isinstance(node, ast.Expr) and isinstance(node.value, ast.Await): - await_expr = node.value.value - - if isinstance(await_expr, ast.Call): - func = await_expr.func - - if isinstance(func, ast.Attribute) and func.attr == 'send_async': - if isinstance(func.value, ast.Attribute): - attr_name = func.value.attr - if attr_name in ('http_client', '_http_client'): - violations.append(LintViolation( - file=filepath.name, - line=node.lineno, - message='Unchecked send_async call' - )) + if not isinstance(node, ast.Expr): + continue + + expression = node.value + if isinstance(expression, ast.Await): + expression = expression.value + + if not isinstance(expression, ast.Call): + continue + + function = expression.func + if not isinstance(function, ast.Attribute) or function.attr != 'send': + continue + + if isinstance(function.value, ast.Attribute): + attribute_name = function.value.attr + if attribute_name in ('http_client', '_http_client'): + violations.append(LintViolation( + file=filepath.relative_to(ROOT_PATH).as_posix(), + line=node.lineno, + message='Unchecked send call' + )) return violations diff --git a/tests/test_commondataservice.py b/tests/test_commondataservice.py index e717dc6..1e73682 100644 --- a/tests/test_commondataservice.py +++ b/tests/test_commondataservice.py @@ -5,10 +5,10 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.commondataservice import CommondataserviceClient from azure.connectors.commondataservice import ( TRIGGER_OPERATIONS, AssociateRecordsPatchItemInput, - CommondataserviceClient, ItemsList, PatchItemInput, PostItemInput, @@ -18,6 +18,7 @@ ) from azure.connectors.sdk.serialization import to_wire from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestCommondataserviceClientInitialization: @@ -53,7 +54,7 @@ def test_init_with_custom_settings(self, mock_credential): client = CommondataserviceClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -138,11 +139,11 @@ async def test_get_item_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"itemInternalId": "1"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - result = await client.get_item_async(dataset="default", table="accounts", id="1") + result = await client.get_item(dataset="default", table="accounts", id="1") call_args = mock_send.call_args assert call_args[0][0] == "GET" @@ -153,17 +154,17 @@ async def test_get_item_success(self, mock_credential): async def test_get_item_error_response(self, mock_credential): """Test that error response raises ConnectorException.""" client = _make_client(mock_credential) - mock_response = MockResponse(status=404, text="Not found") + mock_response = MockResponse(status=500, text="Server error") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.get_item_async(dataset="default", table="accounts", id="99") + await client.get_item(dataset="default", table="accounts", id="99") - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestGetItems: @@ -176,12 +177,12 @@ async def test_get_items_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"value": []}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response result = [ - item async for item in client.get_items_async( + item async for item in client.list_items( dataset="default", table="accounts", ) @@ -212,12 +213,12 @@ async def test_get_items_follows_odata_next_link(self, mock_credential): ] with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.side_effect = responses result = [ - item async for item in client.get_items_async( + item async for item in client.list_items( dataset="default", table="accounts", ) @@ -227,6 +228,38 @@ async def test_get_items_follows_odata_next_link(self, mock_credential): assert mock_send.await_count == 2 assert mock_send.await_args_list[1].args[1] == next_link + @pytest.mark.asyncio + async def test_get_items_rebases_caller_continuation_to_runtime_origin( + self, + mock_credential, + ): + """Test caller continuation URLs cannot redirect authenticated requests.""" + client = _make_client(mock_credential) + continuation_token = "https://attacker.invalid/capture?secret=opaque" + mock_response = MockResponse( + status=200, + text='{"value": [{"sequence": 2}]}', + ) + + with patch.object( + client._http_client, "send", new_callable=AsyncMock + ) as mock_send: + mock_send.return_value = mock_response + + page_iterator = client.list_items( + dataset="default", + table="accounts", + ).by_page(continuation_token=continuation_token) + page = await anext(page_iterator) + result = [item async for item in page] + + assert result == [{"sequence": 2}] + mock_send.assert_awaited_once() + assert mock_send.await_args.args[1] == ( + "https://example.azure.com/connections/test" + "/capture?secret=opaque" + ) + @pytest.mark.asyncio async def test_get_items_resolves_query_only_next_link_against_current_url( self, @@ -247,12 +280,12 @@ async def test_get_items_resolves_query_only_next_link_against_current_url( ] with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.side_effect = responses result = [ - item async for item in client.get_items_async( + item async for item in client.list_items( dataset="default", table="accounts", filter="statecode eq 0", @@ -285,12 +318,12 @@ async def test_get_items_resolves_leading_slash_next_link_against_runtime( ] with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.side_effect = responses result = [ - item async for item in client.get_items_async( + item async for item in client.list_items( dataset="default", table="accounts", ) @@ -322,12 +355,12 @@ async def test_get_items_routes_bare_token_through_next_link_endpoint( ] with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.side_effect = responses result = [ - item async for item in client.get_items_async( + item async for item in client.list_items( dataset="default", table="accounts", ) @@ -443,11 +476,11 @@ async def test_get_items_with_query_params(self, mock_credential): mock_response = MockResponse(status=200, text='{"value": []}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - result = client.get_items_async( + result = client.list_items( dataset="default", table="contacts", apply="groupby((name))", @@ -472,13 +505,13 @@ async def test_get_items_error_response(self, mock_credential): mock_response = MockResponse(status=500, text="Server error") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: await anext( - client.get_items_async(dataset="default", table="accounts") + client.list_items(dataset="default", table="accounts") ) assert exc_info.value.status_code == 500 @@ -495,11 +528,11 @@ async def test_patch_item_success(self, mock_credential): body = PatchItemInput() with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - result = await client.patch_item_async( + result = await client.patch_item( input=body, dataset="default", table="accounts", @@ -519,12 +552,12 @@ async def test_patch_item_error_response(self, mock_credential): mock_response = MockResponse(status=400, text="Bad request") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.patch_item_async( + await client.patch_item( input=PatchItemInput(), dataset="default", table="accounts", @@ -545,11 +578,11 @@ async def test_post_item_success(self, mock_credential): body = PostItemInput() with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - result = await client.post_item_async( + result = await client.post_item( input=body, dataset="default", table="accounts", @@ -568,12 +601,12 @@ async def test_post_item_error_response(self, mock_credential): mock_response = MockResponse(status=400, text="Bad request") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.post_item_async( + await client.post_item( input=PostItemInput(), dataset="default", table="accounts", @@ -592,11 +625,11 @@ async def test_get_data_sets_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"value": []}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.get_data_sets_async() + await resolve_generated_result(client.list_data_sets()) call_args = mock_send.call_args assert call_args[0][0] == "GET" @@ -609,12 +642,12 @@ async def test_get_data_sets_error_response(self, mock_credential): mock_response = MockResponse(status=500, text="Server error") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.get_data_sets_async() + await resolve_generated_result(client.list_data_sets()) assert exc_info.value.status_code == 500 @@ -629,11 +662,11 @@ async def test_get_metadata_for_patch_item_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"name": "accounts"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.get_metadata_for_patch_item_async(dataset="default", table="accounts") + await client.get_metadata_for_patch_item(dataset="default", table="accounts") call_args = mock_send.call_args assert call_args[0][0] == "GET" @@ -646,17 +679,17 @@ async def test_get_metadata_for_patch_item_success(self, mock_credential): async def test_get_metadata_for_patch_item_error_response(self, mock_credential): """Test that error response raises ConnectorException.""" client = _make_client(mock_credential) - mock_response = MockResponse(status=404, text="Not found") + mock_response = MockResponse(status=500, text="Server error") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.get_metadata_for_patch_item_async(dataset="default", table="accounts") + await client.get_metadata_for_patch_item(dataset="default", table="accounts") - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestGetMetadataForPostItem: @@ -669,11 +702,11 @@ async def test_get_metadata_for_post_item_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"name": "accounts"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.get_metadata_for_post_item_async(dataset="default", table="accounts") + await client.get_metadata_for_post_item(dataset="default", table="accounts") call_args = mock_send.call_args assert call_args[0][0] == "GET" @@ -686,17 +719,17 @@ async def test_get_metadata_for_post_item_success(self, mock_credential): async def test_get_metadata_for_post_item_error_response(self, mock_credential): """Test that error response raises ConnectorException.""" client = _make_client(mock_credential) - mock_response = MockResponse(status=404, text="Not found") + mock_response = MockResponse(status=500, text="Server error") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.get_metadata_for_post_item_async(dataset="default", table="accounts") + await client.get_metadata_for_post_item(dataset="default", table="accounts") - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestGetTable: @@ -709,11 +742,11 @@ async def test_get_table_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"name": "accounts"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - result = await client.get_table_async(dataset="default", table="accounts") + result = await client.get_table(dataset="default", table="accounts") call_args = mock_send.call_args assert call_args[0][0] == "GET" @@ -727,12 +760,12 @@ async def test_get_table_error_response(self, mock_credential): mock_response = MockResponse(status=404, text="Not found") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.get_table_async(dataset="default", table="accounts") + await client.get_table(dataset="default", table="accounts") assert exc_info.value.status_code == 404 @@ -750,17 +783,19 @@ async def test_get_tables_success(self, mock_credential): ) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - result = await client.get_tables_async(dataset="default") + result = await resolve_generated_result( + client.list_tables(dataset="default") + ) call_args = mock_send.call_args assert call_args[0][0] == "GET" assert call_args[0][1].endswith("/v2/datasets/default/tables") assert call_args.kwargs["body"] is None - assert result == {"value": [{"Name": "accounts"}]} + assert result == [{"Name": "accounts"}] @pytest.mark.asyncio async def test_get_tables_error_response(self, mock_credential): @@ -769,12 +804,14 @@ async def test_get_tables_error_response(self, mock_credential): mock_response = MockResponse(status=500, text="Server error") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.get_tables_async(dataset="default") + await resolve_generated_result( + client.list_tables(dataset="default") + ) assert exc_info.value.status_code == 500 @@ -789,11 +826,11 @@ async def test_get_data_sets_metadata_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"tabular": {}}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - result = await client.get_data_sets_metadata_async() + result = await client.get_data_sets_metadata() call_args = mock_send.call_args assert call_args[0][0] == "GET" @@ -807,12 +844,12 @@ async def test_get_data_sets_metadata_error_response(self, mock_credential): mock_response = MockResponse(status=500, text="Server error") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.get_data_sets_metadata_async() + await client.get_data_sets_metadata() assert exc_info.value.status_code == 500 @@ -830,11 +867,11 @@ async def test_get_next_page_success(self, mock_credential): ) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - result = await client.get_next_page_async(next_link="token123") + result = await client.get_next_page(next_link="token123") call_args = mock_send.call_args assert call_args[0][0] == "GET" @@ -854,11 +891,11 @@ async def test_get_next_page_empty_body_returns_none(self, mock_credential): mock_response = MockResponse(status=200, text="") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - result = await client.get_next_page_async(next_link="token123") + result = await client.get_next_page(next_link="token123") assert result is None @@ -869,12 +906,12 @@ async def test_get_next_page_error_response(self, mock_credential): mock_response = MockResponse(status=404, text="Not found") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.get_next_page_async(next_link="token123") + await client.get_next_page(next_link="token123") assert exc_info.value.status_code == 404 @@ -889,11 +926,11 @@ async def test_associate_records_success(self, mock_credential): mock_response = MockResponse(status=200, text='{}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.associate_records_patch_item_async( + await client.associate_records_patch_item( AssociateRecordsPatchItemInput(), dataset="default", table="accounts", @@ -913,12 +950,12 @@ async def test_associate_records_error_response(self, mock_credential): mock_response = MockResponse(status=400, text="Bad request") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.associate_records_patch_item_async( + await client.associate_records_patch_item( AssociateRecordsPatchItemInput(), dataset="default", table="accounts", @@ -939,11 +976,11 @@ async def test_create_attachment_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"annotationid": "abc"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - result = await client.create_attachment_async( + result = await client.create_attachment( b"file-bytes", dataset="default", table="accounts", @@ -968,12 +1005,12 @@ async def test_create_attachment_error_response(self, mock_credential): mock_response = MockResponse(status=403, text="Forbidden") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.create_attachment_async( + await client.create_attachment( b"file-bytes", dataset="default", table="accounts", @@ -994,12 +1031,14 @@ async def test_get_item_attachments_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"value": []}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.get_item_attachments_async( - dataset="default", table="accounts", id="1" + await resolve_generated_result( + client.list_item_attachments( + dataset="default", table="accounts", id="1" + ) ) call_args = mock_send.call_args @@ -1013,13 +1052,15 @@ async def test_get_item_attachments_error_response(self, mock_credential): mock_response = MockResponse(status=404, text="Not found") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.get_item_attachments_async( - dataset="default", table="accounts", id="1" + await resolve_generated_result( + client.list_item_attachments( + dataset="default", table="accounts", id="1" + ) ) assert exc_info.value.status_code == 404 @@ -1035,11 +1076,11 @@ async def test_get_attachment_content_success(self, mock_credential): mock_response = MockResponse(status=200, content=b"binary-data") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - result = await client.get_attachment_content_async( + result = await client.get_attachment_content( dataset="default", table="accounts", id="1", attachment_id="att1" ) @@ -1055,12 +1096,12 @@ async def test_get_attachment_content_error_response(self, mock_credential): mock_response = MockResponse(status=404, text="Not found") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.get_attachment_content_async( + await client.get_attachment_content( dataset="default", table="accounts", id="1", attachment_id="att1" ) @@ -1077,11 +1118,11 @@ async def test_delete_attachment_success(self, mock_credential): mock_response = MockResponse(status=200, text="") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.delete_attachment_async( + await client.delete_attachment( dataset="default", table="accounts", id="1", attachment_id="att1" ) @@ -1093,19 +1134,19 @@ async def test_delete_attachment_success(self, mock_credential): async def test_delete_attachment_error_response(self, mock_credential): """Test that error response raises ConnectorException.""" client = _make_client(mock_credential) - mock_response = MockResponse(status=404, text="Not found") + mock_response = MockResponse(status=500, text="Server error") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.delete_attachment_async( + await client.delete_attachment( dataset="default", table="accounts", id="1", attachment_id="att1" ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestDeleteItem: @@ -1118,11 +1159,11 @@ async def test_delete_item_success(self, mock_credential): mock_response = MockResponse(status=200, text="") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.delete_item_async(dataset="default", table="accounts", id="1") + await client.delete_item(dataset="default", table="accounts", id="1") call_args = mock_send.call_args assert call_args[0][0] == "DELETE" @@ -1132,19 +1173,19 @@ async def test_delete_item_success(self, mock_credential): async def test_delete_item_error_response(self, mock_credential): """Test that error response raises ConnectorException.""" client = _make_client(mock_credential) - mock_response = MockResponse(status=404, text="Not found") + mock_response = MockResponse(status=500, text="Server error") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.delete_item_async( + await client.delete_item( dataset="default", table="accounts", id="1" ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestDisassociateRecordsPostItem: @@ -1157,11 +1198,11 @@ async def test_disassociate_records_success(self, mock_credential): mock_response = MockResponse(status=200, text='{}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.disassociate_records_post_item_async( + await client.disassociate_records_post_item( dataset="default", table="accounts", id="1", @@ -1181,12 +1222,12 @@ async def test_disassociate_records_error_response(self, mock_credential): mock_response = MockResponse(status=400, text="Bad request") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.disassociate_records_post_item_async( + await client.disassociate_records_post_item( dataset="default", table="accounts", id="1", @@ -1207,11 +1248,11 @@ async def test_disassociate_single_value_success(self, mock_credential): mock_response = MockResponse(status=200, text='{}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.disassociate_single_value_record_delete_item_async( + await client.disassociate_single_value_record_delete_item( dataset="default", table="accounts", id="1", @@ -1226,22 +1267,22 @@ async def test_disassociate_single_value_success(self, mock_credential): async def test_disassociate_single_value_error_response(self, mock_credential): """Test that error response raises ConnectorException.""" client = _make_client(mock_credential) - mock_response = MockResponse(status=404, text="Not found") + mock_response = MockResponse(status=500, text="Server error") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.disassociate_single_value_record_delete_item_async( + await client.disassociate_single_value_record_delete_item( dataset="default", table="accounts", id="1", relationship="primarycontactid", ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestGetCollectionRelationships: @@ -1254,17 +1295,19 @@ async def test_get_collection_relationships_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"value": []}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.get_collection_relationships_async( - dataset="default", - table="accounts", - id="1", - collection_type="onetomany", - relationship="account_tasks", - target="task", + await resolve_generated_result( + client.list_collection_relationships( + dataset="default", + table="accounts", + id="1", + collection_type="onetomany", + relationship="account_tasks", + target="task", + ) ) call_args = mock_send.call_args @@ -1279,18 +1322,20 @@ async def test_get_collection_relationships_error_response(self, mock_credential mock_response = MockResponse(status=404, text="Not found") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.get_collection_relationships_async( - dataset="default", - table="accounts", - id="1", - collection_type="onetomany", - relationship="account_tasks", - target="task", + await resolve_generated_result( + client.list_collection_relationships( + dataset="default", + table="accounts", + id="1", + collection_type="onetomany", + relationship="account_tasks", + target="task", + ) ) assert exc_info.value.status_code == 404 @@ -1306,11 +1351,11 @@ async def test_get_multi_select_metadata_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"name": "col"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.get_multi_select_metadata_async( + await client.get_multi_select_metadata( dataset="default", table="accounts", item="col" ) @@ -1325,12 +1370,12 @@ async def test_get_multi_select_metadata_error_response(self, mock_credential): mock_response = MockResponse(status=404, text="Not found") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.get_multi_select_metadata_async( + await client.get_multi_select_metadata( dataset="default", table="accounts", item="col" ) @@ -1347,11 +1392,11 @@ async def test_get_option_set_metadata_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"name": "col"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.get_option_set_metadata_async( + await client.get_option_set_metadata( dataset="default", table="accounts", item="col", type_="Picklist" ) @@ -1367,12 +1412,12 @@ async def test_get_option_set_metadata_error_response(self, mock_credential): mock_response = MockResponse(status=404, text="Not found") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.get_option_set_metadata_async( + await client.get_option_set_metadata( dataset="default", table="accounts", item="col", type_="Picklist" ) @@ -1397,11 +1442,11 @@ async def test_get_items_double_encodes_dataset_environment_url(self, mock_crede mock_response = MockResponse(status=200, text='{"value": []}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - result = client.get_items_async( + result = client.list_items( dataset="https://org12345.crm.dynamics.com", table="accounts", ) @@ -1424,11 +1469,11 @@ async def test_get_item_double_encodes_all_segments(self, mock_credential): mock_response = MockResponse(status=200, text='{"name": "row"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.get_item_async( + await client.get_item( dataset="https://org12345.crm.dynamics.com", table="my table", id="a/b", @@ -1452,11 +1497,11 @@ async def test_post_item_double_encodes_dataset_environment_url(self, mock_crede mock_response = MockResponse(status=200, text='{"accountid": "1"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.post_item_async( + await client.post_item( input=PostItemInput(additional_properties={"name": "Contoso"}), dataset="https://org12345.crm.dynamics.com", table="accounts", diff --git a/tests/test_documentdb.py b/tests/test_documentdb.py index 27dff78..1e36296 100644 --- a/tests/test_documentdb.py +++ b/tests/test_documentdb.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.documentdb import DocumentdbClient from azure.connectors.documentdb import ( - DocumentdbClient, PostDocumentsResponse, CreateStoredProcedureInput, CreateStoredProcedureResponse, @@ -75,7 +75,7 @@ def test_init_with_custom_settings(self, mock_credential): client = DocumentdbClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -146,11 +146,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.query_documents_async( + result = await resolve_generated_result(client.list_query_documents( cosmos_db_account_name="mycosmosdb", database_id="mydb", container_id="mycontainer" @@ -177,11 +177,11 @@ async def test_with_query_text(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.query_documents_async( + await resolve_generated_result(client.list_query_documents( cosmos_db_account_name="mycosmosdb", database_id="mydb", container_id="mycontainer", @@ -204,11 +204,11 @@ async def test_with_partition_key(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.query_documents_async( + await resolve_generated_result(client.list_query_documents( cosmos_db_account_name="mycosmosdb", database_id="mydb", container_id="mycontainer", @@ -220,8 +220,8 @@ async def test_with_partition_key(self, mock_credential): assert "partitionKey=region-1" in url @pytest.mark.asyncio - async def test_with_all_query_parameters(self, mock_credential): - """Test GET request with all query parameters.""" + async def test_with_public_query_parameters(self, mock_credential): + """Test GET request with public query parameters.""" client = DocumentdbClient( "https://example.azure.com/connections/test", credential=mock_credential @@ -234,18 +234,17 @@ async def test_with_all_query_parameters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.query_documents_async( + await resolve_generated_result(client.list_query_documents( cosmos_db_account_name="mycosmosdb", database_id="mydb", container_id="mycontainer", query_text="SELECT * FROM c", partition_key="pk1", max_item_count="100", - continuation_token="abc123", consistency_level="Session", session_token="session-xyz" )) @@ -255,7 +254,7 @@ async def test_with_all_query_parameters(self, mock_credential): assert "queryText=" in url assert "partitionKey=pk1" in url assert "maxItemCount=100" in url - assert "continuationToken=abc123" in url + assert "continuationToken=" not in url assert "consistencyLevel=Session" in url assert "sessionToken=session-xyz" in url @@ -271,12 +270,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(client.query_documents_async( + await resolve_generated_result(client.list_query_documents( cosmos_db_account_name="mycosmosdb", database_id="mydb", container_id="nonexistent" @@ -296,11 +295,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await resolve_generated_result(client.query_documents_async( + result = await resolve_generated_result(client.list_query_documents( cosmos_db_account_name="mycosmosdb", database_id="mydb", container_id="mycontainer" @@ -319,12 +318,12 @@ async def test_unauthorized_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(client.query_documents_async( + await resolve_generated_result(client.list_query_documents( cosmos_db_account_name="mycosmosdb", database_id="mydb", container_id="mycontainer" @@ -333,6 +332,41 @@ async def test_unauthorized_raises_exception(self, mock_credential): assert exc_info.value.status_code == 401 +class TestListDocuments: + """Tests for list_documents collection selection.""" + + @pytest.mark.asyncio + async def test_ignores_auxiliary_metadata_array(self, mock_credential): + """Test the pager yields documents rather than auxiliary metadata.""" + client = DocumentdbClient( + "https://example.azure.com/connections/test", + credential=mock_credential, + ) + mock_response = MockResponse( + status=200, + text=( + '{"Documents": [{"id": "doc-1"}], ' + '"@metadata": [{"name": "classification"}]}' + ), + ) + + with patch.object( + client._http_client, + "send", + new_callable=AsyncMock, + return_value=mock_response, + ): + result = await resolve_generated_result( + client.list_documents( + cosmos_db_account_name="mycosmosdb", + database_id="mydb", + collection_id="mycollection", + ) + ) + + assert result == [{"id": "doc-1"}] + + class TestDataClasses: """Tests for data class creation and attributes.""" @@ -649,16 +683,16 @@ async def test_multiple_consecutive_calls(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.query_documents_async( + await resolve_generated_result(client.list_query_documents( cosmos_db_account_name="account1", database_id="db1", container_id="container1" )) - await resolve_generated_result(client.query_documents_async( + await resolve_generated_result(client.list_query_documents( cosmos_db_account_name="account2", database_id="db2", container_id="container2" @@ -678,11 +712,11 @@ async def test_special_characters_in_ids(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.query_documents_async( + await resolve_generated_result(client.list_query_documents( cosmos_db_account_name="my-cosmos-db", database_id="my-database", container_id="my-container" diff --git a/tests/test_docusign.py b/tests/test_docusign.py index 61ad572..405b851 100644 --- a/tests/test_docusign.py +++ b/tests/test_docusign.py @@ -7,10 +7,10 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.docusign import DocusignClient from azure.connectors.docusign import ( AdditionalURLForSenderView, CombinedEmailBodyAndCustomFields, - DocusignClient, DynamicSigningUrlFields, DynamicSigners, UpdateDocgenFormFieldsInput, @@ -19,6 +19,7 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestDocusignClientInitialization: @@ -54,7 +55,7 @@ def test_init_with_custom_settings(self, mock_credential): client = DocusignClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -146,11 +147,11 @@ async def test_generate_embedded_sender_url_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.generate_embedded_sender_url_async( + result = await client.generate_embedded_sender_url( input=payload, account_id="acct-1", envelope_id="env-1", @@ -182,11 +183,11 @@ async def test_generate_embedded_signing_url_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.generate_embedded_signing_url_async( + result = await client.generate_embedded_signing_url( input=payload, account_id="acct-1", envelope_id="env-1", @@ -219,22 +220,24 @@ async def test_success(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"accounts": [{"accountId": "123"}]}') + mock_response = MockResponse( + status=200, + text='{"loginAccounts": [{"accountId": "123"}]}', + ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_login_accounts_async() + result = await resolve_generated_result(client.list_login_accounts()) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert path.endswith("/oauth/userinfo") - assert result is not None - assert "accounts" in result + assert result == [{"accountId": "123"}] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -247,12 +250,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.get_login_accounts_async() + await resolve_generated_result(client.list_login_accounts()) class TestSearchListEnvelopesAsync: @@ -269,11 +272,11 @@ async def test_success_with_filters(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.search_list_envelopes_async( + result = await client.search_list_envelopes( account_id="acct-1", envelope_title="Quarterly Contract", top="5", @@ -300,12 +303,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.search_list_envelopes_async(account_id="acct-1") + await client.search_list_envelopes(account_id="acct-1") class TestCreateBlankEnvelopeAsync: @@ -323,11 +326,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_blank_envelope_async( + result = await client.create_blank_envelope( input=payload, account_id="acct-1", email_subject="Please sign", @@ -354,12 +357,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.create_blank_envelope_async( + await client.create_blank_envelope( input=payload, account_id="acct-1", email_subject="Please sign", @@ -381,11 +384,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.send_envelope_async( + result = await client.send_envelope( input=payload, account_id="acct-1", status="sent", @@ -415,12 +418,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.send_envelope_async( + await client.send_envelope( input=payload, account_id="acct-1", status="sent", @@ -444,11 +447,11 @@ async def test_success_sends_body_and_returns_result(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.update_docgen_form_fields_async( + await client.update_docgen_form_fields( input=payload, account_id="acct-1", envelope_id="env-1", @@ -474,12 +477,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.update_docgen_form_fields_async( + await client.update_docgen_form_fields( input=payload, account_id="acct-1", envelope_id="env-1", @@ -491,8 +494,8 @@ class TestRemoveRecipientFromEnvelopeAsync: """Tests for remove_recipient_from_envelope_async method (DELETE).""" @pytest.mark.asyncio - async def test_success_returns_result(self, mock_credential): - """Test successful DELETE returns response.""" + async def test_success_returns_declared_response(self, mock_credential): + """Test successful DELETE returns its declared response body.""" client = DocusignClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -501,11 +504,11 @@ async def test_success_returns_result(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.remove_recipient_from_envelope_async( + result = await client.remove_recipient_from_envelope( account_id="acct-1", envelope_id="env-1", folder_id=None, @@ -515,7 +518,7 @@ async def test_success_returns_result(self, mock_credential): mock_send.assert_called_once() method = mock_send.call_args[0][0] assert method == "DELETE" - assert result is not None + assert result == {"recipientsRemoved": True} @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -524,16 +527,16 @@ async def test_error_response_raises_exception(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=404, text='{"error": "Envelope not found"}') + mock_response = MockResponse(status=500, text='{"error": "Server error"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.remove_recipient_from_envelope_async( + await client.remove_recipient_from_envelope( account_id="acct-1", envelope_id="missing-env", folder_id=None, diff --git a/tests/test_docuware.py b/tests/test_docuware.py index 5f3febe..ab81f75 100644 --- a/tests/test_docuware.py +++ b/tests/test_docuware.py @@ -2,13 +2,15 @@ """Unit tests for DocuwareClient.""" +from collections.abc import Mapping +from typing import Any, get_args, get_origin, get_type_hints from unittest.mock import AsyncMock, patch import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.docuware import DocuwareClient from azure.connectors.docuware import ( - DocuwareClient, SearchForDocumentsInFileCabinetInput, UpdateIndexFieldsInput, ) @@ -16,6 +18,7 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestDocuwareClientInitialization: @@ -51,7 +54,7 @@ def test_init_with_custom_settings(self, mock_credential): client = DocuwareClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -118,11 +121,11 @@ async def test_success_sends_get(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_organization_async() + result = await client.get_organization() mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -143,12 +146,12 @@ async def test_error_response_raises_connector_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.get_organization_async() + await client.get_organization() assert exc_info.value.status_code == 401 @@ -167,11 +170,13 @@ async def test_success_appends_query_parameter(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_file_cabinets_async(file_cabinet_type="FileCabinet") + result = await resolve_generated_result( + client.list_file_cabinets(file_cabinet_type="FileCabinet") + ) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -184,6 +189,21 @@ async def test_success_appends_query_parameter(self, mock_credential): class TestSearchForDocumentsInFileCabinetAsync: """Tests for search_for_documents_in_file_cabinet_async (POST with body).""" + def test_input_annotation_accepts_model_or_mapping(self): + """Test dynamic search criteria support typed models and wire mappings.""" + input_annotation = get_type_hints( + DocuwareClient.search_for_documents_in_file_cabinet + )["input"] + annotation_members = get_args(input_annotation) + + assert SearchForDocumentsInFileCabinetInput in annotation_members + mapping_annotation = next( + member + for member in annotation_members + if get_origin(member) is Mapping + ) + assert get_args(mapping_annotation) == (str, Any) + @pytest.mark.asyncio async def test_success_forwards_request_body(self, mock_credential): """Test that the POST operation forwards the request body to send_async.""" @@ -196,11 +216,11 @@ async def test_success_forwards_request_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.search_for_documents_in_file_cabinet_async( + result = await client.search_for_documents_in_file_cabinet( input=request, file_cabinet="cabinet-1", search_dialog_id="dialog-1", @@ -227,12 +247,12 @@ async def test_error_response_raises_connector_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.search_for_documents_in_file_cabinet_async( + await client.search_for_documents_in_file_cabinet( input=request, file_cabinet="cabinet-1", search_dialog_id="dialog-1", @@ -256,11 +276,11 @@ async def test_success_forwards_request_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.update_index_fields_async( + await client.update_index_fields( input=request, file_cabinet_id="cabinet-1", document_id="document-1", @@ -284,11 +304,11 @@ async def test_success_sends_delete(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.delete_document_async( + result = await client.delete_document( file_cabinet_id="cabinet-1", document_id="doc-1", ) @@ -306,21 +326,21 @@ async def test_error_response_raises_connector_exception(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=404, text="Not Found") + mock_response = MockResponse(status=500, text="Server error") with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.delete_document_async( + await client.delete_document( file_cabinet_id="cabinet-1", document_id="doc-1", ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestDownloadFileAsync: @@ -337,11 +357,11 @@ async def test_success_returns_content_bytes(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.download_file_async( + result = await client.download_file( file_cabinet_id="cabinet-1", document_id="doc-1", file_number="1", @@ -362,7 +382,7 @@ async def test_success_returns_content_bytes(self, mock_credential): OPERATION_ARGS = { "get_organization": {}, - "get_file_cabinets": {"file_cabinet_type": None}, + "list_file_cabinets": {"file_cabinet_type": None}, "get_document_information": {"file_cabinet_id": "cabinet-1", "document_id": "doc-1"}, "delete_document": {"file_cabinet_id": "cabinet-1", "document_id": "doc-1"}, "download_file": { @@ -389,11 +409,11 @@ async def test_success_returns_content_bytes(self, mock_credential): }, "transfer_document": {"input": {}, "destination_file_cabinet_id": "cabinet-2"}, "place_a_stamp": {"input": {}, "file_cabinet_id": "cabinet-1", "document_id": "doc-1"}, - "get_dialogs": {"file_cabinet": "cabinet-1"}, - "get_dialog_fields": {"file_cabinet": "cabinet-1", "dialog_id": "dialog-1"}, - "get_stamps": {"file_cabinet": "cabinet-1"}, - "get_stamp_fields": {"file_cabinet": "cabinet-1", "stamp": "stamp-1"}, - "get_file_cabinet_fields": {"file_cabinet": "cabinet-1"}, + "list_dialogs": {"file_cabinet": "cabinet-1"}, + "list_dialog_fields": {"file_cabinet": "cabinet-1", "dialog_id": "dialog-1"}, + "list_stamps": {"file_cabinet": "cabinet-1"}, + "list_stamp_fields": {"file_cabinet": "cabinet-1", "stamp": "stamp-1"}, + "list_file_cabinet_fields": {"file_cabinet": "cabinet-1"}, } ALL_OPERATIONS = sorted(OPERATION_ARGS.keys()) @@ -401,8 +421,8 @@ async def test_success_returns_content_bytes(self, mock_credential): async def _invoke_operation(client: DocuwareClient, operation: str): """Invoke a DocuWare operation by name for shared method tests.""" - method = getattr(client, f"{operation}_async") - return await method(**OPERATION_ARGS[operation]) + method = getattr(client, f"{operation}") + return await resolve_generated_result(method(**OPERATION_ARGS[operation])) class TestDocuwareClientAllOperations: @@ -417,7 +437,7 @@ async def test_all_operations_success(self, mock_credential, operation): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: @@ -443,7 +463,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): diff --git a/tests/test_dropbox.py b/tests/test_dropbox.py index 95f4777..d9c160f 100644 --- a/tests/test_dropbox.py +++ b/tests/test_dropbox.py @@ -6,50 +6,53 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.dropbox import DropboxClient from azure.connectors.dropbox import ( BlobMetadata, BlobMetadataPage, - DropboxClient, ) from azure.connectors.sdk import ( ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result async def _invoke_operation(client: DropboxClient, operation: str): """Invoke a Dropbox operation by name for shared parameterized tests.""" if operation == "get_file_metadata": - return await client.get_file_metadata_async(id="file123") + return await client.get_file_metadata(id="file123") if operation == "update_file": - return await client.update_file_async(input=b"updated content", id="file123") + return await client.update_file(input=b"updated content", id="file123") if operation == "delete_file": - return await client.delete_file_async(id="file123") + return await client.delete_file(id="file123") if operation == "get_file_metadata_by_path": - return await client.get_file_metadata_by_path_async(path="/Documents/file.txt") + return await client.get_file_metadata_by_path(path="/Documents/file.txt") if operation == "get_file_content_by_path": - return await client.get_file_content_by_path_async(path="/Documents/file.txt") + return await client.get_file_content_by_path(path="/Documents/file.txt") if operation == "get_file_content": - return await client.get_file_content_async(id="file123") + return await client.get_file_content(id="file123") if operation == "create_file": - return await client.create_file_async( + return await client.create_file( input=b"file content", folder_path="/Documents", name="created.txt", ) if operation == "copy_file": - return await client.copy_file_async( + return await client.copy_file( source="/Documents/source.txt", destination="/Documents/copy.txt", ) if operation == "list_folder": - return await client.list_folder_async(id="folder123") + return await resolve_generated_result(client.list_folder(id="folder123")) if operation == "list_root_folder": - return await client.list_root_folder_async() + return await resolve_generated_result(client.list_root_folder()) if operation == "extract_folder": - return await client.extract_folder_async( - source="/Documents/archive.zip", - destination="/Documents/extracted", + return await resolve_generated_result( + client.extract_folder( + source="/Documents/archive.zip", + destination="/Documents/extracted", + ) ) raise ValueError(f"Unsupported operation '{operation}'.") @@ -88,7 +91,7 @@ def test_init_with_custom_settings(self, mock_credential): client = DropboxClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -155,11 +158,11 @@ async def test_get_file_metadata_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_file_metadata_async(id="file123") + result = await client.get_file_metadata(id="file123") assert result["name"] == "doc.txt" call_args = mock_send.call_args @@ -177,11 +180,11 @@ async def test_get_file_content_by_path_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.get_file_content_by_path_async(path="/Documents/file.txt") + result = await client.get_file_content_by_path(path="/Documents/file.txt") assert result == b"dropbox file content" @@ -196,11 +199,11 @@ async def test_create_file_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_file_async( + result = await client.create_file( input=b"file content", folder_path="/Documents", name="created.txt", @@ -247,7 +250,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): diff --git a/tests/test_dynamicsax.py b/tests/test_dynamicsax.py index c3b9a10..e66bf33 100644 --- a/tests/test_dynamicsax.py +++ b/tests/test_dynamicsax.py @@ -6,6 +6,7 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.dynamicsax import DynamicsaxClient from azure.connectors.dynamicsax import ( AxOnlineProcedureResult, BusinessEventSubscription, @@ -13,7 +14,6 @@ BusinessEventsList, DataSet, DataSetsList, - DynamicsaxClient, ExecuteProcedureInput, GetItemResponse, Item, @@ -31,7 +31,10 @@ ConnectorException, ) from tests.conftest import MockResponse -from tests.generated_connector_test_utils import resolve_generated_result +from tests.generated_connector_test_utils import ( + generated_pager_response_text, + resolve_generated_result, +) BASE_URL = "https://example.azure.com/connections/test" @@ -42,7 +45,7 @@ "dataset": "ds", "procedure": "proc", }, - "get_items": {"dataset": "ds", "table": "tbl"}, + "list_items": {"dataset": "ds", "table": "tbl"}, "post_item": { "input": PostItemInput(), "dataset": "ds", @@ -56,16 +59,16 @@ "table": "tbl", "id": "1", }, - "get_tables": {"dataset": "ds"}, - "get_data_sets": {}, - "get_business_event_categories": {"dataset": "ds"}, - "get_business_events": {"dataset": "ds", "businesseventcategory": "cat"}, - "get_legal_entities": { + "list_tables": {"dataset": "ds"}, + "list_data_sets": {}, + "list_business_event_categories": {"dataset": "ds"}, + "list_business_events": {"dataset": "ds", "businesseventcategory": "cat"}, + "list_legal_entities": { "dataset": "ds", "businesseventcategory": "cat", "businessevent": "evt", }, - "get_procedures": {"dataset": "ds"}, + "list_procedures": {"dataset": "ds"}, "get_procedure": {"dataset": "ds", "procedure": "proc"}, "get_table": {"dataset": "ds", "table": "tbl"}, } @@ -79,7 +82,7 @@ async def _invoke_operation(client: DynamicsaxClient, operation: str): """Invoke a Dynamics AX operation by name for shared parametrized tests.""" return await resolve_generated_result( - getattr(client, f"{operation}_async")(**OPERATION_ARGS[operation]) + getattr(client, f"{operation}")(**OPERATION_ARGS[operation]) ) @@ -116,7 +119,7 @@ def test_init_with_custom_settings(self, mock_credential): client = DynamicsaxClient( BASE_URL, credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -171,13 +174,13 @@ async def test_get_data_sets_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_data_sets_async() + result = await resolve_generated_result(client.list_data_sets()) - assert result["value"][0]["name"] == "instance-1" + assert result == [{"name": "instance-1"}] assert mock_send.call_args[0][0] == "GET" assert mock_send.call_args[0][1].endswith("/datasets") @@ -189,11 +192,11 @@ async def test_get_items_targets_items_endpoint(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await resolve_generated_result(client.get_items_async(dataset="ds", table="tbl")) + await resolve_generated_result(client.list_items(dataset="ds", table="tbl")) request_url = mock_send.call_args[0][1] assert "/datasets/ds/tables/tbl/items" in request_url @@ -206,11 +209,11 @@ async def test_get_items_appends_odata_query_params(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await resolve_generated_result(client.get_items_async( + await resolve_generated_result(client.list_items( dataset="ds", table="tbl", filter="Name eq 'x'", @@ -230,11 +233,11 @@ async def test_post_item_sends_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.post_item_async(input=item_input, dataset="ds", table="tbl") + result = await client.post_item(input=item_input, dataset="ds", table="tbl") assert result["id"] == "1" assert mock_send.call_args[0][0] == "POST" @@ -249,11 +252,11 @@ async def test_patch_item_sends_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.patch_item_async( + result = await client.patch_item( input=item_input, dataset="ds", table="tbl", @@ -272,11 +275,11 @@ async def test_delete_item_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.delete_item_async(dataset="ds", table="tbl", id="1") + result = await client.delete_item(dataset="ds", table="tbl", id="1") assert result is None assert mock_send.call_args[0][0] == "DELETE" @@ -289,11 +292,11 @@ async def test_get_table_targets_metadata_endpoint(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.get_table_async(dataset="ds", table="tbl") + await client.get_table(dataset="ds", table="tbl") request_url = mock_send.call_args[0][1] assert "/$metadata.json/datasets/ds/tables/tbl" in request_url @@ -303,16 +306,17 @@ async def test_get_table_targets_metadata_endpoint(self, mock_credential): async def test_all_operations_success(self, mock_credential, operation): """Test every operation returns the expected success result.""" client = _make_client(credential=mock_credential) + method = getattr(client, operation) response_text = ( - '{"value":[{"value":"ok"}]}' - if operation == "get_items" + generated_pager_response_text(method) + if operation.startswith("list_") else '{"value":"ok"}' ) mock_response = MockResponse(status=200, text=response_text) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -320,8 +324,8 @@ async def test_all_operations_success(self, mock_credential, operation): if operation in NO_JSON_OPERATIONS: assert result is None - elif operation == "get_items": - assert result == [{"value": "ok"}] + elif operation.startswith("list_"): + assert result == [{"ok": True}] else: assert result == {"value": "ok"} @@ -334,7 +338,7 @@ async def test_no_json_operations_ignore_body(self, mock_credential, operation): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -359,7 +363,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -374,7 +378,9 @@ class TestDynamicsaxTypeSerialization: def test_dataclass_instances_initialize_expected_defaults(self): """Test generated dataclasses initialize with expected default values.""" - assert BusinessEventSubscription().notification_url is None + assert BusinessEventSubscription( + notification_url="https://example.com/callback" + ).notification_url == "https://example.com/callback" assert BusinessEventSubscriptionResponse().id is None assert ExecuteProcedureInput().additional_properties == {} assert AxOnlineProcedureResult().value is None diff --git a/tests/test_elfsquaddata.py b/tests/test_elfsquaddata.py index ea27bf8..265b56b 100644 --- a/tests/test_elfsquaddata.py +++ b/tests/test_elfsquaddata.py @@ -8,7 +8,8 @@ import pytest import azure.connectors.elfsquaddata as elfsquaddata_module -from azure.connectors.elfsquaddata import ElfsquaddataClient, TRIGGER_OPERATIONS +from azure.connectors.aio.elfsquaddata import ElfsquaddataClient +from azure.connectors.elfsquaddata import TRIGGER_OPERATIONS from tests.conftest import MockResponse from tests.generated_connector_test_utils import ( GeneratedConnectorContractTests, @@ -20,7 +21,7 @@ "delete_entity_by_id": ("DELETE", False), **dict.fromkeys( [ - "get_entities", + "list_entities", "get_entity_by_id", "get_function_definition", "get_functions", @@ -68,11 +69,11 @@ async def test_get_entities_serializes_query_and_response( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"value": []}'), ) as mock_send: - result = await resolve_generated_result(client.get_entities_async( + result = await resolve_generated_result(client.list_entities( entity_name="products", top=10, select="id,name", @@ -109,7 +110,7 @@ async def test_get_entities_follows_odata_pages_and_terminates( ) as client: with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, side_effect=[ MockResponse(status=200, text=json.dumps({ @@ -123,7 +124,7 @@ async def test_get_entities_follows_odata_pages_and_terminates( ], ) as transport: entities = [ - entity async for entity in client.get_entities_async( + entity async for entity in client.list_entities( entity_name="products", top=10, ) @@ -155,12 +156,12 @@ async def test_get_entities_empty_response_is_a_single_request( ) as client: with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=status, text=body), ) as transport: entities = [ - entity async for entity in client.get_entities_async( + entity async for entity in client.list_entities( entity_name="products" ) ] diff --git a/tests/test_etsy.py b/tests/test_etsy.py index bcd816f..03c3f61 100644 --- a/tests/test_etsy.py +++ b/tests/test_etsy.py @@ -3,7 +3,7 @@ """Contract tests for EtsyClient.""" import azure.connectors.etsy as etsy_module -from azure.connectors.etsy import EtsyClient +from azure.connectors.aio.etsy import EtsyClient from tests.generated_connector_test_utils import GeneratedConnectorContractTests diff --git a/tests/test_eventbrite.py b/tests/test_eventbrite.py index 546f553..4ddccf5 100644 --- a/tests/test_eventbrite.py +++ b/tests/test_eventbrite.py @@ -3,18 +3,19 @@ """Contract tests for EventbriteClient.""" import azure.connectors.eventbrite as eventbrite_module -from azure.connectors.eventbrite import EventbriteClient, TRIGGER_OPERATIONS +from azure.connectors.aio.eventbrite import EventbriteClient +from azure.connectors.eventbrite import TRIGGER_OPERATIONS from tests.generated_connector_test_utils import GeneratedConnectorContractTests OPERATION_CONTRACTS = { "create_event": ("POST", False), "update_event": ("POST", False), - "get_organizations": ("GET", False), - "get_organizers": ("GET", False), - "get_my_venues": ("GET", False), - "get_categories": ("GET", False), - "get_organization_events": ("GET", False), + "list_organizations": ("GET", False), + "list_organizers": ("GET", False), + "list_my_venues": ("GET", False), + "list_categories": ("GET", False), + "list_organization_events": ("GET", False), } diff --git a/tests/test_eventhubs.py b/tests/test_eventhubs.py index 1539754..723fba1 100644 --- a/tests/test_eventhubs.py +++ b/tests/test_eventhubs.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.eventhubs import EventhubsClient from azure.connectors.eventhubs import ( - EventhubsClient, Event, SendEventsInput, ObjectEntity, @@ -18,6 +18,7 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestEventhubsClientInitialization: @@ -53,7 +54,7 @@ def test_init_with_custom_settings(self, mock_credential): client = EventhubsClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -125,11 +126,11 @@ async def test_generate_event_schema(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.generate_event_schema_async( + result = await client.generate_event_schema( content_type="application/json", content_schema="schema-1" ) @@ -159,11 +160,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.send_event_async( + await client.send_event( input=event_input, event_hub_name="myeventhub" ) @@ -189,11 +190,11 @@ async def test_with_partition_key(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.send_event_async( + await client.send_event( input=event_input, event_hub_name="myeventhub", partition_key="partition-1" @@ -216,12 +217,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.send_event_async( + await client.send_event( input=event_input, event_hub_name="myeventhub" ) @@ -248,11 +249,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.send_events_async( + await client.send_events( input=events_input, event_hub_name="myeventhub", partition_key="partition-1" @@ -276,11 +277,11 @@ async def test_with_partition_key(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.send_events_async( + await client.send_events( input=events_input, event_hub_name="myeventhub", partition_key="partition-2" @@ -304,12 +305,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.send_events_async( + await client.send_events( input=events_input, event_hub_name="myeventhub", partition_key="partition-1" @@ -428,12 +429,16 @@ async def test_multiple_consecutive_calls(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_partition_keys_async(event_hub_name="hub1") - await client.get_partition_keys_async(event_hub_name="hub2") + await resolve_generated_result( + client.list_partition_keys(event_hub_name="hub1") + ) + await resolve_generated_result( + client.list_partition_keys(event_hub_name="hub2") + ) assert mock_send.call_count == 2 @@ -449,12 +454,14 @@ async def test_special_characters_in_event_hub_name(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_partition_keys_async( - event_hub_name="my-event-hub" + await resolve_generated_result( + client.list_partition_keys( + event_hub_name="my-event-hub" + ) ) call_args = mock_send.call_args @@ -473,11 +480,11 @@ async def test_unauthorized_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_event_hubs_async() + await resolve_generated_result(client.list_event_hubs()) assert exc_info.value.status_code == 401 diff --git a/tests/test_excelonline.py b/tests/test_excelonline.py index f4df36f..b887bad 100644 --- a/tests/test_excelonline.py +++ b/tests/test_excelonline.py @@ -6,9 +6,9 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.excelonline import ExcelonlineClient from azure.connectors.excelonline import ( CreateWorksheetInput, - ExcelonlineClient, GetAllWorksheetsResponse, GetColumnsResponse, GetTablesResponse, @@ -28,27 +28,27 @@ async def _invoke_operation(client: ExcelonlineClient, operation: str): """Invoke an Excel Online operation by name for shared error tests.""" if operation == "create_table": - return await client.create_table_async( + return await client.create_table( input=TableToCreate(table_name="Table1", range="A1:B2"), drive="drive123", file="file123", ) if operation == "create_id_column": - return await client.create_id_column_async( + return await client.create_id_column( drive="drive123", file="file123", table="Table1", id_column="ID", ) - if operation == "get_items": - return await resolve_generated_result(client.get_items_async( + if operation == "list_items": + return await resolve_generated_result(client.list_items( drive="drive123", file="file123", table="Table1", top="10", )) if operation == "get_item": - return await client.get_item_async( + return await client.get_item( drive="drive123", file="file123", table="Table1", @@ -56,7 +56,7 @@ async def _invoke_operation(client: ExcelonlineClient, operation: str): id_column="ID", ) if operation == "delete_item": - return await client.delete_item_async( + return await client.delete_item( drive="drive123", file="file123", table="Table1", @@ -64,7 +64,7 @@ async def _invoke_operation(client: ExcelonlineClient, operation: str): id_column="ID", ) if operation == "patch_item": - return await client.patch_item_async( + return await client.patch_item( input=Item(dynamic_properties={"Name": "Updated"}), drive="drive123", file="file123", @@ -72,28 +72,34 @@ async def _invoke_operation(client: ExcelonlineClient, operation: str): id="row1", id_column="ID", ) - if operation == "get_all_worksheets": - return await client.get_all_worksheets_async(drive="drive123", file="file123") + if operation == "list_all_worksheets": + return await resolve_generated_result( + client.list_all_worksheets(drive="drive123", file="file123") + ) if operation == "create_worksheet": - return await client.create_worksheet_async( + return await client.create_worksheet( input=CreateWorksheetInput(name="Sheet2"), drive="drive123", file="file123", ) - if operation == "get_tables": - return await client.get_tables_async(drive="drive123", file="file123") + if operation == "list_tables": + return await resolve_generated_result( + client.list_tables(drive="drive123", file="file123") + ) if operation == "add_row": - return await client.add_row_async( + return await client.add_row( input=Item(dynamic_properties={"Name": "Item1", "Value": 100}), drive="drive123", file="file123", table="Table1", ) - if operation == "get_columns": - return await client.get_columns_async( - drive="drive123", - file="file123", - table="Table1", + if operation == "list_columns": + return await resolve_generated_result( + client.list_columns( + drive="drive123", + file="file123", + table="Table1", + ) ) raise ValueError(f"Unsupported operation '{operation}'.") @@ -132,7 +138,7 @@ def test_init_with_custom_settings(self, mock_credential): client = ExcelonlineClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -199,11 +205,11 @@ async def test_create_table_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_table_async( + result = await client.create_table( input=TableToCreate(table_name="Table1", range="A1:B2"), drive="drive123", file="file123", @@ -224,11 +230,11 @@ async def test_get_items_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await resolve_generated_result(client.get_items_async( + result = await resolve_generated_result(client.list_items( drive="drive123", file="file123", table="Table1", @@ -252,11 +258,11 @@ async def test_patch_item_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.patch_item_async( + result = await client.patch_item( input=Item(dynamic_properties={"Name": "Updated"}), drive="drive123", file="file123", @@ -270,8 +276,8 @@ async def test_patch_item_success(self, mock_credential): assert isinstance(mock_send.call_args.kwargs["body"], Item) @pytest.mark.asyncio - async def test_get_all_worksheets_success(self, mock_credential): - """Test get_all_worksheets_async uses codeless worksheets endpoint.""" + async def test_list_all_worksheets_success(self, mock_credential): + """Test list_all_worksheets uses codeless worksheets endpoint.""" client = ExcelonlineClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -280,13 +286,15 @@ async def test_get_all_worksheets_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_all_worksheets_async(drive="drive123", file="file123") + result = await resolve_generated_result( + client.list_all_worksheets(drive="drive123", file="file123") + ) - assert len(result["value"]) == 1 + assert result == [{"name": "Sheet1"}] assert "/workbook/worksheets" in mock_send.call_args[0][1] @pytest.mark.asyncio @@ -300,11 +308,11 @@ async def test_add_row_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.add_row_async( + result = await client.add_row( input=Item(dynamic_properties={"Name": "Item1"}), drive="drive123", file="file123", @@ -324,15 +332,15 @@ class TestExcelonlineClientErrorHandling: [ "create_table", "create_id_column", - "get_items", + "list_items", "get_item", "delete_item", "patch_item", - "get_all_worksheets", + "list_all_worksheets", "create_worksheet", - "get_tables", + "list_tables", "add_row", - "get_columns", + "list_columns", ], ) async def test_error_response_raises_exception_for_all_operations( @@ -349,7 +357,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): diff --git a/tests/test_excelonlinebusiness.py b/tests/test_excelonlinebusiness.py index 3707bc7..94fe0c9 100644 --- a/tests/test_excelonlinebusiness.py +++ b/tests/test_excelonlinebusiness.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.excelonlinebusiness import ExcelonlinebusinessClient from azure.connectors.excelonlinebusiness import ( - ExcelonlinebusinessClient, TableToCreate, TableMetadata, Item, @@ -24,7 +24,7 @@ ConnectorException, ) from tests.conftest import MockResponse -from tests.generated_connector_test_utils import resolve_generated_result +from tests.generated_connector_test_utils import model_instance, resolve_generated_result class TestExcelonlinebusinessClientInitialization: @@ -60,7 +60,7 @@ def test_init_with_custom_settings(self, mock_credential): client = ExcelonlinebusinessClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -136,11 +136,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_table_async( + result = await client.create_table( input=table_input, drive="drive-id", file="file-id", @@ -162,16 +162,16 @@ async def test_error_response_raises_exception(self, mock_credential): ) mock_response = MockResponse(status=400, text='{"error": "Invalid range"}') - table_input = TableToCreate(table_name="Table1") + table_input = model_instance(TableToCreate, table_name="Table1") with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_table_async( + await client.create_table( input=table_input, drive="drive-id", file="file-id", @@ -196,11 +196,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.create_id_column_async( + await client.create_id_column( drive="drive-id", file="file-id", table="Table1", @@ -225,12 +225,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_id_column_async( + await client.create_id_column( drive="drive-id", file="file-id", table="InvalidTable", @@ -259,11 +259,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.get_items_async( + result = await resolve_generated_result(client.list_items( drive="drive-id", file="file-id", table="Table1", @@ -288,11 +288,11 @@ async def test_with_query_parameters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.get_items_async( + await resolve_generated_result(client.list_items( drive="drive-id", file="file-id", table="Table1", @@ -322,12 +322,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(client.get_items_async( + await resolve_generated_result(client.list_items( drive="drive-id", file="file-id", table="NonexistentTable", @@ -337,8 +337,8 @@ async def test_error_response_raises_exception(self, mock_credential): assert exc_info.value.status_code == 404 -class TestGetComments: - """Tests for get_comments_async method.""" +class TestListComments: + """Tests for list_comments method.""" @pytest.mark.asyncio async def test_success_with_json_response(self, mock_credential): @@ -355,20 +355,22 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_comments_async( - drive="drive-id", - file="file-id" + result = await resolve_generated_result( + client.list_comments( + drive="drive-id", + file="file-id" + ) ) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/workbook/comments" in call_args[0][1] - assert result["value"][0]["id"] == "comment1" + assert result[0]["id"] == "comment1" @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -382,14 +384,16 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_comments_async( - drive="drive-id", - file="nonexistent-file" + await resolve_generated_result( + client.list_comments( + drive="drive-id", + file="nonexistent-file" + ) ) assert exc_info.value.status_code == 404 @@ -413,11 +417,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_comment_async( + result = await client.get_comment( drive="drive-id", file="file-id", commentid="comment1" @@ -441,12 +445,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_comment_async( + await client.get_comment( drive="drive-id", file="file-id", commentid="nonexistent" @@ -477,11 +481,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.reply_comment_async( + result = await client.reply_comment( input=comment_details, drive="drive-id", file="file-id", @@ -507,12 +511,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.reply_comment_async( + await client.reply_comment( input=comment_details, drive="drive-id", file="file-id", @@ -540,11 +544,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_item_async( + result = await client.get_item( drive="drive-id", file="file-id", table="Table1", @@ -567,16 +571,16 @@ async def test_error_response_raises_exception(self, mock_credential): credential=mock_credential ) - mock_response = MockResponse(status=404, text='{"error": "Row not found"}') + mock_response = MockResponse(status=500, text='{"error": "Server error"}') with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_item_async( + await client.get_item( drive="drive-id", file="file-id", table="Table1", @@ -585,7 +589,7 @@ async def test_error_response_raises_exception(self, mock_credential): id_column="ID" ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestDeleteItem: @@ -603,11 +607,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.delete_item_async( + await client.delete_item( drive="drive-id", file="file-id", table="Table1", @@ -629,16 +633,16 @@ async def test_error_response_raises_exception(self, mock_credential): credential=mock_credential ) - mock_response = MockResponse(status=404, text='{"error": "Row not found"}') + mock_response = MockResponse(status=500, text='{"error": "Server error"}') with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.delete_item_async( + await client.delete_item( drive="drive-id", file="file-id", table="Table1", @@ -647,7 +651,7 @@ async def test_error_response_raises_exception(self, mock_credential): id_column="ID" ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestPatchItem: @@ -669,11 +673,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.patch_item_async( + result = await client.patch_item( input=item_input, drive="drive-id", file="file-id", @@ -702,12 +706,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.patch_item_async( + await client.patch_item( input=item_input, drive="drive-id", file="file-id", @@ -741,11 +745,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.run_script_prod_async( + result = await client.run_script_prod( input=script_input, drive="drive-id", file="file-id", @@ -774,12 +778,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.run_script_prod_async( + await client.run_script_prod( input=script_input, drive="drive-id", file="file-id", @@ -793,7 +797,7 @@ async def test_error_response_raises_exception(self, mock_credential): class TestGetAllWorksheets: - """Tests for get_all_worksheets_async method.""" + """Tests for list_all_worksheets method.""" @pytest.mark.asyncio async def test_success_with_json_response(self, mock_credential): @@ -810,21 +814,23 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_all_worksheets_async( - drive="drive-id", - file="file-id", - source="me" + result = await resolve_generated_result( + client.list_all_worksheets( + drive="drive-id", + file="file-id", + source="me" + ) ) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/worksheets" in call_args[0][1] - assert result["value"][0]["name"] == "Sheet1" + assert result[0]["name"] == "Sheet1" @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -838,15 +844,17 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_all_worksheets_async( - drive="drive-id", - file="nonexistent", - source="me" + await resolve_generated_result( + client.list_all_worksheets( + drive="drive-id", + file="nonexistent", + source="me" + ) ) assert exc_info.value.status_code == 404 @@ -871,11 +879,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_worksheet_async( + result = await client.create_worksheet( input=worksheet_input, drive="drive-id", file="file-id", @@ -901,12 +909,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_worksheet_async( + await client.create_worksheet( input=worksheet_input, drive="drive-id", file="file-id", @@ -917,7 +925,7 @@ async def test_error_response_raises_exception(self, mock_credential): class TestGetTables: - """Tests for get_tables_async method.""" + """Tests for list_tables method.""" @pytest.mark.asyncio async def test_success_with_json_response(self, mock_credential): @@ -934,21 +942,23 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_tables_async( - drive="drive-id", - file="file-id", - source="me" + result = await resolve_generated_result( + client.list_tables( + drive="drive-id", + file="file-id", + source="me" + ) ) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/tables" in call_args[0][1] - assert len(result["value"]) == 2 + assert len(result) == 2 @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -962,15 +972,17 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_tables_async( - drive="drive-id", - file="nonexistent", - source="me" + await resolve_generated_result( + client.list_tables( + drive="drive-id", + file="nonexistent", + source="me" + ) ) assert exc_info.value.status_code == 404 @@ -995,11 +1007,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.add_row_async( + result = await client.add_row( input=item_input, drive="drive-id", file="file-id", @@ -1026,12 +1038,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.add_row_async( + await client.add_row( input=item_input, drive="drive-id", file="file-id", @@ -1201,11 +1213,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await resolve_generated_result(client.get_items_async( + result = await resolve_generated_result(client.list_items( drive="drive-id", file="file-id", table="Table1", @@ -1225,17 +1237,17 @@ async def test_multiple_consecutive_calls(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.get_items_async( + await resolve_generated_result(client.list_items( drive="drive1", file="file1", table="Table1", source="me" )) - await resolve_generated_result(client.get_items_async( + await resolve_generated_result(client.list_items( drive="drive2", file="file2", table="Table2", diff --git a/tests/test_formstackforms.py b/tests/test_formstackforms.py index 0342c2a..b88f95a 100644 --- a/tests/test_formstackforms.py +++ b/tests/test_formstackforms.py @@ -3,7 +3,8 @@ """Contract tests for FormstackformsClient.""" import azure.connectors.formstackforms as formstackforms_module -from azure.connectors.formstackforms import FormstackformsClient, TRIGGER_OPERATIONS +from azure.connectors.aio.formstackforms import FormstackformsClient +from azure.connectors.formstackforms import TRIGGER_OPERATIONS from tests.generated_connector_test_utils import GeneratedConnectorContractTests diff --git a/tests/test_freshservice.py b/tests/test_freshservice.py index c55c15f..98a6189 100644 --- a/tests/test_freshservice.py +++ b/tests/test_freshservice.py @@ -8,12 +8,12 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.freshservice import FreshserviceClient from azure.connectors.freshservice import ( AddNoteRequest, AddNoteResponse, CreateTicketRequest, CreateUpdateTicketResponse, - FreshserviceClient, ListTicketResponse, ListUsersResponse, TicketResponse, @@ -25,16 +25,20 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import model_instance async def _invoke_operation(client: FreshserviceClient, operation: str): """Invoke a Freshservice operation by name for shared tests.""" if operation == "add_note": - return await client.add_note_async(input=AddNoteRequest(), ticket_id="1") + return await client.add_note( + input=model_instance(AddNoteRequest), + ticket_id="1", + ) if operation == "create_ticket": - return await client.create_ticket_async(input=CreateTicketRequest()) + return await client.create_ticket(input=model_instance(CreateTicketRequest)) if operation == "update_ticket": - return await client.update_ticket_async(input=UpdateTicketRequest(), ticket_id="1") + return await client.update_ticket(input=UpdateTicketRequest(), ticket_id="1") raise ValueError(f"Unsupported operation '{operation}'.") @@ -79,7 +83,7 @@ def test_init_with_custom_settings(self, mock_credential): client = FreshserviceClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -146,11 +150,13 @@ async def test_create_ticket_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_ticket_async(input=CreateTicketRequest()) + result = await client.create_ticket( + input=model_instance(CreateTicketRequest) + ) method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "POST" @@ -169,11 +175,11 @@ async def test_update_ticket_success_targets_resource(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.update_ticket_async(input=UpdateTicketRequest(), ticket_id="5") + result = await client.update_ticket(input=UpdateTicketRequest(), ticket_id="5") method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "PUT" @@ -192,11 +198,14 @@ async def test_add_note_success_targets_notes(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.add_note_async(input=AddNoteRequest(), ticket_id="7") + result = await client.add_note( + input=model_instance(AddNoteRequest), + ticket_id="7", + ) method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "POST" @@ -215,11 +224,13 @@ async def test_empty_response_body_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.create_ticket_async(input=CreateTicketRequest()) + result = await client.create_ticket( + input=model_instance(CreateTicketRequest) + ) assert result is None @@ -243,7 +254,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -292,7 +303,12 @@ def test_response_dataclasses_initialize_expected_defaults(self): assert get_origin(ListUsersResponse) is list def test_request_dataclasses_instantiate(self): - """Test generated request dataclasses instantiate without arguments.""" - assert CreateTicketRequest().email is None + """Test generated request dataclasses honor required and optional fields.""" + create_ticket = model_instance(CreateTicketRequest) + add_note = model_instance(AddNoteRequest) + + assert create_ticket.subject == "value" + assert create_ticket.email is None assert UpdateTicketRequest().priority is None - assert AddNoteRequest().body is None + assert add_note.body == "value" + assert add_note.private is None diff --git a/tests/test_ftp.py b/tests/test_ftp.py index 4f71f4e..959f197 100644 --- a/tests/test_ftp.py +++ b/tests/test_ftp.py @@ -6,53 +6,56 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.ftp import FtpClient from azure.connectors.ftp import ( BlobMetadata, BlobMetadataPage, - FtpClient, ) from azure.connectors.sdk import ( ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result async def _invoke_operation(client: FtpClient, operation: str): """Invoke an FTP operation by name for shared error tests.""" if operation == "create_file": - return await client.create_file_async( + return await client.create_file( input=b"file content", folder_path="/inbound", name="sample.txt", ) if operation == "get_file_metadata": - return await client.get_file_metadata_async(id="file123") + return await client.get_file_metadata(id="file123") if operation == "update_file": - return await client.update_file_async(input=b"updated content", id="file123") + return await client.update_file(input=b"updated content", id="file123") if operation == "delete_file": - return await client.delete_file_async(id="file123") + return await client.delete_file(id="file123") if operation == "copy_file": - return await client.copy_file_async( + return await client.copy_file( source="/inbound/sample.txt", destination="/archive/sample.txt", overwrite="true", ) if operation == "get_file_metadata_by_path": - return await client.get_file_metadata_by_path_async(path="/inbound/sample.txt") + return await client.get_file_metadata_by_path(path="/inbound/sample.txt") if operation == "get_file_content_by_path": - return await client.get_file_content_by_path_async(path="/inbound/sample.txt") + return await client.get_file_content_by_path(path="/inbound/sample.txt") if operation == "get_file_content": - return await client.get_file_content_async(id="file123") + return await client.get_file_content(id="file123") if operation == "list_folder": - return await client.list_folder_async(id="folder123") + return await resolve_generated_result(client.list_folder(id="folder123")) if operation == "list_root_folder": - return await client.list_root_folder_async() + return await resolve_generated_result(client.list_root_folder()) if operation == "extract_folder": - return await client.extract_folder_async( - source="/inbound/archive.zip", - destination="/expanded", - overwrite="true", - create_folders="true", + return await resolve_generated_result( + client.extract_folder( + source="/inbound/archive.zip", + destination="/expanded", + overwrite=True, + create_folders=True, + ) ) raise ValueError(f"Unsupported operation '{operation}'.") @@ -91,7 +94,7 @@ def test_init_with_custom_settings(self, mock_credential): client = FtpClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -149,7 +152,7 @@ class TestFtpClientMethods: @pytest.mark.asyncio async def test_create_file_success(self, mock_credential): - """Test create_file_async sends query parameters and body.""" + """Test create_file sends query parameters and body.""" client = FtpClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -158,11 +161,11 @@ async def test_create_file_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_file_async( + result = await client.create_file( input=b"file content", folder_path="/inbound", name="sample.txt", @@ -176,7 +179,7 @@ async def test_create_file_success(self, mock_credential): @pytest.mark.asyncio async def test_get_file_metadata_success(self, mock_credential): - """Test get_file_metadata_async returns parsed JSON.""" + """Test get_file_metadata returns parsed JSON.""" client = FtpClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -185,18 +188,18 @@ async def test_get_file_metadata_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_file_metadata_async(id="file123") + result = await client.get_file_metadata(id="file123") assert result["name"] == "sample.txt" assert "/datasets/default/files/file123" in mock_send.call_args[0][1] @pytest.mark.asyncio async def test_get_file_content_by_path_success(self, mock_credential): - """Test get_file_content_by_path_async returns bytes content.""" + """Test get_file_content_by_path returns bytes content.""" client = FtpClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -205,60 +208,62 @@ async def test_get_file_content_by_path_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.get_file_content_by_path_async(path="/inbound/sample.txt") + result = await client.get_file_content_by_path(path="/inbound/sample.txt") assert result == b"ftp file content" @pytest.mark.asyncio async def test_list_root_folder_success(self, mock_credential): - """Test list_root_folder_async returns parsed JSON response.""" + """Test list_root_folder returns parsed JSON response.""" client = FtpClient( "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"value":[{"name":"inbound"}]}') + mock_response = MockResponse(status=200, text='[{"name":"inbound"}]') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.list_root_folder_async() + result = await resolve_generated_result(client.list_root_folder()) - assert len(result["value"]) == 1 - assert result["value"][0]["name"] == "inbound" + assert len(result) == 1 + assert result[0]["name"] == "inbound" @pytest.mark.asyncio async def test_extract_folder_success(self, mock_credential): - """Test extract_folder_async serializes extraction query parameters.""" + """Test extract_folder serializes extraction query parameters.""" client = FtpClient( "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"status":"ok"}') + mock_response = MockResponse(status=200, text='[{"status":"ok"}]') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.extract_folder_async( - source="/inbound/archive.zip", - destination="/expanded", - overwrite="true", - create_folders="true", + result = await resolve_generated_result( + client.extract_folder( + source="/inbound/archive.zip", + destination="/expanded", + overwrite=True, + create_folders=True, + ) ) call_path = mock_send.call_args[0][1] assert "source=%2Finbound%2Farchive.zip" in call_path assert "destination=%2Fexpanded" in call_path - assert result["status"] == "ok" + assert result[0]["status"] == "ok" class TestFtpClientErrorHandling: @@ -295,7 +300,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): diff --git a/tests/test_generated_aio_catalog_contract.py b/tests/test_generated_aio_catalog_contract.py new file mode 100644 index 0000000..effc255 --- /dev/null +++ b/tests/test_generated_aio_catalog_contract.py @@ -0,0 +1,342 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Behavioral contract tests for the asynchronous generated catalog.""" + +from __future__ import annotations + +import importlib +import inspect +from pathlib import Path +from types import ModuleType +from typing import Any, get_args, get_origin, get_type_hints +from unittest.mock import AsyncMock, MagicMock, patch + +import pytest +from azure.core.async_paging import AsyncItemPaged +from azure.core.paging import ItemPaged +from azure.core.polling import AsyncLROPoller, LROPoller + +import azure.connectors as connectors_package +import azure.connectors.aio as aio_package +from azure.connectors.sdk import ConnectorClientBase as SyncConnectorClientBase +from azure.connectors.sdk.aio import ConnectorClientBase +from azure.connectors.sdk.exceptions import ConnectorException +from azure.connectors.sdk.serialization import to_wire +from tests.conftest import MockResponse +from tests.generated_connector_test_utils import ( + _representative_value, + generated_pager_response_text, + get_generated_operations, +) + + +assert connectors_package.__file__ is not None +AIO_MODULE_DIRECTORY = Path(connectors_package.__file__).parent / "aio" +CONNECTOR_MODULE_NAMES = [ + path.stem + for path in sorted(AIO_MODULE_DIRECTORY.glob("*.py")) + if path.name != "__init__.py" +] +REQUEST_CONTROL_PARAMETER_NAMES = { + "client_request_id", + "headers", + "response_hook", + "timeout", +} +SHARED_PACKAGE_EXPORT_NAMES = { + "ConnectorClientBase", + "ConnectorException", + "ConnectorHttpClient", + "ConnectorResponse", + "ConnectorResponseHook", + "ConnectorResponseSnapshot", + "TriggerCallbackBody", + "TriggerCallbackPayload", +} +NOT_FOUND_CONTRACT_OPERATIONS = [ + ("arm", "deployments_delete", "DELETE", True), + ("zohosign", "delete_document", "PUT", False), +] + + +def test_package_roots_export_generated_clients_lazily() -> None: + """Expose generated clients without importing their modules eagerly.""" + client_names = set(connectors_package.CLIENT_REGISTRY) + + assert SHARED_PACKAGE_EXPORT_NAMES <= set(connectors_package.__all__) + assert client_names <= set(connectors_package.__all__) + assert client_names <= set(aio_package.__all__) + assert client_names <= set(dir(connectors_package)) + assert client_names <= set(dir(aio_package)) + assert not (client_names & vars(connectors_package).keys()) + assert not (client_names & vars(aio_package).keys()) + + +def get_generated_client_type(connector_module: ModuleType) -> type[Any]: + """Return the asynchronous client type defined by a connector module.""" + client_types = [ + value + for value in vars(connector_module).values() + if inspect.isclass(value) + and issubclass(value, ConnectorClientBase) + and value is not ConnectorClientBase + and value.__module__ == connector_module.__name__ + ] + + assert len(client_types) == 1, connector_module.__name__ + return client_types[0] + + +async def invoke_generated_operation( + client: Any, + operation: str, + module: ModuleType, + *, + include_optional_parameters: bool = False, + request_controls: dict[str, Any] | None = None, +) -> Any: + """Invoke an asynchronous generated operation with representative values.""" + method = getattr(client, operation) + type_hints = get_type_hints(method, globalns=vars(module)) + arguments = { + parameter.name: _representative_value(type_hints[parameter.name]) + for parameter in inspect.signature(method).parameters.values() + if parameter.name not in REQUEST_CONTROL_PARAMETER_NAMES + and ( + include_optional_parameters + or parameter.default is inspect.Parameter.empty + ) + } + arguments.update(request_controls or {}) + result = method(**arguments) + if isinstance(result, AsyncItemPaged): + return [item async for item in result] + + awaited_result = await result + if isinstance(awaited_result, AsyncLROPoller): + return await awaited_result.result() + + return awaited_result + + +@pytest.mark.parametrize( + ( + "module_name", + "operation_name", + "expected_method", + "accepts_not_found", + ), + NOT_FOUND_CONTRACT_OPERATIONS, +) +@pytest.mark.asyncio +async def test_not_found_contract_follows_http_method( + module_name: str, + operation_name: str, + expected_method: str, + accepts_not_found: bool, + mock_credential: Any, +) -> None: + """Apply idempotent HTTP 404 handling only to DELETE requests.""" + connector_module = importlib.import_module( + f"azure.connectors.aio.{module_name}" + ) + client_type = get_generated_client_type(connector_module) + client = client_type( + "https://example.azure.com/connections/test", + credential=mock_credential, + ) + + with patch.object( + client._http_client, + "send", + new_callable=AsyncMock, + return_value=MockResponse(status=404, text="not found"), + ) as mock_send: + if accepts_not_found: + result = await invoke_generated_operation( + client, + operation_name, + connector_module, + ) + assert result is None + else: + with pytest.raises(ConnectorException): + await invoke_generated_operation( + client, + operation_name, + connector_module, + ) + + assert mock_send.call_args.args[0] == expected_method + + +@pytest.mark.parametrize("module_name", CONNECTOR_MODULE_NAMES) +def test_root_and_aio_operation_surfaces_match(module_name: str) -> None: + """Keep root and aio class, operation, and signature identities aligned.""" + root_module = importlib.import_module(f"azure.connectors.{module_name}") + aio_module = importlib.import_module(f"azure.connectors.aio.{module_name}") + root_client = next( + value + for value in vars(root_module).values() + if inspect.isclass(value) + and issubclass(value, SyncConnectorClientBase) + and value is not SyncConnectorClientBase + and value.__module__ == root_module.__name__ + ) + aio_client = get_generated_client_type(aio_module) + + assert aio_client.__name__ == root_client.__name__ + operation_names = get_generated_operations(root_client) + assert get_generated_operations(aio_client) == operation_names + assert not any(name.endswith("_async") for name in operation_names) + + for operation_name in operation_names: + root_method = getattr(root_client, operation_name) + aio_method = getattr(aio_client, operation_name) + root_signature = inspect.signature(root_method) + aio_signature = inspect.signature(aio_method) + assert list(root_signature.parameters.values()) == list( + aio_signature.parameters.values() + ), operation_name + + root_return_type = get_type_hints( + root_method, + globalns=vars(root_module), + )["return"] + aio_return_type = get_type_hints( + aio_method, + globalns=vars(aio_module), + )["return"] + is_pageable = get_origin(root_return_type) is ItemPaged + is_long_running = get_origin(root_return_type) is LROPoller + if is_pageable: + assert get_origin(aio_return_type) is AsyncItemPaged, operation_name + assert get_args(aio_return_type) == get_args( + root_return_type + ), operation_name + elif is_long_running: + assert get_origin(aio_return_type) is AsyncLROPoller, operation_name + assert get_args(aio_return_type) == get_args( + root_return_type + ), operation_name + else: + assert aio_return_type == root_return_type, operation_name + + assert not inspect.iscoroutinefunction(root_method), operation_name + assert inspect.iscoroutinefunction(aio_method) == ( + not is_pageable + ), operation_name + + +@pytest.mark.parametrize("module_name", CONNECTOR_MODULE_NAMES) +@pytest.mark.asyncio +async def test_all_aio_operations_succeed_with_request_controls( + module_name: str, + mock_credential: Any, +) -> None: + """Exercise every asynchronous operation's successful request contract.""" + connector_module = importlib.import_module( + f"azure.connectors.aio.{module_name}" + ) + client_type = get_generated_client_type(connector_module) + + for operation in sorted(get_generated_operations(client_type)): + client = client_type( + "https://example.azure.com/connections/test", + credential=mock_credential, + ) + generated_method = getattr(client, operation) + return_type = get_type_hints( + generated_method, + globalns=vars(connector_module), + )["return"] + is_pageable = get_origin(return_type) is AsyncItemPaged + result_type = ( + get_args(return_type)[0] + if get_origin(return_type) is AsyncLROPoller + else return_type + ) + response_text = '{"ok": true}' + if is_pageable: + response_text = generated_pager_response_text(generated_method) + response_hook = MagicMock() + + with patch.object( + client._http_client, + "send", + new_callable=AsyncMock, + return_value=MockResponse(status=200, text=response_text), + ) as mock_send: + result = await invoke_generated_operation( + client, + operation, + connector_module, + include_optional_parameters=True, + request_controls={ + "timeout": 5.0, + "headers": {"x-test": "value"}, + "client_request_id": "request-id", + "response_hook": response_hook, + }, + ) + + assert mock_send.call_count >= 1, operation + for call in mock_send.call_args_list: + method, request_url = call.args[:2] + assert method, operation + assert request_url.startswith( + "https://example.azure.com/connections/test/" + ), operation + assert "{" not in request_url and "}" not in request_url, operation + assert call.kwargs["timeout"] == 5.0, operation + expected_headers = {"x-test": "value"} + if "match_condition" in inspect.signature(generated_method).parameters: + expected_headers["If-Match"] = "*" + assert call.kwargs["headers"] == expected_headers, operation + assert call.kwargs["client_request_id"] == "request-id", operation + assert call.kwargs["response_hook"] is response_hook, operation + body = call.kwargs["body"] + if body is not None: + assert to_wire(body) is not None, operation + + if result_type is type(None): + assert result is None, operation + elif is_pageable: + assert result == [{"ok": True}], operation + elif result_type is bytes: + assert result == b'{"ok": true}', operation + else: + assert result == {"ok": True}, operation + + +@pytest.mark.parametrize("module_name", CONNECTOR_MODULE_NAMES) +@pytest.mark.asyncio +async def test_all_aio_operations_reject_error_responses( + module_name: str, + mock_credential: Any, +) -> None: + """Verify every asynchronous operation raises for an error response.""" + connector_module = importlib.import_module( + f"azure.connectors.aio.{module_name}" + ) + client_type = get_generated_client_type(connector_module) + + for operation in sorted(get_generated_operations(client_type)): + client = client_type( + "https://example.azure.com/connections/test", + credential=mock_credential, + ) + + with patch.object( + client._http_client, + "send", + new_callable=AsyncMock, + return_value=MockResponse(status=400, text="bad request"), + ): + with pytest.raises(ConnectorException): + await invoke_generated_operation( + client, + operation, + connector_module, + include_optional_parameters=True, + ) diff --git a/tests/test_generated_catalog_contract.py b/tests/test_generated_catalog_contract.py index a07966f..69feb3b 100644 --- a/tests/test_generated_catalog_contract.py +++ b/tests/test_generated_catalog_contract.py @@ -8,18 +8,22 @@ import inspect from pathlib import Path from types import ModuleType -from typing import Any, get_type_hints -from unittest.mock import AsyncMock, MagicMock, patch +from typing import Any, get_args, get_origin, get_type_hints +from unittest.mock import MagicMock, patch import pytest +from azure.core.credentials import AzureKeyCredential +from azure.core.paging import ItemPaged +from azure.core.polling import LROPoller import azure.connectors as connectors_package from azure.connectors.sdk import ConnectorClientBase, ConnectorException from azure.connectors.sdk.serialization import to_wire from tests.conftest import MockResponse from tests.generated_connector_test_utils import ( + generated_pager_response_text, get_generated_operations, - invoke_generated_operation, + invoke_sync_generated_operation, ) @@ -27,7 +31,43 @@ CONNECTOR_MODULE_NAMES = [ path.stem for path in sorted(Path(connectors_package.__file__).parent.glob("*.py")) - if path.name != "__init__.py" + if not path.name.startswith("_") +] + +PRIMITIVE_STRING_PAGER_OPERATIONS = [ + ("azuread", "list_member_groups"), + ("eventhubs", "list_consumer_groups"), + ("eventhubs", "list_content_types"), + ("eventhubs", "list_event_hubs"), + ("eventhubs", "list_partition_keys"), + ("meetingroommap", "list_categories"), + ("msgraphgroupsanduser", "list_member_groups"), + ("onedrive", "list_file_tags"), + ("servicebus", "list_queues"), + ("servicebus", "list_session_options"), + ("servicebus", "list_subscriptions"), + ("servicebus", "list_system_properties"), + ("servicebus", "list_topics"), +] + +EAGER_MUTATION_OPERATIONS = [ + ("azuread", "check_member_groups"), + ("docusign", "add_recipient_tabs"), + ("mq", "delete_all"), + ("mq", "read_all"), + ("mq", "receive_all"), + ("onedrive", "add_file_tag"), + ("powerbi", "execute_dataset_query"), + ("replicon", "bulk_get_project_details3"), + ("replicon", "bulk_get_time_entered_summary"), + ("replicon", "create_task_hierarchy_or_apply_modifications"), + ("sendgrid", "add_global_suppression"), + ("yammer", "post_message"), +] + +NOT_FOUND_CONTRACT_OPERATIONS = [ + ("arm", "deployments_delete", "DELETE", True), + ("zohosign", "delete_document", "PUT", False), ] @@ -46,11 +86,95 @@ def get_generated_client_type(connector_module: ModuleType) -> type[Any]: return client_types[0] +@pytest.mark.parametrize( + ("module_name", "operation_name"), + PRIMITIVE_STRING_PAGER_OPERATIONS, +) +def test_primitive_string_collections_use_typed_pagers( + module_name: str, + operation_name: str, +) -> None: + """Preserve primitive item types in generated pager annotations.""" + connector_module = importlib.import_module(f"azure.connectors.{module_name}") + client_type = get_generated_client_type(connector_module) + return_type = get_type_hints( + getattr(client_type, operation_name), + globalns=vars(connector_module), + )["return"] + + assert get_origin(return_type) is ItemPaged + assert get_args(return_type) == (str,) + + +@pytest.mark.parametrize( + ("module_name", "operation_name"), + EAGER_MUTATION_OPERATIONS, +) +def test_mutation_collection_responses_remain_eager( + module_name: str, + operation_name: str, +) -> None: + """Keep bounded mutation responses out of the lazy paging contract.""" + connector_module = importlib.import_module(f"azure.connectors.{module_name}") + client_type = get_generated_client_type(connector_module) + return_type = get_type_hints( + getattr(client_type, operation_name), + globalns=vars(connector_module), + )["return"] + + assert get_origin(return_type) is not ItemPaged + + +@pytest.mark.parametrize( + ( + "module_name", + "operation_name", + "expected_method", + "accepts_not_found", + ), + NOT_FOUND_CONTRACT_OPERATIONS, +) +def test_not_found_contract_follows_http_method( + module_name: str, + operation_name: str, + expected_method: str, + accepts_not_found: bool, +) -> None: + """Apply idempotent HTTP 404 handling only to DELETE requests.""" + connector_module = importlib.import_module(f"azure.connectors.{module_name}") + client_type = get_generated_client_type(connector_module) + client = client_type( + "https://example.azure.com/connections/test", + credential=AzureKeyCredential("test-key"), + ) + + with patch.object( + client._http_client, + "send", + new_callable=MagicMock, + return_value=MockResponse(status=404, text="not found"), + ) as mock_send: + if accepts_not_found: + result = invoke_sync_generated_operation( + client, + operation_name, + connector_module, + ) + assert result is None + else: + with pytest.raises(ConnectorException): + invoke_sync_generated_operation( + client, + operation_name, + connector_module, + ) + + assert mock_send.call_args.args[0] == expected_method + + @pytest.mark.parametrize("module_name", CONNECTOR_MODULE_NAMES) -@pytest.mark.asyncio -async def test_all_generated_operations_succeed_with_request_controls( +def test_all_generated_operations_succeed_with_request_controls( module_name: str, - mock_credential: Any, ) -> None: """Exercise every generated operation's successful request contract.""" connector_module = importlib.import_module(f"azure.connectors.{module_name}") @@ -59,22 +183,31 @@ async def test_all_generated_operations_succeed_with_request_controls( for operation in sorted(get_generated_operations(client_type)): client = client_type( "https://example.azure.com/connections/test", - credential=mock_credential, + credential=AzureKeyCredential("test-key"), ) - generated_method = getattr(client, f"{operation}_async") - is_pageable = inspect.isasyncgenfunction(generated_method) - response_text = ( - '{"value": [{"ok": true}]}' if is_pageable else '{"ok": true}' + generated_method = getattr(client, operation) + return_type = get_type_hints( + generated_method, + globalns=vars(connector_module), + )["return"] + is_pageable = get_origin(return_type) is ItemPaged + result_type = ( + get_args(return_type)[0] + if get_origin(return_type) is LROPoller + else return_type ) + response_text = '{"ok": true}' + if is_pageable: + response_text = generated_pager_response_text(generated_method) response_hook = MagicMock() with patch.object( client._http_client, - "send_async", - new_callable=AsyncMock, + "send", + new_callable=MagicMock, return_value=MockResponse(status=200, text=response_text), ) as mock_send: - result = await invoke_generated_operation( + result = invoke_sync_generated_operation( client, operation, connector_module, @@ -96,33 +229,30 @@ async def test_all_generated_operations_succeed_with_request_controls( ), operation assert "{" not in request_url and "}" not in request_url, operation assert call.kwargs["timeout"] == 5.0, operation - assert call.kwargs["headers"] == {"x-test": "value"}, operation + expected_headers = {"x-test": "value"} + if "match_condition" in inspect.signature(generated_method).parameters: + expected_headers["If-Match"] = "*" + assert call.kwargs["headers"] == expected_headers, operation assert call.kwargs["client_request_id"] == "request-id", operation assert call.kwargs["response_hook"] is response_hook, operation body = call.kwargs["body"] if body is not None: - assert to_wire(body), operation + assert to_wire(body) is not None, operation - return_type = get_type_hints( - generated_method, - globalns=vars(connector_module), - )["return"] - if return_type is type(None): + if result_type is type(None): assert result is None, operation elif is_pageable: assert result == [{"ok": True}], operation - elif return_type is bytes: + elif result_type is bytes: assert result == b'{"ok": true}', operation else: assert result == {"ok": True}, operation @pytest.mark.parametrize("module_name", CONNECTOR_MODULE_NAMES) -@pytest.mark.asyncio -async def test_all_generated_operations_reject_error_responses( +def test_all_generated_operations_reject_error_responses( module_name: str, - mock_credential: Any, ) -> None: """Verify every generated operation raises for a non-success response.""" connector_module = importlib.import_module(f"azure.connectors.{module_name}") @@ -131,17 +261,17 @@ async def test_all_generated_operations_reject_error_responses( for operation in sorted(get_generated_operations(client_type)): client = client_type( "https://example.azure.com/connections/test", - credential=mock_credential, + credential=AzureKeyCredential("test-key"), ) with patch.object( client._http_client, - "send_async", - new_callable=AsyncMock, + "send", + new_callable=MagicMock, return_value=MockResponse(status=400, text="bad request"), ): with pytest.raises(ConnectorException): - await invoke_generated_operation( + invoke_sync_generated_operation( client, operation, connector_module, diff --git a/tests/test_generated_lro_catalog_contract.py b/tests/test_generated_lro_catalog_contract.py new file mode 100644 index 0000000..2607e75 --- /dev/null +++ b/tests/test_generated_lro_catalog_contract.py @@ -0,0 +1,186 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Catalog-wide contract tests for generated long-running operations.""" + +from __future__ import annotations + +import ast +import importlib +import inspect +from pathlib import Path +from types import ModuleType +from typing import Any, get_args, get_origin, get_type_hints + +from azure.core.polling import AsyncLROPoller, LROPoller + +import azure.connectors as connectors_package +from azure.connectors.sdk import ConnectorClientBase as SyncConnectorClientBase +from azure.connectors.sdk.aio import ConnectorClientBase as AioConnectorClientBase + + +EXPECTED_LRO_OPERATIONS = { + "kusto": { + "begin_list_kusto_results", + "begin_list_kusto_show_command_results", + "begin_run_async_control_command_and_wait", + "begin_run_kusto_command_and_visualize_results", + "begin_run_kusto_query_and_visualize_results", + }, + "plumsail": { + "begin_flow_v1_documents_jobs_add_watermark_to_pdf", + "begin_flow_v1_documents_jobs_any2_pdf_v2", + "begin_flow_v1_documents_jobs_apply_docx", + "begin_flow_v1_documents_jobs_apply_docx_template", + "begin_flow_v1_documents_jobs_apply_html", + "begin_flow_v1_documents_jobs_apply_pptx", + "begin_flow_v1_documents_jobs_apply_xlsx_template", + "begin_flow_v1_documents_jobs_compress_pdf", + "begin_flow_v1_documents_jobs_create_archive", + "begin_flow_v1_documents_jobs_csv2_xlsx", + "begin_flow_v1_documents_jobs_doc2_docx", + "begin_flow_v1_documents_jobs_docx2_pdf", + "begin_flow_v1_documents_jobs_email2_pdf", + "begin_flow_v1_documents_jobs_extract_archive", + "begin_flow_v1_documents_jobs_extract_text_from_pdf", + "begin_flow_v1_documents_jobs_fill_in_pdf_form", + "begin_flow_v1_documents_jobs_get_pdf_form", + "begin_flow_v1_documents_jobs_get_pdf_protection_info", + "begin_flow_v1_documents_jobs_html2_docx", + "begin_flow_v1_documents_jobs_html2_pdf", + "begin_flow_v1_documents_jobs_image2_pdf", + "begin_flow_v1_documents_jobs_json2_csv", + "begin_flow_v1_documents_jobs_json2_xlsx", + "begin_flow_v1_documents_jobs_merge_any_to_pdf_v2", + "begin_flow_v1_documents_jobs_merge_docx", + "begin_flow_v1_documents_jobs_merge_xlsx", + "begin_flow_v1_documents_jobs_parse_csv", + "begin_flow_v1_documents_jobs_pdf2_image_v2", + "begin_flow_v1_documents_jobs_ppt2_pptx", + "begin_flow_v1_documents_jobs_pptx2_pdf", + "begin_flow_v1_documents_jobs_protect_pdf", + "begin_flow_v1_documents_jobs_reg_exp_match", + "begin_flow_v1_documents_jobs_reg_exp_replace", + "begin_flow_v1_documents_jobs_reg_exp_test", + "begin_flow_v1_documents_jobs_split_pdf_v2", + "begin_flow_v1_documents_jobs_xls2_xlsx", + "begin_flow_v1_documents_jobs_xslx2_pdf", + "begin_flow_v1_processes_flow_jobs_execute_process", + "begin_flow_v1_processes_flow_jobs_execute_process_with_generated_data", + }, +} + + +assert connectors_package.__file__ is not None +CONNECTOR_DIRECTORY = Path(connectors_package.__file__).parent +CONNECTOR_MODULE_NAMES = sorted( + path.stem + for path in CONNECTOR_DIRECTORY.glob("*.py") + if path.name != "__init__.py" and not path.name.startswith("_") +) + + +def get_generated_client_type( + module: ModuleType, + base_type: type[Any], +) -> type[Any]: + """Return the generated client declared by a connector module.""" + client_types = [ + value + for value in vars(module).values() + if inspect.isclass(value) + and issubclass(value, base_type) + and value is not base_type + and value.__module__ == module.__name__ + ] + assert len(client_types) == 1, module.__name__ + return client_types[0] + + +def get_lro_operations(client_type: type[Any]) -> set[str]: + """Return generated begin methods declared by a connector client.""" + return { + name + for name, member in vars(client_type).items() + if name.startswith("begin_") and callable(member) + } + + +def test_generated_lro_inventory_and_sync_aio_parity() -> None: + """Keep the retained 44-operation LRO surface exact across all 99 pairs.""" + assert len(CONNECTOR_MODULE_NAMES) == 99 + + for module_name in CONNECTOR_MODULE_NAMES: + root_module = importlib.import_module(f"azure.connectors.{module_name}") + aio_module = importlib.import_module(f"azure.connectors.aio.{module_name}") + root_client = get_generated_client_type( + root_module, + SyncConnectorClientBase, + ) + aio_client = get_generated_client_type( + aio_module, + AioConnectorClientBase, + ) + expected_operations = EXPECTED_LRO_OPERATIONS.get(module_name, set()) + + assert get_lro_operations(root_client) == expected_operations, module_name + assert get_lro_operations(aio_client) == expected_operations, module_name + + for operation_name in expected_operations: + root_method = getattr(root_client, operation_name) + aio_method = getattr(aio_client, operation_name) + root_return = get_type_hints( + root_method, + globalns=vars(root_module), + )["return"] + aio_return = get_type_hints( + aio_method, + globalns=vars(aio_module), + )["return"] + + assert get_origin(root_return) is LROPoller, operation_name + assert get_origin(aio_return) is AsyncLROPoller, operation_name + assert get_args(root_return) == get_args(aio_return), operation_name + assert not inspect.iscoroutinefunction(root_method), operation_name + assert inspect.iscoroutinefunction(aio_method), operation_name + + assert sum(map(len, EXPECTED_LRO_OPERATIONS.values())) == 44 + + +def test_generated_lro_operations_use_only_location_polling() -> None: + """Require every retained poller to use the supported Location protocol.""" + for module_name, expected_operations in EXPECTED_LRO_OPERATIONS.items(): + for package_directory in ( + CONNECTOR_DIRECTORY, + CONNECTOR_DIRECTORY / "aio", + ): + tree = ast.parse( + (package_directory / f"{module_name}.py").read_text( + encoding="utf-8" + ) + ) + actual_headers = {} + for node in ast.walk(tree): + if not isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): + continue + if node.name not in expected_operations: + continue + for child in ast.walk(node): + if not isinstance(child, ast.Call): + continue + if not isinstance(child.func, ast.Name): + continue + if child.func.id != "ConnectorPollingMethod": + continue + header_keyword = next( + keyword + for keyword in child.keywords + if keyword.arg == "polling_header_name" + ) + assert isinstance(header_keyword.value, ast.Constant) + actual_headers[node.name] = header_keyword.value.value + + assert set(actual_headers) == expected_operations + assert all( + isinstance(header, str) and header.casefold() == "location" + for header in actual_headers.values() + ) diff --git a/tests/test_generation_manifest.py b/tests/test_generation_manifest.py new file mode 100644 index 0000000..288141c --- /dev/null +++ b/tests/test_generation_manifest.py @@ -0,0 +1,170 @@ +# ------------------------------------------------------------ +# Copyright (c) Microsoft Corporation. All rights reserved. +# ------------------------------------------------------------ + +"""Tests for generated connector provenance.""" + +from __future__ import annotations + +import ast +import hashlib +import json +from pathlib import Path +from typing import Any + +from azure.connectors._client_registry import CLIENT_REGISTRY + + +REPOSITORY_ROOT = Path(__file__).resolve().parent.parent +MANIFEST_PATH = REPOSITORY_ROOT / "generation.manifest.json" +CONNECTOR_DIRECTORY = REPOSITORY_ROOT / "src" / "azure" / "connectors" +ASYNC_CONNECTOR_DIRECTORY = CONNECTOR_DIRECTORY / "aio" +EXPECTED_GENERATOR_REVISION = "b9c9fd25aeeefb309e17054b9bd0697f9b6d4f41" + + +def canonical_sha256(path: Path) -> str: + """Return the SHA-256 of UTF-8 text with canonical LF line endings.""" + text = path.read_text(encoding="utf-8").replace("\r\n", "\n").replace("\r", "\n") + return hashlib.sha256(text.encode("utf-8")).hexdigest() + + +def load_manifest() -> dict[str, Any]: + """Load the generation manifest.""" + return json.loads(MANIFEST_PATH.read_text(encoding="utf-8")) + + +def generated_client_name(path: Path) -> str: + """Return the generated client class declared by a connector module.""" + tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path)) + client_names = [ + node.name + for node in tree.body + if isinstance(node, ast.ClassDef) + and any( + isinstance(base, ast.Name) and base.id == "ConnectorClientBase" + for base in node.bases + ) + ] + assert len(client_names) == 1, path + return client_names[0] + + +def stub_client_names(path: Path) -> set[str]: + """Return connector client names imported by a package type stub.""" + tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path)) + return { + alias.asname + for node in tree.body + if isinstance(node, ast.ImportFrom) + and node.module is not None + and not node.module.startswith("sdk.") + for alias in node.names + if alias.asname is not None and alias.asname.endswith("Client") + } + + +def test_generation_manifest_covers_exact_connector_inventory() -> None: + """Verify every generated sync and aio module has one manifest entry.""" + manifest = load_manifest() + manifest_names = [entry["apiName"] for entry in manifest["connectors"]] + connector_names = sorted( + path.stem + for path in CONNECTOR_DIRECTORY.glob("*.py") + if not path.name.startswith("_") + ) + async_connector_names = sorted( + path.stem + for path in ASYNC_CONNECTOR_DIRECTORY.glob("*.py") + if path.name != "__init__.py" + ) + assert manifest["manifestVersion"] == 1 + assert manifest["generator"]["revision"] == EXPECTED_GENERATOR_REVISION + assert manifest_names == sorted(manifest_names) + assert manifest_names == connector_names + assert manifest_names == async_connector_names + + +def test_generation_manifest_hashes_match_committed_files() -> None: + """Verify generated output hashes match the manifest.""" + manifest = load_manifest() + + for entry in manifest["connectors"]: + assert canonical_sha256( + REPOSITORY_ROOT / entry["outputFile"] + ) == entry["outputSha256"] + assert canonical_sha256( + REPOSITORY_ROOT / entry["asyncOutputFile"] + ) == entry["asyncOutputSha256"] + + for artifact in manifest["packageArtifacts"].values(): + assert canonical_sha256( + REPOSITORY_ROOT / artifact["path"] + ) == artifact["sha256"] + + +def test_generated_registry_and_type_stubs_cover_every_client() -> None: + """Keep runtime and static package exports aligned with generated clients.""" + expected_registry = { + generated_client_name(path): path.stem + for path in sorted(CONNECTOR_DIRECTORY.glob("*.py")) + if not path.name.startswith("_") + } + expected_client_names = set(expected_registry) + + assert CLIENT_REGISTRY == expected_registry + assert stub_client_names(CONNECTOR_DIRECTORY / "__init__.pyi") == expected_client_names + assert stub_client_names( + ASYNC_CONNECTOR_DIRECTORY / "__init__.pyi" + ) == expected_client_names + + +def test_generated_operations_have_structured_docstrings() -> None: + """Require structured public API documentation in both client surfaces.""" + operation_count = 0 + violations: list[str] = [] + connector_paths = [ + *CONNECTOR_DIRECTORY.glob("*.py"), + *ASYNC_CONNECTOR_DIRECTORY.glob("*.py"), + ] + + for path in connector_paths: + if path.name.startswith("_"): + continue + + tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path)) + for client in ( + node + for node in tree.body + if isinstance(node, ast.ClassDef) + and any( + isinstance(base, ast.Name) and base.id == "ConnectorClientBase" + for base in node.bases + ) + ): + for method in ( + node + for node in client.body + if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) + and not node.name.startswith("_") + and any( + isinstance(descendant, ast.Call) + and isinstance(descendant.func, ast.Attribute) + and descendant.func.attr == "send" + for descendant in ast.walk(node) + ) + ): + operation_count += 1 + docstring = ast.get_docstring(method) or "" + if not all( + section in docstring + for section in ("Args:", "Returns:", "Raises:") + ): + violations.append( + f"{path.relative_to(REPOSITORY_ROOT).as_posix()}:" + f"{method.lineno}: {method.name}" + ) + + assert operation_count > 0 + assert not violations, "Generated operations missing structured docs:\n" + "\n".join( + violations + ) diff --git a/tests/test_github.py b/tests/test_github.py index 04826cb..10597e2 100644 --- a/tests/test_github.py +++ b/tests/test_github.py @@ -7,9 +7,9 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.github import GithubClient from azure.connectors.github import ( CreateRepositorySecretRequest, - GithubClient, IssueBasicDetailsModel, PullRequestUpdateRequest, QueryRequest, @@ -19,6 +19,7 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestGithubClientInitialization: @@ -54,7 +55,7 @@ def test_init_with_custom_settings(self, mock_credential): client = GithubClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -122,11 +123,11 @@ async def test_success_uses_acronym_aware_name(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.invoke_mcp_server_async(input=payload) + await client.invoke_mcp_server(input=payload) mock_send.assert_called_once_with( "POST", @@ -150,12 +151,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.invoke_mcp_server_async(input=QueryRequest()) + await client.invoke_mcp_server(input=QueryRequest()) class TestGetUserAsync: @@ -175,11 +176,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_user_async() + result = await client.get_user() mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -202,12 +203,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.get_user_async() + await client.get_user() class TestCreateIssueAsync: @@ -231,11 +232,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_issue_async( + result = await client.create_issue( input=payload, repository_owner="octocat", repository_name="hello-world", @@ -265,20 +266,20 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.create_issue_async( + await client.create_issue( input=payload, repository_owner="octocat", repository_name="hello-world", ) -class TestGetIssuesAsync: - """Tests for get_issues_async method.""" +class TestListIssuesAsync: + """Tests for list_issues method.""" @pytest.mark.asyncio async def test_success(self, mock_credential): @@ -294,15 +295,17 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_issues_async( - repository_owner="octocat", - repository_name="hello-world", - state="open", - per_page="10", + result = await resolve_generated_result( + client.list_issues( + repository_owner="octocat", + repository_name="hello-world", + state="open", + per_page=10, + ) ) mock_send.assert_called_once() @@ -328,14 +331,16 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.get_issues_async( - repository_owner="octocat", - repository_name="hello-world", + await resolve_generated_result( + client.list_issues( + repository_owner="octocat", + repository_name="hello-world", + ) ) @@ -357,11 +362,11 @@ async def test_success_sends_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_update_repository_secret_async( + result = await client.create_update_repository_secret( input=payload, repository_owner="octocat", repository_name="hello world", @@ -395,12 +400,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.create_update_repository_secret_async( + await client.create_update_repository_secret( input=payload, repository_owner="octocat", repository_name="hello-world", @@ -428,11 +433,11 @@ async def test_success_sends_body_and_returns_result(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.update_pull_request_async( + result = await client.update_pull_request( input=payload, repository_owner="octocat", repository_name="hello-world", @@ -462,12 +467,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.update_pull_request_async( + await client.update_pull_request( input=payload, repository_owner="octocat", repository_name="hello-world", @@ -490,11 +495,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.remove_reviewers_pull_request_async( + await client.remove_reviewers_pull_request( input=payload, repository_owner="octocat", repository_name="hello-world", @@ -513,16 +518,16 @@ async def test_error_response_raises_exception(self, mock_credential): credential=mock_credential, ) payload = RequestReviewersBody(reviewers=["alice"]) - mock_response = MockResponse(status=404, text='{"message": "Not Found"}') + mock_response = MockResponse(status=500, text='{"message": "Server error"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.remove_reviewers_pull_request_async( + await client.remove_reviewers_pull_request( input=payload, repository_owner="octocat", repository_name="missing-repo", diff --git a/tests/test_googlecalendar.py b/tests/test_googlecalendar.py index 484700e..5b2f46a 100644 --- a/tests/test_googlecalendar.py +++ b/tests/test_googlecalendar.py @@ -8,12 +8,12 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.googlecalendar import GooglecalendarClient from azure.connectors.googlecalendar import ( CalendarEventChangedList, CalendarEventList, CalendarList, CalendarListEntry, - GooglecalendarClient, ObjectEntity, PatchEvent, RequestEvent, @@ -25,36 +25,45 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import ( + generated_pager_response_text, + model_instance, + resolve_generated_result, +) async def _invoke_operation(client: GooglecalendarClient, operation: str): """Invoke a Google Calendar operation by name for shared tests.""" if operation == "list_calendars": - return await client.list_calendars_async(min_access_role="reader") + return await resolve_generated_result( + client.list_calendars(min_access_role="reader") + ) if operation == "list_events": - return await client.list_events_async( - calendar_id="cal123", - time_min="2026-01-01T00:00:00Z", - time_max="2026-01-31T23:59:59Z", - q="planning", + return await resolve_generated_result( + client.list_events( + calendar_id="cal123", + time_min="2026-01-01T00:00:00Z", + time_max="2026-01-31T23:59:59Z", + q="planning", + ) ) if operation == "create_event": - return await client.create_event_async( - input=RequestEvent(), + return await client.create_event( + input=model_instance(RequestEvent), calendar_id="cal123", ) if operation == "get_event": - return await client.get_event_async(calendar_id="cal123", event_id="evt123") + return await client.get_event(calendar_id="cal123", event_id="evt123") if operation == "delete_event": - return await client.delete_event_async(calendar_id="cal123", event_id="evt123") + return await client.delete_event(calendar_id="cal123", event_id="evt123") if operation == "update_event": - return await client.update_event_async( + return await client.update_event( input=PatchEvent(), calendar_id="cal123", event_id="evt123", ) if operation == "list_writable_calendars": - return await client.list_writable_calendars_async() + return await resolve_generated_result(client.list_writable_calendars()) raise ValueError(f"Unsupported operation '{operation}'.") @@ -92,7 +101,7 @@ def test_init_with_custom_settings(self, mock_credential): client = GooglecalendarClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -159,17 +168,22 @@ async def test_list_calendars_success(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"items":[{"id":"cal1"}]}') + mock_response = MockResponse( + status=200, + text=generated_pager_response_text(client.list_calendars), + ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_calendars_async(min_access_role="reader") + result = await resolve_generated_result( + client.list_calendars(min_access_role="reader") + ) - assert len(result["items"]) == 1 + assert result == [{"ok": True}] call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/users/me/calendarList" in call_args[0][1] @@ -182,22 +196,27 @@ async def test_list_events_success(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"items": []}') + mock_response = MockResponse( + status=200, + text=generated_pager_response_text(client.list_events), + ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_events_async( - calendar_id="cal123", - time_min="2026-01-01T00:00:00Z", - time_max="2026-01-31T23:59:59Z", - q="planning", + result = await resolve_generated_result( + client.list_events( + calendar_id="cal123", + time_min="2026-01-01T00:00:00Z", + time_max="2026-01-31T23:59:59Z", + q="planning", + ) ) - assert result["items"] == [] + assert result == [{"ok": True}] call_args = mock_send.call_args assert "/calendars/cal123/events" in call_args[0][1] assert "timeMin=2026-01-01T00%3A00%3A00Z" in call_args[0][1] @@ -215,12 +234,12 @@ async def test_create_event_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_event_async( - input=RequestEvent(summary="Standup"), + result = await client.create_event( + input=model_instance(RequestEvent, summary="Standup"), calendar_id="cal123", ) @@ -236,19 +255,25 @@ async def test_list_writable_calendars_success(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"items": []}') + mock_response = MockResponse( + status=200, + text=generated_pager_response_text(client.list_writable_calendars), + ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.list_writable_calendars_async() + result = await resolve_generated_result( + client.list_writable_calendars() + ) call_args = mock_send.call_args assert "/users/me/calendarList/1" in call_args[0][1] assert "minAccessRole=writer" in call_args[0][1] + assert result == [{"ok": True}] class TestGooglecalendarClientErrorHandling: @@ -281,7 +306,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -297,13 +322,13 @@ class TestGooglecalendarApiSurface: def test_callable_method_signatures(self): """Test the client exposes exactly the generated callable methods.""" expected_signatures = { - "create_event_async": ("self", "input", "calendar_id"), - "delete_event_async": ("self", "calendar_id", "event_id"), - "get_event_async": ("self", "calendar_id", "event_id"), - "list_calendars_async": ("self", "min_access_role"), - "list_events_async": ("self", "calendar_id", "time_min", "time_max", "q"), - "list_writable_calendars_async": ("self",), - "update_event_async": ("self", "input", "calendar_id", "event_id"), + "create_event": ("self", "input", "calendar_id"), + "delete_event": ("self", "calendar_id", "event_id"), + "get_event": ("self", "calendar_id", "event_id"), + "list_calendars": ("self", "min_access_role"), + "list_events": ("self", "calendar_id", "time_min", "time_max", "q"), + "list_writable_calendars": ("self",), + "update_event": ("self", "input", "calendar_id", "event_id"), } request_control_parameters = ( "timeout", @@ -318,10 +343,9 @@ def test_callable_method_signatures(self): actual_signatures = { name: tuple(inspect.signature(method).parameters) for name, method in vars(GooglecalendarClient).items() - if ( - inspect.iscoroutinefunction(method) - or inspect.isasyncgenfunction(method) - ) + if not name.startswith("_") + and name != "close" + and callable(method) } assert actual_signatures == expected_signatures @@ -378,7 +402,7 @@ def test_dataclass_instances_initialize_expected_defaults(self): object_entity = ObjectEntity() changed_list = CalendarEventChangedList() calendar_entry = CalendarListEntry() - request_event = RequestEvent() + request_event = model_instance(RequestEvent) patch_event = PatchEvent() changed_event = ResponseEventWithActionType() diff --git a/tests/test_googledrive.py b/tests/test_googledrive.py index e653727..7385bd6 100644 --- a/tests/test_googledrive.py +++ b/tests/test_googledrive.py @@ -6,9 +6,9 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.googledrive import GoogledriveClient from azure.connectors.googledrive import ( BlobMetadata, - GoogledriveClient, Table, TableMetadata, TablesList, @@ -17,41 +17,44 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result async def _invoke_operation(client: GoogledriveClient, operation: str): """Invoke a Google Drive operation by name for shared parameterized tests.""" if operation == "get_file_metadata": - return await client.get_file_metadata_async(id="file123") + return await client.get_file_metadata(id="file123") if operation == "update_file": - return await client.update_file_async(input=b"updated content", id="file123") + return await client.update_file(input=b"updated content", id="file123") if operation == "delete_file": - return await client.delete_file_async(id="file123") + return await client.delete_file(id="file123") if operation == "get_file_metadata_by_path": - return await client.get_file_metadata_by_path_async(path="/Documents/file.txt") + return await client.get_file_metadata_by_path(path="/Documents/file.txt") if operation == "get_file_content_by_path": - return await client.get_file_content_by_path_async(path="/Documents/file.txt") + return await client.get_file_content_by_path(path="/Documents/file.txt") if operation == "get_file_content": - return await client.get_file_content_async(id="file123") + return await client.get_file_content(id="file123") if operation == "create_file": - return await client.create_file_async( + return await client.create_file( input=b"file content", folder_id="folder123", name="created.txt", ) if operation == "copy_file": - return await client.copy_file_async( + return await client.copy_file( source="/Documents/source.txt", destination="/Documents/copy.txt", ) if operation == "list_folder": - return await client.list_folder_async(id="folder123") + return await resolve_generated_result(client.list_folder(id="folder123")) if operation == "list_root_folder": - return await client.list_root_folder_async() + return await resolve_generated_result(client.list_root_folder()) if operation == "extract_folder": - return await client.extract_folder_async( - source="/Documents/archive.zip", - destination="/Documents/extracted", + return await resolve_generated_result( + client.extract_folder( + source="/Documents/archive.zip", + destination="/Documents/extracted", + ) ) raise ValueError(f"Unsupported operation '{operation}'.") @@ -89,7 +92,7 @@ def test_init_with_custom_settings(self, mock_credential): client = GoogledriveClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -156,11 +159,11 @@ async def test_get_file_metadata_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_file_metadata_async(id="file123") + result = await client.get_file_metadata(id="file123") assert result["name"] == "doc.txt" call_args = mock_send.call_args @@ -178,11 +181,11 @@ async def test_get_file_content_by_path_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.get_file_content_by_path_async(path="/Documents/file.txt") + result = await client.get_file_content_by_path(path="/Documents/file.txt") assert result == b"google drive file content" @@ -197,11 +200,11 @@ async def test_create_file_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_file_async( + result = await client.create_file( input=b"file content", folder_id="folder123", name="created.txt", @@ -248,7 +251,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): diff --git a/tests/test_googletasks.py b/tests/test_googletasks.py index df034f5..b753d0d 100644 --- a/tests/test_googletasks.py +++ b/tests/test_googletasks.py @@ -6,8 +6,8 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.googletasks import GoogletasksClient from azure.connectors.googletasks import ( - GoogletasksClient, TRIGGER_OPERATIONS, TaskCreate, TaskList, @@ -20,23 +20,30 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import ( + generated_pager_response_text, + model_instance, + resolve_generated_result, +) async def _invoke_operation(client: GoogletasksClient, operation: str): """Invoke a Google Tasks operation by name for shared tests.""" if operation == "list_task_lists": - return await client.list_task_lists_async() + return await resolve_generated_result(client.list_task_lists()) if operation == "create_task_list": - return await client.create_task_list_async(input=TaskListCreate(title="Work")) + return await client.create_task_list(input=TaskListCreate(title="Work")) if operation == "list_tasks": - return await client.list_tasks_async(task_list_id="list123") + return await resolve_generated_result( + client.list_tasks(task_list_id="list123") + ) if operation == "create_task": - return await client.create_task_async( + return await client.create_task( input=TaskCreate(title="Buy milk"), task_list_id="list123", ) if operation == "list_task": - return await client.list_task_async(task_list_id="list123", task_id="task123") + return await client.list_task(task_list_id="list123", task_id="task123") raise ValueError(f"Unsupported operation '{operation}'.") @@ -73,7 +80,7 @@ def test_init_with_custom_settings(self, mock_credential): client = GoogletasksClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -136,17 +143,20 @@ async def test_list_task_lists_success(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"items":[{"id":"list123"}]}') + mock_response = MockResponse( + status=200, + text=generated_pager_response_text(client.list_task_lists), + ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_task_lists_async() + result = await resolve_generated_result(client.list_task_lists()) - assert len(result["items"]) == 1 + assert result == [{"ok": True}] assert "/users/@me/lists" in mock_send.call_args[0][1] @pytest.mark.asyncio @@ -160,11 +170,11 @@ async def test_create_task_list_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_task_list_async(input=TaskListCreate(title="Work")) + result = await client.create_task_list(input=TaskListCreate(title="Work")) assert result["id"] == "list123" assert isinstance(mock_send.call_args.kwargs["body"], TaskListCreate) @@ -180,11 +190,11 @@ async def test_create_task_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_task_async( + result = await client.create_task( input=TaskCreate(title="Buy milk"), task_list_id="list123", ) @@ -204,11 +214,11 @@ async def test_list_task_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_task_async(task_list_id="list123", task_id="task123") + result = await client.list_task(task_list_id="list123", task_id="task123") assert result["id"] == "task123" assert "/lists/list123/tasks/task123" in mock_send.call_args[0][1] @@ -242,7 +252,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -279,12 +289,12 @@ def test_dataclass_instances_initialize_expected_defaults(self): task_list_entry = TaskListEntry() task_list = TaskList() task_object = TaskObject() - task_list_create = TaskListCreate() - task_create = TaskCreate() + task_list_create = model_instance(TaskListCreate) + task_create = model_instance(TaskCreate) assert task_list_list.items is None assert task_list_entry.id is None assert task_list.items is None assert task_object.id is None - assert task_list_create.title is None - assert task_create.title is None + assert task_list_create.title == "value" + assert task_create.title == "value" diff --git a/tests/test_impexium.py b/tests/test_impexium.py index 4057db8..b36e2cf 100644 --- a/tests/test_impexium.py +++ b/tests/test_impexium.py @@ -3,7 +3,8 @@ """Contract tests for ImpexiumClient.""" import azure.connectors.impexium as impexium_module -from azure.connectors.impexium import ImpexiumClient, TRIGGER_OPERATIONS +from azure.connectors.aio.impexium import ImpexiumClient +from azure.connectors.impexium import TRIGGER_OPERATIONS from tests.generated_connector_test_utils import GeneratedConnectorContractTests @@ -45,16 +46,12 @@ "get_committee_information_for_an_individual", "get_committee_members_by_committee_id_or_code", "get_course_attendees", - "get_individual_active_memberships", - "get_individual_custom_field_values", "get_individual_inactive_memberships", "get_individuals_active_subscriptions", "get_individuals_relationships", "get_list_of_active_certifications_for_an_individual", "get_list_of_active_certifications_for_an_organization", "get_nominees_by_committee", - "get_organization_active_memberships", - "get_organization_custom_field_values", "get_organization_inactive_memberships", "get_organizations_active_subscriptions", "get_organizations_relationships", @@ -70,11 +67,15 @@ "list_all_exhibits", "list_all_individuals", "list_all_open_customer_request", + "list_individual_active_memberships", + "list_individual_custom_field_values", "list_completed_user_tasks_by_user_id_or_email", "list_of_all_individual_members", "list_of_all_organization_members", "list_of_customer_relationships", "list_of_exams", + "list_organization_active_memberships", + "list_organization_custom_field_values", "list_pending_user_tasks_by_user_id_or_email", "list_registrants", "organization_get_profile", @@ -94,13 +95,10 @@ "add_customer_request", "add_email_to_individual", "add_email_to_organization", - "add_exam_scores", "add_individual", "add_nominee", "add_note_to_sales_opportunity", "add_notification_to_individual", - "add_or_update_a_list_of_custom_fields_per_individual", - "add_or_update_a_list_of_custom_fields_per_organization", "add_or_update_address_to_individual", "add_or_update_address_to_organization", "add_organization", @@ -114,6 +112,9 @@ "awards_add_award_nomination", "individual_add_education_credit", "individual_add_note", + "add_exam_scores", + "add_or_update_a_list_of_custom_fields_per_individual", + "add_or_update_a_list_of_custom_fields_per_organization", "organization_add_note", "register_an_individual_for_a_free_session", "save_relationship_for_organization", diff --git a/tests/test_infusionsoft.py b/tests/test_infusionsoft.py index 06982d3..b0b2db0 100644 --- a/tests/test_infusionsoft.py +++ b/tests/test_infusionsoft.py @@ -8,9 +8,9 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.infusionsoft import InfusionsoftClient from azure.connectors.infusionsoft import ( CreateTaskRequest, - InfusionsoftClient, ListOrdersResponse, ListTasksResponse, OnNewTaskResponse, @@ -21,16 +21,24 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import ( + generated_pager_response_text, + model_instance, + resolve_generated_result, +) async def _invoke_operation(client: InfusionsoftClient, operation: str): """Invoke an Infusionsoft operation by name for shared tests.""" if operation == "create_task": - return await client.create_task_async(input=CreateTaskRequest()) + return await client.create_task(input=model_instance(CreateTaskRequest)) if operation == "update_task": - return await client.update_task_async(input=CreateTaskRequest(), id="1") + return await client.update_task( + input=model_instance(CreateTaskRequest), + id="1", + ) if operation == "list_tasks": - return await client.list_tasks_async() + return await resolve_generated_result(client.list_tasks()) raise ValueError(f"Unsupported operation '{operation}'.") @@ -75,7 +83,7 @@ def test_init_with_custom_settings(self, mock_credential): client = InfusionsoftClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -142,11 +150,13 @@ async def test_create_task_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_task_async(input=CreateTaskRequest()) + result = await client.create_task( + input=model_instance(CreateTaskRequest) + ) method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "POST" @@ -165,11 +175,14 @@ async def test_update_task_success_targets_resource(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.update_task_async(input=CreateTaskRequest(), id="5") + result = await client.update_task( + input=model_instance(CreateTaskRequest), + id="5", + ) method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "PUT" @@ -184,25 +197,28 @@ async def test_list_tasks_success_includes_order_query(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"tasks": [{"id": 1}]}') + mock_response = MockResponse( + status=200, + text=generated_pager_response_text(client.list_tasks), + ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_tasks_async() + result = await resolve_generated_result(client.list_tasks()) method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert "/crm/rest/v1/tasks/search?" in path assert "order=" in path - assert result == {"tasks": [{"id": 1}]} + assert result == [{"ok": True}] @pytest.mark.asyncio - async def test_empty_response_body_returns_none(self, mock_credential): - """Test a 2xx response with no body returns None.""" + async def test_empty_response_body_returns_empty_page(self, mock_credential): + """Test a pageable 2xx response with no body returns no items.""" client = InfusionsoftClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -211,13 +227,13 @@ async def test_empty_response_body_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.list_tasks_async() + result = await resolve_generated_result(client.list_tasks()) - assert result is None + assert result == [] class TestInfusionsoftClientErrorHandling: @@ -239,7 +255,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -288,6 +304,8 @@ def test_response_dataclasses_initialize_expected_defaults(self): assert get_origin(ListOrdersResponse) is list def test_request_dataclasses_instantiate(self): - """Test generated request dataclasses instantiate without arguments.""" - assert CreateTaskRequest() is not None - assert CreateTaskRequest().type_ is None + """Test generated request dataclasses initialize optional defaults.""" + request = model_instance(CreateTaskRequest) + + assert request is not None + assert request.type_ is None diff --git a/tests/test_insightly.py b/tests/test_insightly.py index d441540..a2d7566 100644 --- a/tests/test_insightly.py +++ b/tests/test_insightly.py @@ -7,9 +7,9 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.insightly import InsightlyClient from azure.connectors.insightly import ( ContactRequest, - InsightlyClient, LeadRequest, ListContactsResponse, ListEventsResponse, @@ -26,48 +26,61 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import ( + generated_pager_response_text, + model_instance, + resolve_generated_result, +) async def _invoke_operation(client: InsightlyClient, operation: str): """Invoke an Insightly operation by name for shared tests.""" if operation == "list_tasks": - return await client.list_tasks_async() + return await resolve_generated_result(client.list_tasks()) if operation == "update_task": - return await client.update_task_async(input=TaskRequest(), id="1") + return await client.update_task(input=model_instance(TaskRequest), id="1") if operation == "add_task": - return await client.add_task_async(input=TaskRequest()) + return await client.add_task(input=model_instance(TaskRequest)) if operation == "list_projects": - return await client.list_projects_async() + return await resolve_generated_result(client.list_projects()) if operation == "update_project": - return await client.update_project_async(input=ProjectRequest(), id="1") + return await client.update_project( + input=model_instance(ProjectRequest), + id="1", + ) if operation == "add_project": - return await client.add_project_async(input=ProjectRequest()) + return await client.add_project(input=model_instance(ProjectRequest)) if operation == "list_leads": - return await client.list_leads_async() + return await resolve_generated_result(client.list_leads()) if operation == "update_lead": - return await client.update_lead_async(input=LeadRequest(), id="1") + return await client.update_lead(input=model_instance(LeadRequest), id="1") if operation == "add_lead": - return await client.add_lead_async(input=LeadRequest()) + return await client.add_lead(input=model_instance(LeadRequest)) if operation == "list_contacts": - return await client.list_contacts_async() + return await resolve_generated_result(client.list_contacts()) if operation == "update_contact": - return await client.update_contact_async(input=ContactRequest(), id="1") + return await client.update_contact( + input=model_instance(ContactRequest), + id="1", + ) if operation == "add_contact": - return await client.add_contact_async(input=ContactRequest()) + return await client.add_contact(input=model_instance(ContactRequest)) if operation == "list_users": - return await client.list_users_async() + return await resolve_generated_result(client.list_users()) if operation == "delete_task": - return await client.delete_task_async(task_id="1") + return await client.delete_task(task_id="1") if operation == "follow_task": - return await client.follow_task_async(task_id="1") + return await client.follow_task(task_id="1") if operation == "delete_project": - return await client.delete_project_async(project_id="1") + return await client.delete_project(project_id="1") if operation == "delete_lead": - return await client.delete_lead_async(lead_id="1") + return await client.delete_lead(lead_id="1") if operation == "delete_contact": - return await client.delete_contact_async(contact_id="1") + return await client.delete_contact(contact_id="1") if operation == "add_organization": - return await client.add_organization_async(input=OrganizationRequest()) + return await client.add_organization( + input=model_instance(OrganizationRequest) + ) raise ValueError(f"Unsupported operation '{operation}'.") @@ -128,7 +141,7 @@ def test_init_with_custom_settings(self, mock_credential): client = InsightlyClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -191,20 +204,23 @@ async def test_list_tasks_success(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"tasks": [{"TASK_ID": 1}]}') + mock_response = MockResponse( + status=200, + text=generated_pager_response_text(client.list_tasks), + ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_tasks_async() + result = await resolve_generated_result(client.list_tasks()) method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert path.endswith("/Tasks") - assert result == {"tasks": [{"TASK_ID": 1}]} + assert result == [{"ok": True}] @pytest.mark.asyncio async def test_add_task_success(self, mock_credential): @@ -217,11 +233,11 @@ async def test_add_task_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.add_task_async(input=TaskRequest()) + result = await client.add_task(input=model_instance(TaskRequest)) method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "POST" @@ -240,11 +256,14 @@ async def test_update_task_success_includes_id_query(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.update_task_async(input=TaskRequest(), id="5") + result = await client.update_task( + input=model_instance(TaskRequest), + id="5", + ) method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "PUT" @@ -263,11 +282,11 @@ async def test_delete_task_success_targets_resource(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.delete_task_async(task_id="7") + result = await client.delete_task(task_id="7") method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "DELETE" @@ -285,11 +304,11 @@ async def test_follow_task_success_targets_follow(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.follow_task_async(task_id="7") + result = await client.follow_task(task_id="7") method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "POST" @@ -307,11 +326,13 @@ async def test_add_organization_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.add_organization_async(input=OrganizationRequest()) + result = await client.add_organization( + input=model_instance(OrganizationRequest) + ) method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "POST" @@ -319,8 +340,8 @@ async def test_add_organization_success(self, mock_credential): assert result == {"ORGANISATION_ID": 3} @pytest.mark.asyncio - async def test_empty_response_body_returns_none(self, mock_credential): - """Test a 2xx response with no body returns None.""" + async def test_empty_response_body_returns_empty_page(self, mock_credential): + """Test a pageable 2xx response with no body returns no items.""" client = InsightlyClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -329,13 +350,13 @@ async def test_empty_response_body_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.list_tasks_async() + result = await resolve_generated_result(client.list_tasks()) - assert result is None + assert result == [] class TestInsightlyClientErrorHandling: @@ -357,7 +378,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -417,9 +438,9 @@ def test_response_dataclasses_initialize_expected_defaults(self): assert ListEventsResponse().events is None def test_request_dataclasses_instantiate(self): - """Test generated request dataclasses instantiate without arguments.""" - assert TaskRequest() is not None - assert ProjectRequest() is not None - assert LeadRequest() is not None - assert ContactRequest() is not None - assert OrganizationRequest() is not None + """Test generated request dataclasses initialize required fields.""" + assert model_instance(TaskRequest) is not None + assert model_instance(ProjectRequest) is not None + assert model_instance(LeadRequest) is not None + assert model_instance(ContactRequest) is not None + assert model_instance(OrganizationRequest) is not None diff --git a/tests/test_jedoxodatahub.py b/tests/test_jedoxodatahub.py index 51ab3e2..e6b57a6 100644 --- a/tests/test_jedoxodatahub.py +++ b/tests/test_jedoxodatahub.py @@ -3,46 +3,46 @@ """Contract tests for JedoxodatahubClient.""" import azure.connectors.jedoxodatahub as jedoxodatahub_module -from azure.connectors.jedoxodatahub import JedoxodatahubClient +from azure.connectors.aio.jedoxodatahub import JedoxodatahubClient from tests.generated_connector_test_utils import GeneratedConnectorContractTests OPERATION_CONTRACTS = dict.fromkeys( [ "cube_by_id", - "cube_cells", - "cubes", "database_by_id", - "databases", "dimension_by_id", - "dimensions", "element_by_id", - "elements", "extract_by_name", - "extract_rows", - "extracts", "get_cube_cell_result_schema", "get_extract_rows_result_schema", "get_transform_rows_result_schema", "get_view_cell_result_schema", - "integrator_project_groups", - "integrator_projects", "integrator_projects_by_id", "integrator_projects_by_name", "job_by_name", - "jobs", + "list_cube_cells", + "list_cubes", + "list_databases", + "list_dimensions", + "list_elements", + "list_extract_rows", + "list_extracts", + "list_integrator_project_groups", + "list_integrator_projects", + "list_jobs", + "list_loads", + "list_transform_rows", + "list_transforms", + "list_view_cells", + "list_views", "load_by_name", - "loads", "run_job", "run_job_with_variables", "run_load", "run_load_with_variables", "transform_by_name", - "transform_rows", - "transforms", "view_by_id", - "view_cells", - "views", ], ("GET", False), ) diff --git a/tests/test_jira.py b/tests/test_jira.py index 49d6c01..c52b02a 100644 --- a/tests/test_jira.py +++ b/tests/test_jira.py @@ -9,11 +9,13 @@ import pytest from azure.core.credentials import AzureKeyCredential -from azure.connectors.jira import JiraClient, CreateIssueInput, EditIssueInput +from azure.connectors.aio.jira import JiraClient +from azure.connectors.jira import CreateIssueInput, EditIssueInput from azure.connectors.sdk import ( ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestJiraClientInitialization: @@ -49,7 +51,7 @@ def test_init_with_custom_settings(self, mock_credential): client = JiraClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -114,23 +116,22 @@ async def test_success(self, mock_credential): ) mock_response = MockResponse( status=200, - text='{"value": [{"id": "site-1"}]}', + text='[{"id": "site-1"}]', ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_resources_async() + result = await resolve_generated_result(client.list_resources()) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert "/oauth/token/accessible-resources" in path - assert result is not None - assert "value" in result + assert result == [{"id": "site-1"}] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -146,12 +147,53 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.list_resources_async() + await resolve_generated_result(client.list_resources()) + + +class TestListFiltersAsync: + """Tests for list_filters paging behavior.""" + + @pytest.mark.asyncio + async def test_follows_next_page_url(self, mock_credential): + """Test Jira's schema continuation URL is followed to the second page.""" + client = JiraClient( + "https://example.azure.com/connections/test", + credential=mock_credential, + ) + next_page_url = ( + "https://example.azure.com/connections/test/v2/filter/search" + "?startAt=50" + ) + responses = [ + MockResponse( + status=200, + text=( + '{"values": [{"id": "filter-1"}], ' + f'"nextPage": "{next_page_url}"}}' + ), + ), + MockResponse( + status=200, + text='{"values": [{"id": "filter-2"}]}', + ), + ] + + with patch.object( + client._http_client, + "send", + new_callable=AsyncMock, + side_effect=responses, + ) as transport: + result = await resolve_generated_result(client.list_filters()) + + assert result == [{"id": "filter-1"}, {"id": "filter-2"}] + assert transport.await_count == 2 + assert transport.await_args_list[1].args[1] == next_page_url class TestListIssuesAsync: @@ -159,10 +201,10 @@ class TestListIssuesAsync: def test_fields_are_an_optional_string(self): """Test the live fields parameter is exposed without an implicit all-fields default.""" - fields = inspect.signature(JiraClient.list_issues_async).parameters["fields"] + fields = inspect.signature(JiraClient.list_issues).parameters["fields"] assert fields.default is None - assert get_type_hints(JiraClient.list_issues_async)["fields"] == Optional[str] + assert get_type_hints(JiraClient.list_issues)["fields"] == Optional[str] @pytest.mark.asyncio @pytest.mark.parametrize( @@ -179,14 +221,14 @@ async def test_fields_query_matches_live_optional_contract( ) as client: with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"issues": []}'), ) as transport: arguments = {"jql": "project = DEMO"} if fields is not None: arguments["fields"] = fields - await client.list_issues_async(**arguments) + await resolve_generated_result(client.list_issues(**arguments)) transport.assert_awaited_once() method, request_url = transport.await_args.args @@ -199,18 +241,25 @@ async def test_fields_query_matches_live_optional_contract( @pytest.mark.asyncio async def test_named_continuation_token_keeps_its_query_binding(self, mock_credential): - """Test callers can retain token binding by using the existing named parameter.""" + """Test callers can resume paging with an Azure Core continuation URL.""" async with JiraClient( "https://example.azure.com/connections/test", credential=mock_credential, ) as client: with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"issues": []}'), ) as transport: - await client.list_issues_async(next_page_token="page/2") + continuation_url = ( + "https://example.azure.com/connections/test/2/search" + "?nextPageToken=page%2F2" + ) + pages = client.list_issues().by_page( + continuation_token=continuation_url + ) + await anext(pages) request_url = transport.await_args.args[1] assert "nextPageToken=page%2F2" in request_url @@ -230,13 +279,15 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_issues_async( - jql="created >= -3650d", - fields="summary,status", + result = await resolve_generated_result( + client.list_issues( + jql="created >= -3650d", + fields="summary,status", + ) ) mock_send.assert_called_once() @@ -246,8 +297,7 @@ async def test_success(self, mock_credential): assert "jql=created%20%3E%3D%20-3650d" in path assert "fields=summary%2Cstatus" in path assert "fields=%2Aall" not in path - assert result is not None - assert "issues" in result + assert result == [{"key": "PROJ-1"}] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -263,12 +313,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.list_issues_async() + await resolve_generated_result(client.list_issues()) class TestCreateIssueAsync: @@ -291,11 +341,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_issue_async( + result = await client.create_issue( input=payload, project_key="PROJ", issue_type_ids="10001", @@ -327,12 +377,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.create_issue_async( + await client.create_issue( input=payload, project_key="PROJ", issue_type_ids="10001", @@ -356,11 +406,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_issue_async(issue_key="PROJ-1") + result = await client.get_issue(issue_key="PROJ-1") mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -384,11 +434,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.delete_project_async(project_id_or_key="PROJ") + await client.delete_project(project_id_or_key="PROJ") mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -406,12 +456,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.delete_project_async(project_id_or_key="PROJ") + await client.delete_project(project_id_or_key="PROJ") class TestEditIssueAsync: @@ -429,11 +479,11 @@ async def test_success_sends_body_and_returns_result(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.edit_issue_async( + result = await client.edit_issue( input=payload, issue_id_or_key="PROJ-1", ) @@ -458,12 +508,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.edit_issue_async( + await client.edit_issue( input=payload, issue_id_or_key="PROJ-1", ) diff --git a/tests/test_keyvault.py b/tests/test_keyvault.py index ef650b6..256e2bc 100644 --- a/tests/test_keyvault.py +++ b/tests/test_keyvault.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.keyvault import KeyvaultClient from azure.connectors.keyvault import ( - KeyvaultClient, KeyMetadataCollection, KeyMetadata, KeyEncryptOutput, @@ -66,7 +66,7 @@ def test_init_with_custom_settings(self, mock_credential): client = KeyvaultClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -128,7 +128,7 @@ async def test_context_manager(self, mock_credential): class TestListKeysAsync: - """Tests for list_keys_async method.""" + """Tests for list_keys method.""" @pytest.mark.asyncio async def test_success_returns_keys(self, mock_credential): @@ -146,22 +146,21 @@ async def test_success_returns_keys(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.list_keys_async() + result = [item async for item in client.list_keys()] mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/keys" in call_args[0][1] - assert result is not None - assert "value" in result + assert result == [{"name": "key1", "version": "v1"}] @pytest.mark.asyncio - async def test_empty_response_returns_none(self, mock_credential): - """Test empty response returns None.""" + async def test_empty_response_returns_empty_page(self, mock_credential): + """Test empty response returns an empty page.""" mock_response = MockResponse(status=200, text='') client = KeyvaultClient( @@ -171,12 +170,12 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.list_keys_async() - assert result is None + result = [item async for item in client.list_keys()] + assert result == [] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -193,18 +192,18 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.list_keys_async() + [item async for item in client.list_keys()] assert exc_info.value.status_code == 403 class TestListKeyVersionsAsync: - """Tests for list_key_versions_async method.""" + """Tests for list_key_versions method.""" @pytest.mark.asyncio async def test_success(self, mock_credential): @@ -219,17 +218,21 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.list_key_versions_async(key_name="mykey") + result = [ + item async for item in client.list_key_versions( + key_name="mykey" + ) + ] mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/keys/mykey/versions" in call_args[0][1] - assert result is not None + assert result == [{"version": "v1"}, {"version": "v2"}] class TestGetKeyMetadataAsync: @@ -251,11 +254,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_key_metadata_async(key_name="mykey") + result = await client.get_key_metadata(key_name="mykey") mock_send.assert_called_once() call_args = mock_send.call_args @@ -276,12 +279,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_key_metadata_async(key_name="nonexistent") + await client.get_key_metadata(key_name="nonexistent") assert exc_info.value.status_code == 404 @@ -302,11 +305,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_key_version_metadata_async( + result = await client.get_key_version_metadata( key_name="mykey", key_version="v1" ) @@ -339,11 +342,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.encrypt_data_async( + result = await client.encrypt_data( input=encrypt_input, key_name="mykey" ) @@ -375,12 +378,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.encrypt_data_async( + await client.encrypt_data( input=encrypt_input, key_name="mykey" ) @@ -409,11 +412,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.encrypt_data_with_version_async( + result = await client.encrypt_data_with_version( input=encrypt_input, key_name="mykey", key_version="v1" @@ -447,11 +450,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.decrypt_data_async( + result = await client.decrypt_data( input=decrypt_input, key_name="mykey" ) @@ -485,11 +488,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.decrypt_data_with_version_async( + result = await client.decrypt_data_with_version( input=decrypt_input, key_name="mykey", key_version="v1" @@ -503,7 +506,7 @@ async def test_success(self, mock_credential): class TestListSecretsAsync: - """Tests for list_secrets_async method.""" + """Tests for list_secrets method.""" @pytest.mark.asyncio async def test_success(self, mock_credential): @@ -518,17 +521,17 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.list_secrets_async() + result = [item async for item in client.list_secrets()] mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/secrets" in call_args[0][1] - assert result is not None + assert result == [{"name": "secret1"}, {"name": "secret2"}] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -542,18 +545,18 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.list_secrets_async() + [item async for item in client.list_secrets()] assert exc_info.value.status_code == 403 class TestListSecretVersionsAsync: - """Tests for list_secret_versions_async method.""" + """Tests for list_secret_versions method.""" @pytest.mark.asyncio async def test_success(self, mock_credential): @@ -568,19 +571,21 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.list_secret_versions_async( - secret_name="mysecret" - ) + result = [ + item async for item in client.list_secret_versions( + secret_name="mysecret" + ) + ] mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/secrets/mysecret/versions" in call_args[0][1] - assert result is not None + assert result == [{"version": "v1"}, {"version": "v2"}] class TestGetSecretMetadataAsync: @@ -602,11 +607,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_secret_metadata_async( + result = await client.get_secret_metadata( secret_name="mysecret" ) @@ -634,11 +639,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_secret_version_metadata_async( + result = await client.get_secret_version_metadata( secret_name="mysecret", secret_version="v1" ) @@ -669,11 +674,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_secret_async(secret_name="mysecret") + result = await client.get_secret(secret_name="mysecret") mock_send.assert_called_once() call_args = mock_send.call_args @@ -694,12 +699,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_secret_async(secret_name="nonexistent") + await client.get_secret(secret_name="nonexistent") assert exc_info.value.status_code == 404 @@ -720,11 +725,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_secret_version_async( + result = await client.get_secret_version( secret_name="mysecret", secret_version="v1" ) @@ -770,11 +775,14 @@ def test_key_metadata_collection_defaults(self): assert collection.value is None assert collection.continuation_token is None - def test_key_encrypt_input_defaults(self): - """Test KeyEncryptInput dataclass with defaults.""" - input_obj = KeyEncryptInput() - assert input_obj.algorithm is None - assert input_obj.raw_data is None + def test_key_encrypt_input_required_fields(self): + """Test KeyEncryptInput dataclass required fields.""" + input_obj = KeyEncryptInput( + algorithm="RSA-OAEP", + raw_data="data to encrypt", + ) + assert input_obj.algorithm == "RSA-OAEP" + assert input_obj.raw_data == "data to encrypt" def test_key_encrypt_input_with_values(self): """Test KeyEncryptInput dataclass with values.""" @@ -785,11 +793,14 @@ def test_key_encrypt_input_with_values(self): assert input_obj.algorithm == "RSA-OAEP" assert input_obj.raw_data == "data to encrypt" - def test_key_decrypt_input_defaults(self): - """Test KeyDecryptInput dataclass with defaults.""" - input_obj = KeyDecryptInput() - assert input_obj.algorithm is None - assert input_obj.encrypted_data is None + def test_key_decrypt_input_required_fields(self): + """Test KeyDecryptInput dataclass required fields.""" + input_obj = KeyDecryptInput( + algorithm="RSA-OAEP", + encrypted_data="encrypted data", + ) + assert input_obj.algorithm == "RSA-OAEP" + assert input_obj.encrypted_data == "encrypted data" def test_key_encrypt_output_defaults(self): """Test KeyEncryptOutput dataclass with defaults.""" diff --git a/tests/test_kusto.py b/tests/test_kusto.py index 3cf5364..9eed5c1 100644 --- a/tests/test_kusto.py +++ b/tests/test_kusto.py @@ -6,8 +6,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.kusto import KustoClient from azure.connectors.kusto import ( - KustoClient, QueryAndListSchema, ControlCommandAndListSchema, QueryAndVisualizeSchema, @@ -18,6 +18,13 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import model_instance + + +async def resolve_lro(poller_awaitable): + """Await a generated asynchronous poller and return its terminal result.""" + poller = await poller_awaitable + return await poller.result() class TestKustoClientInitialization: @@ -53,7 +60,7 @@ def test_init_with_custom_settings(self, mock_credential): client = KustoClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -124,7 +131,7 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: @@ -133,7 +140,9 @@ async def test_success_with_json_response(self, mock_credential): db="testdb", csl="TestTable | take 10" ) - result = await client.list_kusto_results_async(input_schema) + result = await resolve_lro( + client.begin_list_kusto_results(input_schema) + ) mock_send.assert_called_once_with( "POST", @@ -158,12 +167,14 @@ async def test_success_with_empty_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - input_schema = QueryAndListSchema() - result = await client.list_kusto_results_async(input_schema) + input_schema = model_instance(QueryAndListSchema) + result = await resolve_lro( + client.begin_list_kusto_results(input_schema) + ) assert result is None @@ -182,14 +193,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - input_schema = QueryAndListSchema() + input_schema = model_instance(QueryAndListSchema) with pytest.raises(ConnectorException) as exc_info: - await client.list_kusto_results_async(input_schema) + await client.begin_list_kusto_results(input_schema) assert exc_info.value.status_code == 400 assert exc_info.value.response_body == '{"error": "Invalid query"}' @@ -211,12 +222,14 @@ async def test_500_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.list_kusto_results_async(QueryAndListSchema()) + await client.begin_list_kusto_results( + model_instance(QueryAndListSchema) + ) assert exc_info.value.status_code == 500 @@ -239,7 +252,7 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: @@ -248,7 +261,9 @@ async def test_success_with_json_response(self, mock_credential): db="testdb", csl=".show tables" ) - result = await client.list_kusto_show_command_results_async(input_schema) + result = await resolve_lro( + client.begin_list_kusto_show_command_results(input_schema) + ) mock_send.assert_called_once_with( "POST", @@ -273,12 +288,14 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.list_kusto_show_command_results_async( - ControlCommandAndListSchema() + result = await resolve_lro( + client.begin_list_kusto_show_command_results( + model_instance(ControlCommandAndListSchema) + ) ) assert result is None @@ -298,13 +315,13 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.list_kusto_show_command_results_async( - ControlCommandAndListSchema() + await client.begin_list_kusto_show_command_results( + model_instance(ControlCommandAndListSchema) ) assert exc_info.value.status_code == 403 @@ -328,7 +345,7 @@ async def test_success_with_chart_data(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: @@ -338,7 +355,9 @@ async def test_success_with_chart_data(self, mock_credential): csl="TestTable | summarize count() by timestamp", chart_type="line" ) - result = await client.run_kusto_query_and_visualize_results_async(input_schema) + result = await resolve_lro( + client.begin_run_kusto_query_and_visualize_results(input_schema) + ) mock_send.assert_called_once_with( "POST", @@ -366,13 +385,13 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.run_kusto_query_and_visualize_results_async( - QueryAndVisualizeSchema() + await client.begin_run_kusto_query_and_visualize_results( + model_instance(QueryAndVisualizeSchema) ) assert exc_info.value.status_code == 400 @@ -396,7 +415,7 @@ async def test_success_with_chart_data(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: @@ -406,7 +425,9 @@ async def test_success_with_chart_data(self, mock_credential): csl=".show schema", chart_type="bar" ) - result = await client.run_kusto_command_and_visualize_results_async(input_schema) + result = await resolve_lro( + client.begin_run_kusto_command_and_visualize_results(input_schema) + ) mock_send.assert_called_once_with( "POST", @@ -431,12 +452,14 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.run_kusto_command_and_visualize_results_async( - CommandAndVisualizeSchema() + result = await resolve_lro( + client.begin_run_kusto_command_and_visualize_results( + model_instance(CommandAndVisualizeSchema) + ) ) assert result is None @@ -460,7 +483,7 @@ async def test_success_with_command_id(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: @@ -469,7 +492,9 @@ async def test_success_with_command_id(self, mock_credential): db="testdb", csl=".set-or-append async TargetTable <| SourceTable" ) - result = await client.run_async_control_command_and_wait_async(input_schema) + result = await resolve_lro( + client.begin_run_async_control_command_and_wait(input_schema) + ) mock_send.assert_called_once_with( "POST", @@ -499,13 +524,13 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.run_async_control_command_and_wait_async( - ControlCommandAndListSchema() + await client.begin_run_async_control_command_and_wait( + model_instance(ControlCommandAndListSchema) ) assert exc_info.value.status_code == 408 @@ -529,7 +554,7 @@ async def test_success_without_session_id(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: @@ -539,7 +564,7 @@ async def test_success_without_session_id(self, mock_credential): method="query", params={"query": "TestTable | take 1"} ) - result = await client.mcp_kusto_query_management_async(input_request) + result = await client.mcp_kusto_query_management(input_request) mock_send.assert_called_once_with( "POST", @@ -568,12 +593,12 @@ async def test_success_with_session_id(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_request = MCPQueryRequest(jsonrpc="2.0", id="2", method="init") - result = await client.mcp_kusto_query_management_async( + result = await client.mcp_kusto_query_management( input_request, session_id="session-123" ) @@ -603,11 +628,11 @@ async def test_session_id_with_special_characters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.mcp_kusto_query_management_async( + await client.mcp_kusto_query_management( MCPQueryRequest(), session_id="session with spaces" ) @@ -628,11 +653,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.mcp_kusto_query_management_async(MCPQueryRequest()) + result = await client.mcp_kusto_query_management(MCPQueryRequest()) assert result is None @@ -651,12 +676,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.mcp_kusto_query_management_async(MCPQueryRequest()) + await client.mcp_kusto_query_management(MCPQueryRequest()) assert exc_info.value.status_code == 500 @@ -734,13 +759,10 @@ def test_mcp_query_request_creation(self): assert request.params == {"query": "test"} assert request.callback_endpoint == "https://callback.example.com" - def test_dataclasses_with_defaults(self): - """Test that dataclasses can be created with default None values.""" - schema = QueryAndListSchema() - - assert schema.cluster is None - assert schema.db is None - assert schema.csl is None + def test_required_dataclass_fields(self): + """Test that Swagger-required dataclass fields must be provided.""" + with pytest.raises(TypeError): + QueryAndListSchema() class TestEdgeCases: @@ -759,12 +781,20 @@ async def test_multiple_consecutive_calls(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, side_effect=[mock_response_1, mock_response_2] ): - result_1 = await client.list_kusto_results_async(QueryAndListSchema()) - result_2 = await client.list_kusto_results_async(QueryAndListSchema()) + result_1 = await resolve_lro( + client.begin_list_kusto_results( + model_instance(QueryAndListSchema) + ) + ) + result_2 = await resolve_lro( + client.begin_list_kusto_results( + model_instance(QueryAndListSchema) + ) + ) assert result_1 == {"result": "first"} assert result_2 == {"result": "second"} @@ -781,12 +811,16 @@ async def test_json_parse_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(json.JSONDecodeError): - await client.list_kusto_results_async(QueryAndListSchema()) + await resolve_lro( + client.begin_list_kusto_results( + model_instance(QueryAndListSchema) + ) + ) @pytest.mark.asyncio async def test_url_construction_with_multiple_trailing_slashes(self): @@ -828,14 +862,14 @@ async def test_success_returns_schema(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=MockResponse( status=200, text='{"columns": [{"name": "Timestamp"}]}' ) ) as mock_send: - result = await client.list_kusto_results_schema_async(input_schema) + result = await client.list_kusto_results_schema(input_schema) mock_send.assert_called_once_with( "POST", @@ -858,13 +892,13 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=MockResponse(status=400, text="Invalid query") ): with pytest.raises(ConnectorException) as exc_info: - await client.list_kusto_results_schema_async( - QueryAndListSchema() + await client.list_kusto_results_schema( + model_instance(QueryAndListSchema) ) assert exc_info.value.status_code == 400 diff --git a/tests/test_mailchimp.py b/tests/test_mailchimp.py index d0ab645..e3b1ca5 100644 --- a/tests/test_mailchimp.py +++ b/tests/test_mailchimp.py @@ -7,8 +7,8 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.mailchimp import MailchimpClient from azure.connectors.mailchimp import ( - MailchimpClient, NewCampaignRequest, NewListRequest, NewMemberInListRequest, @@ -20,6 +20,7 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import model_instance, resolve_generated_result class TestMailchimpClientInitialization: @@ -55,7 +56,7 @@ def test_init_with_custom_settings(self, mock_credential): client = MailchimpClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -112,7 +113,7 @@ class TestMailchimpClientOperations: """Tests for MailchimpClient operations against expected HTTP calls.""" @pytest.mark.asyncio - async def test_get_campaigns_success(self, mock_credential): + async def test_list_campaigns_success(self, mock_credential): """Test list campaigns issues a GET to the campaigns route.""" client = MailchimpClient( "https://example.azure.com/connections/test", @@ -122,16 +123,16 @@ async def test_get_campaigns_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_campaigns_async() + result = await resolve_generated_result(client.list_campaigns()) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert url.endswith("/campaigns") - assert result == {"campaigns": []} + assert result == [] @pytest.mark.asyncio async def test_sendcampaign_success(self, mock_credential): @@ -144,11 +145,11 @@ async def test_sendcampaign_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.sendcampaign_async(campaign_id="c1") + result = await client.sendcampaign(campaign_id="c1") method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "POST" @@ -166,11 +167,11 @@ async def test_get_lists_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_lists_async(count="10", offset="0") + result = await client.get_lists(count="10", offset="0") method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" @@ -190,11 +191,13 @@ async def test_newlist_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.newlist_async(input=NewListRequest(name="Test")) + result = await client.newlist( + input=model_instance(NewListRequest, name="Test"), + ) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "POST" @@ -213,12 +216,12 @@ async def test_add_members_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.add_members_async( - input=NewMembersInListRequest(), + result = await client.add_members( + input=model_instance(NewMembersInListRequest), list_id="L1", ) @@ -239,11 +242,11 @@ async def test_get_list_members_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_list_members_async(list_id="L1") + result = await client.get_list_members(list_id="L1") method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" @@ -261,12 +264,12 @@ async def test_addmember_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.addmember_async( - input=NewMemberInListRequest(), + result = await client.addmember( + input=model_instance(NewMemberInListRequest), list_id="L1", ) @@ -287,11 +290,13 @@ async def test_newcampaign_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.newcampaign_async(input=NewCampaignRequest()) + result = await client.newcampaign( + input=model_instance(NewCampaignRequest), + ) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "POST" @@ -310,11 +315,11 @@ async def test_removemember_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.removemember_async(list_id="L1") + result = await client.removemember(list_id="L1") method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "DELETE" @@ -333,12 +338,12 @@ async def test_updatemember_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.updatemember_async( - input=UpdateMemberInListRequest(), + result = await client.updatemember( + input=model_instance(UpdateMemberInListRequest), list_id="L1", ) @@ -350,8 +355,8 @@ async def test_updatemember_success(self, mock_credential): assert result == {"id": "m1"} @pytest.mark.asyncio - async def test_empty_response_body_returns_none(self, mock_credential): - """Test a 2xx response with no body returns None.""" + async def test_empty_response_body_returns_empty_page(self, mock_credential): + """Test a paged 2xx response with no body yields no items.""" client = MailchimpClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -360,13 +365,13 @@ async def test_empty_response_body_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.get_campaigns_async() + result = await resolve_generated_result(client.list_campaigns()) - assert result is None + assert result == [] class TestMailchimpClientErrorHandling: @@ -376,7 +381,7 @@ class TestMailchimpClientErrorHandling: @pytest.mark.parametrize( "operation", [ - "get_campaigns", + "list_campaigns", "sendcampaign", "get_lists", "newlist", @@ -398,36 +403,41 @@ async def test_error_response_raises_exception(self, mock_credential, operation) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - if operation == "get_campaigns": - await client.get_campaigns_async() + if operation == "list_campaigns": + await resolve_generated_result(client.list_campaigns()) elif operation == "sendcampaign": - await client.sendcampaign_async(campaign_id="c1") + await client.sendcampaign(campaign_id="c1") elif operation == "get_lists": - await client.get_lists_async() + await client.get_lists() elif operation == "newlist": - await client.newlist_async(input=NewListRequest()) + await client.newlist(input=model_instance(NewListRequest)) elif operation == "add_members": - await client.add_members_async( - input=NewMembersInListRequest(), list_id="L1" + await client.add_members( + input=model_instance(NewMembersInListRequest), + list_id="L1", ) elif operation == "get_list_members": - await client.get_list_members_async(list_id="L1") + await client.get_list_members(list_id="L1") elif operation == "addmember": - await client.addmember_async( - input=NewMemberInListRequest(), list_id="L1" + await client.addmember( + input=model_instance(NewMemberInListRequest), + list_id="L1", ) elif operation == "newcampaign": - await client.newcampaign_async(input=NewCampaignRequest()) + await client.newcampaign( + input=model_instance(NewCampaignRequest), + ) elif operation == "removemember": - await client.removemember_async(list_id="L1") + await client.removemember(list_id="L1") else: - await client.updatemember_async( - input=UpdateMemberInListRequest(), list_id="L1" + await client.updatemember( + input=model_instance(UpdateMemberInListRequest), + list_id="L1", ) assert exc_info.value.status_code == 500 @@ -475,11 +485,11 @@ def test_triggers_are_not_client_methods(self): class TestMailchimpTypeSerialization: - """Tests for Mailchimp connector dataclass defaults.""" + """Tests for Mailchimp connector dataclass construction.""" def test_request_dataclasses_instantiate(self): - """Test generated request dataclasses instantiate without arguments.""" - assert NewListRequest().name is None - assert NewCampaignRequest().type_ is None - assert NewMemberInListRequest().email_address is None - assert UpdateMemberInListRequest().status is None + """Test generated request dataclasses populate required fields.""" + assert model_instance(NewListRequest).name is not None + assert model_instance(NewCampaignRequest).type_ is not None + assert model_instance(NewMemberInListRequest).email_address is not None + assert model_instance(UpdateMemberInListRequest).status is not None diff --git a/tests/test_meetingroommap.py b/tests/test_meetingroommap.py index 626b38a..7a803e4 100644 --- a/tests/test_meetingroommap.py +++ b/tests/test_meetingroommap.py @@ -3,30 +3,30 @@ """Contract tests for MeetingroommapClient.""" import azure.connectors.meetingroommap as meetingroommap_module -from azure.connectors.meetingroommap import MeetingroommapClient +from azure.connectors.aio.meetingroommap import MeetingroommapClient from tests.generated_connector_test_utils import GeneratedConnectorContractTests OPERATION_CONTRACTS = { "get_custom_locations": ("POST", True), "get_custom_locations_by_image_name": ("POST", True), - "get_categories": ("GET", False), + "list_categories": ("GET", False), "location_details": ("GET", False), - "search_locations": ("GET", False), + "list_search_locations": ("GET", False), "get_custom_location_image": ("GET", False), - "images": ("GET", False), + "list_images": ("GET", False), "get_meeting_room_image": ("GET", False), "next_meetings": ("GET", False), "get_meeting_room_details": ("GET", False), "get_office_locations": ("GET", False), - "search_coworkers": ("GET", False), + "list_search_coworkers": ("GET", False), "get_office_locations_by_image": ("GET", False), "get_room_with_persons_details": ("GET", False), "get_office_location_image": ("GET", False), - "get_rooms": ("GET", False), - "search_meeting_rooms": ("GET", False), - "room_lists": ("GET", False), - "rooms_by_list_address": ("GET", False), + "list_rooms": ("GET", False), + "list_search_meeting_rooms": ("GET", False), + "list_room_lists": ("GET", False), + "list_rooms_by_list_address": ("GET", False), "get_rooms_by_image_name": ("GET", False), } diff --git a/tests/test_microsoftbookings.py b/tests/test_microsoftbookings.py index 356dbe7..96cdddf 100644 --- a/tests/test_microsoftbookings.py +++ b/tests/test_microsoftbookings.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.microsoftbookings import MicrosoftbookingsClient from azure.connectors.microsoftbookings import ( - MicrosoftbookingsClient, CreateAppointmentInput, UpdateAppointmentInput, CancelAppointmentInput, @@ -24,6 +24,7 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestMicrosoftbookingsClientInitialization: @@ -69,7 +70,7 @@ def test_init_with_custom_settings(self, mock_credential): client = MicrosoftbookingsClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -170,22 +171,28 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.list_bookings_business_user_as_admin_async() + result = await resolve_generated_result( + client.list_bookings_business_user_as_admin() + ) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/bookingBusinessesUserAsAdmin" in call_args[0][1] - assert result is not None - assert "mailboxes" in result + assert result == [ + { + "display_name": "Contoso Bookings", + "email": "bookings@contoso.com", + } + ] @pytest.mark.asyncio - async def test_empty_response_returns_none(self, mock_credential): - """Test empty response returns None.""" + async def test_empty_response_returns_empty_page(self, mock_credential): + """Test empty response yields no mailbox items.""" mock_response = MockResponse(status=200, text='') client = MicrosoftbookingsClient( @@ -195,12 +202,14 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.list_bookings_business_user_as_admin_async() - assert result is None + result = await resolve_generated_result( + client.list_bookings_business_user_as_admin() + ) + assert result == [] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -217,12 +226,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.list_bookings_business_user_as_admin_async() + await resolve_generated_result( + client.list_bookings_business_user_as_admin() + ) assert exc_info.value.status_code == 401 @@ -230,10 +241,12 @@ async def test_error_response_raises_exception(self, mock_credential): class TestDataClasses: """Tests for dataclass definitions.""" - def test_create_appointment_input_defaults(self): - """Test CreateAppointmentInput dataclass with defaults.""" - input_obj = CreateAppointmentInput() - assert input_obj.webhook is None + def test_create_appointment_input_required_webhook(self): + """Test CreateAppointmentInput requires webhook data.""" + input_obj = CreateAppointmentInput( + webhook={"callbackUrl": "https://example.com/create"} + ) + assert input_obj.webhook["callbackUrl"] == "https://example.com/create" def test_create_appointment_input_with_values(self): """Test CreateAppointmentInput dataclass with values.""" @@ -242,15 +255,19 @@ def test_create_appointment_input_with_values(self): ) assert input_obj.webhook["callbackUrl"] == "https://example.com/callback" - def test_update_appointment_input_defaults(self): - """Test UpdateAppointmentInput dataclass with defaults.""" - input_obj = UpdateAppointmentInput() - assert input_obj.webhook is None + def test_update_appointment_input_required_webhook(self): + """Test UpdateAppointmentInput requires webhook data.""" + input_obj = UpdateAppointmentInput( + webhook={"callbackUrl": "https://example.com/update"} + ) + assert input_obj.webhook["callbackUrl"] == "https://example.com/update" - def test_cancel_appointment_input_defaults(self): - """Test CancelAppointmentInput dataclass with defaults.""" - input_obj = CancelAppointmentInput() - assert input_obj.webhook is None + def test_cancel_appointment_input_required_webhook(self): + """Test CancelAppointmentInput requires webhook data.""" + input_obj = CancelAppointmentInput( + webhook={"callbackUrl": "https://example.com/cancel"} + ) + assert input_obj.webhook["callbackUrl"] == "https://example.com/cancel" def test_webhook_response_defaults(self): """Test WebhookResponse dataclass with defaults.""" diff --git a/tests/test_microsoftforms.py b/tests/test_microsoftforms.py index 8e6b1f0..dc50524 100644 --- a/tests/test_microsoftforms.py +++ b/tests/test_microsoftforms.py @@ -7,11 +7,13 @@ import pytest from azure.core.credentials import AzureKeyCredential -from azure.connectors.microsoftforms import MicrosoftformsClient, TRIGGER_OPERATIONS +from azure.connectors.aio.microsoftforms import MicrosoftformsClient +from azure.connectors.microsoftforms import TRIGGER_OPERATIONS from azure.connectors.sdk import ( ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestMicrosoftformsClientInitialization: @@ -47,7 +49,7 @@ def test_init_with_custom_settings(self, mock_credential): client = MicrosoftformsClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -120,22 +122,21 @@ async def test_success(self, mock_credential): credential=mock_credential, ) mock_response = MockResponse( - status=200, text='{"value": [{"id": "form-1", "title": "Survey"}]}') + status=200, text='[{"id": "form-1", "title": "Survey"}]') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_forms_async() + result = await resolve_generated_result(client.list_forms()) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert path.endswith("/formapi/api/forms") - assert result is not None - assert "value" in result + assert result == [{"id": "form-1", "title": "Survey"}] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -148,12 +149,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.list_forms_async() + await resolve_generated_result(client.list_forms()) class TestGetFormDetailsByIdAsync: @@ -170,11 +171,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_form_details_by_id_async(form_id="form-123") + result = await client.get_form_details_by_id(form_id="form-123") mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -195,12 +196,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.get_form_details_by_id_async(form_id="missing") + await client.get_form_details_by_id(form_id="missing") class TestGetQuestionsAsync: @@ -218,11 +219,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_questions_async(form_id="form-123") + result = await client.get_questions(form_id="form-123") mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -241,9 +242,9 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.get_questions_async(form_id="form-123") + await client.get_questions(form_id="form-123") diff --git a/tests/test_monday.py b/tests/test_monday.py index 1d02012..54c8dd2 100644 --- a/tests/test_monday.py +++ b/tests/test_monday.py @@ -7,112 +7,36 @@ import pytest from azure.core.credentials import AzureKeyCredential +import azure.connectors.monday as monday_module +from azure.connectors.aio.monday import MondayClient from azure.connectors.monday import ( CreateBoardInput, - CreateColumnInput, - CreateGroupInput, CreateItemInput, CreateItemResponse, CreateNotificationInput, - CreateSubitemInput, - CreateUpdateInput, CreateWorkspaceInput, - DuplicateBoardInput, GetSubitemSchemaResponse, GetTagsResponse, GetUsersResponse, GetWorkspacesResponse, - MondayClient, - MoveItemToGroupInput, UpdateItemColumnInput, - UpdateMultipleItemColumnsInput, TRIGGER_OPERATIONS, ) from azure.connectors.sdk import ( ConnectorException, ) from tests.conftest import MockResponse -from tests.generated_connector_test_utils import get_generated_operations +from tests.generated_connector_test_utils import ( + get_generated_operations, + invoke_generated_operation, + model_instance, + resolve_generated_result, +) async def _invoke_operation(client: MondayClient, operation: str): """Invoke a Monday operation by name for shared tests.""" - if operation == "create_item": - return await client.create_item_async(input=CreateItemInput()) - if operation == "duplicate_board": - return await client.duplicate_board_async(input=DuplicateBoardInput()) - if operation == "create_board": - return await client.create_board_async(input=CreateBoardInput()) - if operation == "create_column": - return await client.create_column_async(input=CreateColumnInput()) - if operation == "create_group": - return await client.create_group_async(input=CreateGroupInput()) - if operation == "update_item_column": - return await client.update_item_column_async(input=UpdateItemColumnInput()) - if operation == "update_multiple_item_columns": - return await client.update_multiple_item_columns_async( - input=UpdateMultipleItemColumnsInput() - ) - if operation == "move_item_to_group": - return await client.move_item_to_group_async(input=MoveItemToGroupInput()) - if operation == "create_notification": - return await client.create_notification_async(input=CreateNotificationInput()) - if operation == "create_subitem": - return await client.create_subitem_async(input=CreateSubitemInput()) - if operation == "create_update": - return await client.create_update_async(input=CreateUpdateInput()) - if operation == "create_workspace": - return await client.create_workspace_async(input=CreateWorkspaceInput()) - if operation == "get_subitems": - return await client.get_subitems_async( - workspace_id="1", board_id="2", item_id="3" - ) - if operation == "get_item_by_id": - return await client.get_item_by_id_async( - item_id="1", workspace_id="2", board_id="3" - ) - if operation == "get_items": - return await client.get_items_async( - workspace_id="1", board_id="2", group_id="3" - ) - if operation == "get_tags": - return await client.get_tags_async() - if operation == "get_users": - return await client.get_users_async() - if operation == "get_workspaces": - return await client.get_workspaces_async() - if operation == "get_boards": - return await client.get_boards_async() - if operation == "get_groups_for_get_items": - return await client.get_groups_for_get_items_async(board_id="1") - if operation == "get_columns_for_item_filtering": - return await client.get_columns_for_item_filtering_async(board_id="1") - if operation == "get_column_filter_operator": - return await client.get_column_filter_operator_async(board_id="1") - if operation == "get_column_names_schema": - return await client.get_column_names_schema_async() - if operation == "get_single_column_schema": - return await client.get_single_column_schema_async() - if operation == "get_column_names_schema_for_webhook": - return await client.get_column_names_schema_for_webhook_async() - if operation == "get_schema_for_get_items_action": - return await client.get_schema_for_get_items_action_async() - if operation == "get_column_names_schema_for_update_webhook": - return await client.get_column_names_schema_for_update_webhook_async() - if operation == "get_column_names_schema_for_item_name_change_webhook": - return await client.get_column_names_schema_for_item_name_change_webhook_async() - if operation == "get_column_names_schema_for_subitem_name_change_webhook": - return await client.get_column_names_schema_for_subitem_name_change_webhook_async( - parent_board_id="1" - ) - if operation == "get_column_names_schema_for_column_changes_webhook": - return await client.get_column_names_schema_for_column_changes_webhook_async() - if operation == "get_subitem_column_names": - return await client.get_subitem_column_names_async(parent_board_id="1") - if operation == "get_subitem_schema": - return await client.get_subitem_schema_async(parent_board_id="1") - - raise ValueError(f"Unsupported operation '{operation}'.") + return await invoke_generated_operation(client, operation, monday_module) ALL_OPERATIONS = [ @@ -134,10 +58,10 @@ async def _invoke_operation(client: MondayClient, operation: str): "get_tags", "get_users", "get_workspaces", - "get_boards", - "get_groups_for_get_items", - "get_columns_for_item_filtering", - "get_column_filter_operator", + "list_boards", + "list_groups_for_get_items", + "list_columns_for_item_filtering", + "list_column_filter_operator", "get_column_names_schema", "get_single_column_schema", "get_column_names_schema_for_webhook", @@ -184,7 +108,7 @@ def test_init_with_custom_settings(self, mock_credential): client = MondayClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -255,11 +179,13 @@ async def test_create_item_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_item_async(input=CreateItemInput()) + result = await client.create_item( + input=model_instance(CreateItemInput), + ) method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "POST" @@ -278,11 +204,13 @@ async def test_update_item_column_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.update_item_column_async(input=UpdateItemColumnInput()) + result = await client.update_item_column( + input=model_instance(UpdateItemColumnInput), + ) method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "POST" @@ -301,11 +229,11 @@ async def test_get_tags_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_tags_async() + result = await client.get_tags() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" @@ -313,8 +241,8 @@ async def test_get_tags_success(self, mock_credential): assert result == {"data": []} @pytest.mark.asyncio - async def test_get_boards_includes_query_parameter(self, mock_credential): - """Test get boards appends the workspaceId query parameter.""" + async def test_list_boards_includes_query_parameter(self, mock_credential): + """Test list boards appends the workspaceId query parameter.""" client = MondayClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -323,11 +251,13 @@ async def test_get_boards_includes_query_parameter(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.get_boards_async(workspace_id="42") + await resolve_generated_result( + client.list_boards(workspace_id="42") + ) method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" @@ -345,11 +275,11 @@ async def test_get_subitems_includes_query_parameters(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.get_subitems_async(workspace_id="1", board_id="2", item_id="3") + await client.get_subitems(workspace_id="1", board_id="2", item_id="3") method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" @@ -367,11 +297,13 @@ async def test_empty_response_body_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.create_item_async(input=CreateItemInput()) + result = await client.create_item( + input=model_instance(CreateItemInput), + ) assert result is None @@ -395,7 +327,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -439,7 +371,7 @@ def test_triggers_are_not_client_methods(self): class TestMondayTypeSerialization: - """Tests for Monday connector dataclass defaults.""" + """Tests for Monday connector dataclass construction.""" def test_response_dataclasses_initialize_expected_defaults(self): """Test generated response dataclasses initialize with None defaults.""" @@ -450,8 +382,8 @@ def test_response_dataclasses_initialize_expected_defaults(self): assert GetSubitemSchemaResponse().schema is None def test_request_dataclasses_instantiate(self): - """Test generated request dataclasses instantiate without arguments.""" - assert CreateItemInput().item_name is None - assert CreateBoardInput().board_name is None - assert CreateNotificationInput().text is None - assert CreateWorkspaceInput() is not None + """Test generated request dataclasses populate required fields.""" + assert model_instance(CreateItemInput).item_name is not None + assert model_instance(CreateBoardInput).board_name is not None + assert model_instance(CreateNotificationInput).text is not None + assert model_instance(CreateWorkspaceInput).name is not None diff --git a/tests/test_mq.py b/tests/test_mq.py index 3942a70..deaee78 100644 --- a/tests/test_mq.py +++ b/tests/test_mq.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.mq import MqClient from azure.connectors.mq import ( - MqClient, SingleGetValidOptions, MultipleGetValidOptions, SendValidDataOptions, @@ -15,6 +15,7 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestMqClientInitialization: @@ -50,7 +51,7 @@ def test_init_with_custom_settings(self, mock_credential): client = MqClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -122,11 +123,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.delete_async(input=input_options) + result = await client.delete(input=input_options) mock_send.assert_called_once() call_args = mock_send.call_args @@ -146,11 +147,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.delete_async(input=SingleGetValidOptions()) + result = await client.delete(input=SingleGetValidOptions()) assert result is None @pytest.mark.asyncio @@ -165,18 +166,18 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.delete_async(input=SingleGetValidOptions()) + await client.delete(input=SingleGetValidOptions()) assert exc_info.value.status_code == 404 class TestDeleteAll: - """Tests for delete_all_async method.""" + """Tests for delete_all method.""" @pytest.mark.asyncio async def test_success_with_json_response(self, mock_credential): @@ -188,27 +189,29 @@ async def test_success_with_json_response(self, mock_credential): mock_response = MockResponse( status=200, - text='{"deletedCount": 5, "messages": []}' + text='{"value": [{"deletedCount": 5, "messages": []}]}' ) input_options = MultipleGetValidOptions(queue="QUEUE.NAME", batch_size=10) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.delete_all_async(input=input_options) + result = await resolve_generated_result( + client.delete_all(input=input_options) + ) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "POST" assert "/v2/deleteall" in call_args[0][1] - assert result["deletedCount"] == 5 + assert result["value"][0]["deletedCount"] == 5 @pytest.mark.asyncio - async def test_empty_response_returns_none(self, mock_credential): - """Test that empty response returns None.""" + async def test_empty_response_returns_empty_page(self, mock_credential): + """Test that empty response yields no items.""" client = MqClient( "https://example.azure.com/connections/test", credential=mock_credential @@ -218,11 +221,13 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.delete_all_async(input=MultipleGetValidOptions()) + result = await resolve_generated_result( + client.delete_all(input=MultipleGetValidOptions()) + ) assert result is None @pytest.mark.asyncio @@ -237,12 +242,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.delete_all_async(input=MultipleGetValidOptions()) + await resolve_generated_result( + client.delete_all(input=MultipleGetValidOptions()) + ) assert exc_info.value.status_code == 500 @@ -266,11 +273,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.read_async(input=input_options) + result = await client.read(input=input_options) mock_send.assert_called_once() call_args = mock_send.call_args @@ -290,11 +297,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.read_async(input=SingleGetValidOptions()) + result = await client.read(input=SingleGetValidOptions()) assert result is None @pytest.mark.asyncio @@ -309,18 +316,18 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.read_async(input=SingleGetValidOptions()) + await client.read(input=SingleGetValidOptions()) assert exc_info.value.status_code == 403 class TestReadAll: - """Tests for read_all_async method.""" + """Tests for read_all method.""" @pytest.mark.asyncio async def test_success_with_json_response(self, mock_credential): @@ -332,27 +339,29 @@ async def test_success_with_json_response(self, mock_credential): mock_response = MockResponse( status=200, - text='{"messages": [{"messageId": "msg1"}, {"messageId": "msg2"}]}' + text='{"value": [{"messageId": "msg1"}, {"messageId": "msg2"}]}' ) input_options = MultipleGetValidOptions(queue="QUEUE.NAME", batch_size=10) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.read_all_async(input=input_options) + result = await resolve_generated_result( + client.read_all(input=input_options) + ) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "POST" assert "/v2/readall" in call_args[0][1] - assert len(result["messages"]) == 2 + assert len(result["value"]) == 2 @pytest.mark.asyncio - async def test_empty_response_returns_none(self, mock_credential): - """Test that empty response returns None.""" + async def test_empty_response_returns_empty_page(self, mock_credential): + """Test that empty response yields no items.""" client = MqClient( "https://example.azure.com/connections/test", credential=mock_credential @@ -362,11 +371,13 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.read_all_async(input=MultipleGetValidOptions()) + result = await resolve_generated_result( + client.read_all(input=MultipleGetValidOptions()) + ) assert result is None @pytest.mark.asyncio @@ -381,12 +392,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.read_all_async(input=MultipleGetValidOptions()) + await resolve_generated_result( + client.read_all(input=MultipleGetValidOptions()) + ) assert exc_info.value.status_code == 408 @@ -410,11 +423,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.receive_async(input=input_options) + result = await client.receive(input=input_options) mock_send.assert_called_once() call_args = mock_send.call_args @@ -434,11 +447,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.receive_async(input=SingleGetValidOptions()) + result = await client.receive(input=SingleGetValidOptions()) assert result is None @pytest.mark.asyncio @@ -453,18 +466,18 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.receive_async(input=SingleGetValidOptions()) + await client.receive(input=SingleGetValidOptions()) assert exc_info.value.status_code == 503 class TestReceiveAll: - """Tests for receive_all_async method.""" + """Tests for receive_all method.""" @pytest.mark.asyncio async def test_success_with_json_response(self, mock_credential): @@ -476,7 +489,7 @@ async def test_success_with_json_response(self, mock_credential): mock_response = MockResponse( status=200, - text='{"messages": [{"messageId": "msg1", "messageData": "Data1"}]}' + text='{"value": [{"messageId": "msg1", "messageData": "Data1"}]}' ) input_options = MultipleGetValidOptions( queue="QUEUE.NAME", @@ -486,21 +499,23 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.receive_all_async(input=input_options) + result = await resolve_generated_result( + client.receive_all(input=input_options) + ) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "POST" assert "/v2/receiveall" in call_args[0][1] - assert len(result["messages"]) == 1 + assert len(result["value"]) == 1 @pytest.mark.asyncio - async def test_empty_response_returns_none(self, mock_credential): - """Test that empty response returns None.""" + async def test_empty_response_returns_empty_page(self, mock_credential): + """Test that empty response yields no items.""" client = MqClient( "https://example.azure.com/connections/test", credential=mock_credential @@ -510,11 +525,13 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.receive_all_async(input=MultipleGetValidOptions()) + result = await resolve_generated_result( + client.receive_all(input=MultipleGetValidOptions()) + ) assert result is None @pytest.mark.asyncio @@ -529,12 +546,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.receive_all_async(input=MultipleGetValidOptions()) + await resolve_generated_result( + client.receive_all(input=MultipleGetValidOptions()) + ) assert exc_info.value.status_code == 401 @@ -562,11 +581,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.send_async(input=input_options) + result = await client.send(input=input_options) mock_send.assert_called_once() call_args = mock_send.call_args @@ -594,11 +613,11 @@ async def test_with_correlation_id(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.send_async(input=input_options) + result = await client.send(input=input_options) mock_send.assert_called_once() assert result["correlationId"] == "corr123" @@ -621,11 +640,11 @@ async def test_with_reply_to_queue(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.send_async(input=input_options) + result = await client.send(input=input_options) mock_send.assert_called_once() assert result["itemInternalId"] == "item789" @@ -642,11 +661,13 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.send_async(input=SendValidDataOptions()) + result = await client.send( + input=SendValidDataOptions(message="test message") + ) assert result is None @pytest.mark.asyncio @@ -661,12 +682,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.send_async(input=SendValidDataOptions()) + await client.send( + input=SendValidDataOptions(message="test message") + ) assert exc_info.value.status_code == 400 @@ -682,11 +705,11 @@ async def test_queue_full_error(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.send_async(input=SendValidDataOptions(message="test")) + await client.send(input=SendValidDataOptions(message="test")) assert exc_info.value.status_code == 507 diff --git a/tests/test_msgraph.py b/tests/test_msgraph.py index a9c2cbb..73ea43d 100644 --- a/tests/test_msgraph.py +++ b/tests/test_msgraph.py @@ -4,8 +4,8 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.msgraphgroupsanduser import MsgraphgroupsanduserClient from azure.connectors.msgraphgroupsanduser import ( - MsgraphgroupsanduserClient, ListUsersResponse, ListGroupsByDisplayNameSearchResponse, ListSubscribedSkusResponse, @@ -16,6 +16,7 @@ GetMemberGroupsResponse, ) from azure.connectors.sdk import ConnectorException +from tests.generated_connector_test_utils import resolve_generated_result class TestMsgraphClientInitialization: @@ -51,7 +52,7 @@ def test_init_with_custom_settings(self, mock_credential): client = MsgraphgroupsanduserClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) @@ -119,14 +120,14 @@ async def test_success_with_json_response(self, mock_credential, mock_response_s with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - result = await client.list_users_async() + result = await resolve_generated_result(client.list_users()) assert result is not None - assert result["value"][0]["id"] == "user1" + assert result[0]["id"] == "user1" mock_send.assert_called_once_with( "GET", "https://example.azure.com/connections/test/v1.0/users", @@ -147,13 +148,13 @@ async def test_success_with_empty_response(self, mock_credential, mock_response_ with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_empty ): - result = await client.list_users_async() + result = await resolve_generated_result(client.list_users()) - assert result is None + assert result == [] @pytest.mark.asyncio async def test_error_raises_exception(self, mock_credential, mock_response_error): @@ -165,12 +166,12 @@ async def test_error_raises_exception(self, mock_credential, mock_response_error with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_error ): with pytest.raises(ConnectorException) as exc_info: - await client.list_users_async() + await resolve_generated_result(client.list_users()) assert exc_info.value.status_code == 400 @@ -193,16 +194,15 @@ async def test_success_with_search_and_count(self, mock_credential, mock_respons with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - result = await client.list_groups_by_display_name_search_async( - search="Test" + result = await resolve_generated_result( + client.list_groups_by_display_name_search(search="Test") ) - assert result is not None - assert "@odata.count" in result + assert result == [{"id": "group1", "displayName": "Test Group"}] mock_send.assert_called_once() call_path = mock_send.call_args[0][1] assert "$search=Test" in call_path @@ -219,13 +219,15 @@ async def test_success_with_count_only(self, mock_credential, mock_response_succ with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - result = await client.list_groups_by_display_name_search_async() + result = await resolve_generated_result( + client.list_groups_by_display_name_search() + ) - assert result is not None + assert result == [] call_path = mock_send.call_args[0][1] assert "$search" not in call_path @@ -241,12 +243,12 @@ async def test_url_encodes_search_parameter(self, mock_credential, mock_response with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - await client.list_groups_by_display_name_search_async( - search="Test Group Name" + await resolve_generated_result( + client.list_groups_by_display_name_search(search="Test Group Name") ) call_path = mock_send.call_args[0][1] @@ -262,12 +264,14 @@ async def test_error_raises_exception(self, mock_credential, mock_response_error with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_error ): with pytest.raises(ConnectorException) as exc_info: - await client.list_groups_by_display_name_search_async() + await resolve_generated_result( + client.list_groups_by_display_name_search() + ) assert exc_info.value.status_code == 400 @@ -289,14 +293,13 @@ async def test_success_with_json_response(self, mock_credential, mock_response_s with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - result = await client.list_subscribed_skus_async() + result = await resolve_generated_result(client.list_subscribed_skus()) - assert result is not None - assert result["value"][0]["skuPartNumber"] == "ENTERPRISEPACK" + assert result[0]["skuPartNumber"] == "ENTERPRISEPACK" mock_send.assert_called_once_with( "GET", "https://example.azure.com/connections/test/v1.0/subscribedSkus", @@ -317,12 +320,12 @@ async def test_error_raises_exception(self, mock_credential, mock_response_error with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_error ): with pytest.raises(ConnectorException) as exc_info: - await client.list_subscribed_skus_async() + await resolve_generated_result(client.list_subscribed_skus()) assert exc_info.value.status_code == 400 @@ -345,18 +348,19 @@ async def test_success_with_all_parameters(self, mock_credential, mock_response_ with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - result = await client.list_direct_group_members_async( - group_id="group-123", - filter="userType eq 'Member'", - select="id,displayName" + result = await resolve_generated_result( + client.list_direct_group_members( + group_id="group-123", + filter="userType eq 'Member'", + select="id,displayName" + ) ) - assert result is not None - assert result["@odata.count"] == 5 + assert result == [{"id": "member1", "displayName": "Member One"}] call_path = mock_send.call_args[0][1] assert "/v1.0/groups/group-123/members" in call_path assert "$filter=userType%20eq%20%27Member%27" in call_path @@ -376,15 +380,15 @@ async def test_success_with_group_id_and_count_only( with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - result = await client.list_direct_group_members_async( - group_id="group-456" + result = await resolve_generated_result( + client.list_direct_group_members(group_id="group-456") ) - assert result is not None + assert result == [] call_path = mock_send.call_args[0][1] assert "/v1.0/groups/group-456/members" in call_path assert "$filter" not in call_path @@ -402,12 +406,12 @@ async def test_group_id_in_path(self, mock_credential, mock_response_success): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - await client.list_direct_group_members_async( - group_id="test-group-id" + await resolve_generated_result( + client.list_direct_group_members(group_id="test-group-id") ) call_path = mock_send.call_args[0][1] @@ -423,13 +427,13 @@ async def test_error_raises_exception(self, mock_credential, mock_response_error with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_error ): with pytest.raises(ConnectorException) as exc_info: - await client.list_direct_group_members_async( - group_id="group-123" + await resolve_generated_result( + client.list_direct_group_members(group_id="group-123") ) assert exc_info.value.status_code == 400 @@ -450,17 +454,19 @@ async def test_success_with_select_parameter(self, mock_credential, mock_respons with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - result = await client.get_member_license_details_async( - id="user-123", - select="skuId,servicePlans" + result = await resolve_generated_result( + client.list_member_license_details( + id="user-123", + select="skuId,servicePlans" + ) ) assert result is not None - assert result["value"][0]["skuId"] == "sku1" + assert result[0]["skuId"] == "sku1" call_path = mock_send.call_args[0][1] assert "/v1.0/users/user-123/licenseDetails" in call_path assert "$select=skuId%2CservicePlans" in call_path @@ -479,11 +485,13 @@ async def test_success_without_select_parameter( with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - result = await client.get_member_license_details_async(id="user-456") + result = await resolve_generated_result( + client.list_member_license_details(id="user-456") + ) assert result is not None call_path = mock_send.call_args[0][1] @@ -500,12 +508,14 @@ async def test_error_raises_exception(self, mock_credential, mock_response_error with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_error ): with pytest.raises(ConnectorException) as exc_info: - await client.get_member_license_details_async(id="user-123") + await resolve_generated_result( + client.list_member_license_details(id="user-123") + ) assert exc_info.value.status_code == 400 @@ -528,11 +538,11 @@ async def test_success_with_json_response(self, mock_credential, mock_response_s with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - result = await client.get_group_properties_async(group_id="group-123") + result = await client.get_group_properties(group_id="group-123") assert result is not None assert result["id"] == "group-123" @@ -559,11 +569,11 @@ async def test_group_id_in_path(self, mock_credential, mock_response_success): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - await client.get_group_properties_async(group_id="my-group-id") + await client.get_group_properties(group_id="my-group-id") call_path = mock_send.call_args[0][1] assert "groups/my-group-id" in call_path @@ -578,12 +588,12 @@ async def test_error_raises_exception(self, mock_credential, mock_response_error with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_error ): with pytest.raises(ConnectorException) as exc_info: - await client.get_group_properties_async(group_id="group-123") + await client.get_group_properties(group_id="group-123") assert exc_info.value.status_code == 400 @@ -607,17 +617,19 @@ async def test_success_with_security_enabled_only_true( with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - result = await client.get_member_groups_async( - input=input_data, - member_id="user-123" + result = await resolve_generated_result( + client.list_member_groups( + input=input_data, + member_id="user-123" + ) ) assert result is not None - assert len(result["value"]) == 3 + assert len(result) == 3 mock_send.assert_called_once_with( "POST", "https://example.azure.com/connections/test/v1.0/users/user-123/getMemberGroups", @@ -644,17 +656,19 @@ async def test_success_with_security_enabled_only_false( with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ): - result = await client.get_member_groups_async( - input=input_data, - member_id="user-456" + result = await resolve_generated_result( + client.list_member_groups( + input=input_data, + member_id="user-456" + ) ) assert result is not None - assert result["value"] == [] + assert result == [] @pytest.mark.asyncio async def test_member_id_in_path(self, mock_credential, mock_response_success): @@ -666,17 +680,19 @@ async def test_member_id_in_path(self, mock_credential, mock_response_success): mock_response_success.text = '{}' - input_data = GetMemberGroupsInput() + input_data = GetMemberGroupsInput(security_enabled_only=True) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - await client.get_member_groups_async( - input=input_data, - member_id="member-789" + await resolve_generated_result( + client.list_member_groups( + input=input_data, + member_id="member-789" + ) ) call_path = mock_send.call_args[0][1] @@ -694,14 +710,16 @@ async def test_error_raises_exception(self, mock_credential, mock_response_error with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_error ): with pytest.raises(ConnectorException) as exc_info: - await client.get_member_groups_async( - input=input_data, - member_id="user-123" + await resolve_generated_result( + client.list_member_groups( + input=input_data, + member_id="user-123" + ) ) assert exc_info.value.status_code == 400 @@ -805,13 +823,13 @@ async def test_multiple_consecutive_calls(self, mock_credential, mock_response_s with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ): - result1 = await client.list_users_async() - result2 = await client.list_subscribed_skus_async() - result3 = await client.get_group_properties_async(group_id="group-123") + result1 = await resolve_generated_result(client.list_users()) + result2 = await resolve_generated_result(client.list_subscribed_skus()) + result3 = await client.get_group_properties(group_id="group-123") assert result1 is not None assert result2 is not None @@ -831,12 +849,12 @@ async def test_json_parse_error_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(Exception): # JSON parse error - await client.list_users_async() + await resolve_generated_result(client.list_users()) @pytest.mark.asyncio async def test_boolean_parameter_conversion(self, mock_credential, mock_response_success): @@ -850,11 +868,13 @@ async def test_boolean_parameter_conversion(self, mock_credential, mock_response with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - await client.list_groups_by_display_name_search_async(search="Group") + await resolve_generated_result( + client.list_groups_by_display_name_search(search="Group") + ) call_path = mock_send.call_args[0][1] assert "$search=Group" in call_path @@ -873,14 +893,16 @@ async def test_empty_string_parameters_excluded( with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: - await client.list_direct_group_members_async( - group_id="group-123", - filter=None, - select=None + await resolve_generated_result( + client.list_direct_group_members( + group_id="group-123", + filter=None, + select=None + ) ) call_path = mock_send.call_args[0][1] @@ -899,12 +921,12 @@ async def test_special_characters_in_ids(self, mock_credential, mock_response_su with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: # ID with hyphen and numbers - await client.get_group_properties_async(group_id="abc-123-def-456") + await client.get_group_properties(group_id="abc-123-def-456") call_path = mock_send.call_args[0][1] assert "groups/abc-123-def-456" in call_path @@ -921,18 +943,20 @@ async def test_http_methods_used_correctly(self, mock_credential, mock_response_ with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response_success ) as mock_send: # GET methods - await client.list_users_async() + await resolve_generated_result(client.list_users()) assert mock_send.call_args[0][0] == "GET" - await client.get_group_properties_async(group_id="group-123") + await client.get_group_properties(group_id="group-123") assert mock_send.call_args[0][0] == "GET" # POST method - input_data = GetMemberGroupsInput() - await client.get_member_groups_async(input=input_data, member_id="user-123") + input_data = GetMemberGroupsInput(security_enabled_only=True) + await resolve_generated_result( + client.list_member_groups(input=input_data, member_id="user-123") + ) assert mock_send.call_args[0][0] == "POST" diff --git a/tests/test_office365.py b/tests/test_office365.py index 682dcbb..829affb 100644 --- a/tests/test_office365.py +++ b/tests/test_office365.py @@ -6,8 +6,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.office365 import Office365Client from azure.connectors.office365 import ( - Office365Client, DraftEmailInput, ClientReceiveFileAttachment, ClientReceiveMessage, @@ -18,7 +18,7 @@ MarkAsReadInput, MCPQueryRequest, ResponseToEventInvite, - CalendarEventBackend, + GraphCalendarEventClient, GetAttachmentResponse, SensitivityLabelMetadata, SendEmailInput, @@ -27,7 +27,7 @@ ConnectorException, ) from tests.conftest import MockResponse -from tests.generated_connector_test_utils import resolve_generated_result +from tests.generated_connector_test_utils import model_instance, resolve_generated_result class TestOffice365ClientInitialization: @@ -63,7 +63,7 @@ def test_init_with_custom_settings(self, mock_credential): client = Office365Client( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -118,11 +118,11 @@ async def test_success_uses_response_path_parameter(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=202, text=""), ) as mock_send: - await client.respond_to_event_async( + await client.respond_to_event( input=input_value, event_id="event/1", response="tentatively accept", @@ -149,12 +149,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=404, text="Event not found"), ): with pytest.raises(ConnectorException) as exc_info: - await client.respond_to_event_async( + await client.respond_to_event( input=ResponseToEventInvite(), event_id="missing", response="decline", @@ -188,16 +188,18 @@ async def test_success_with_json_response(self, mock_credential): mock_response = MockResponse( status=200, - text='{"value": [{"displayName": "Red category"}, {"displayName": "Blue category"}]}' + text='[{"displayName": "Red category"}, {"displayName": "Blue category"}]' ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_outlook_category_names_async() + result = await resolve_generated_result( + client.list_outlook_category_names() + ) mock_send.assert_called_once_with( "GET", @@ -208,8 +210,7 @@ async def test_success_with_json_response(self, mock_credential): client_request_id=None, response_hook=None, ) - assert "value" in result - assert len(result["value"]) == 2 + assert len(result) == 2 @pytest.mark.asyncio async def test_empty_response_returns_none(self, mock_credential): @@ -223,12 +224,14 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_outlook_category_names_async() - assert result is None + result = await resolve_generated_result( + client.list_outlook_category_names() + ) + assert result == [] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -245,12 +248,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_outlook_category_names_async() + await resolve_generated_result( + client.list_outlook_category_names() + ) assert exc_info.value.status_code == 401 @@ -273,12 +278,16 @@ async def test_success_with_body_and_no_query_params(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - input_message = DraftEmailInput() - result = await client.draft_email_async(input_message) + input_message = DraftEmailInput( + to="recipient@example.com", + subject="Test Email", + body="Hello", + ) + result = await client.draft_email(input_message) mock_send.assert_called_once_with( "POST", @@ -306,12 +315,16 @@ async def test_success_with_query_parameters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - input_message = DraftEmailInput() - await client.draft_email_async( + input_message = DraftEmailInput( + to="recipient@example.com", + subject="Test Email", + body="Hello", + ) + await client.draft_email( input_message, message_id="original123", draft_type="reply", @@ -339,12 +352,16 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.draft_email_async(DraftEmailInput()) + await client.draft_email(DraftEmailInput( + to="recipient@example.com", + subject="Test Email", + body="Hello", + )) assert exc_info.value.status_code == 400 @@ -364,12 +381,16 @@ async def test_success_no_return_value(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - input_message = DraftEmailInput() - result = await client.update_draft_email_async(input_message, "message123") + input_message = DraftEmailInput( + to="recipient@example.com", + subject="Test Email", + body="Hello", + ) + result = await client.update_draft_email(input_message, "message123") call_args = mock_send.call_args assert call_args[0][0] == "PATCH" @@ -389,13 +410,17 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - input_message = DraftEmailInput() - await client.update_draft_email_async(input_message, "nonexistent") + input_message = DraftEmailInput( + to="recipient@example.com", + subject="Test Email", + body="Hello", + ) + await client.update_draft_email(input_message, "nonexistent") assert exc_info.value.status_code == 404 @@ -415,11 +440,11 @@ async def test_success_with_path_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.send_draft_email_async("message123") + result = await client.send_draft_email("message123") # NOTE: The generated code uses template syntax instead of f-string interpolation call_args = mock_send.call_args @@ -439,11 +464,11 @@ async def test_path_parameter_construction(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.send_draft_email_async("test123") + await client.send_draft_email("test123") call_args = mock_send.call_args path = call_args[0][1] @@ -461,12 +486,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.send_draft_email_async("nonexistent") + await client.send_draft_email("nonexistent") assert exc_info.value.status_code == 404 @@ -486,11 +511,11 @@ async def test_success_with_multiple_query_params(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.assign_category_async( + await client.assign_category( message_id="msg123", category="Red category" ) @@ -512,12 +537,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.assign_category_async( + await client.assign_category( message_id="nonexistent", category="Red category" ) @@ -540,11 +565,11 @@ async def test_delete_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.delete_email_async("message123") + result = await client.delete_email("message123") call_args = mock_send.call_args assert call_args[0][0] == "DELETE" @@ -572,11 +597,11 @@ async def test_success_with_complex_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_email_async("message123") + result = await client.get_email("message123") assert result["id"] == "msg123" assert result["subject"] == "Test" @@ -601,14 +626,16 @@ async def test_success_with_filtering_and_pagination(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_emails_async( - folder_path="Inbox", - top="10", - search_query="subject:Important" + await resolve_generated_result( + client.list_emails( + folder_path="Inbox", + top=10, + search_query="subject:Important" + ) ) call_args = mock_send.call_args @@ -633,12 +660,16 @@ async def test_send_email_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - email_message = SendEmailInput() - result = await client.send_email_async(email_message) + email_message = SendEmailInput( + to="recipient@example.com", + subject="Test Email", + body="Hello", + ) + result = await client.send_email(email_message) call_args = mock_send.call_args assert call_args[0][0] == "POST" @@ -665,7 +696,7 @@ async def test_success_with_input_schema(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): @@ -674,7 +705,7 @@ async def test_success_with_input_schema(self, mock_credential): meeting_duration=60, max_candidates=5 ) - result = await client.find_meeting_times_async(input_data) + result = await client.find_meeting_times(input_data) assert "emptySuggestionsReason" in result @@ -700,11 +731,11 @@ async def test_success_with_attachment_data(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_attachment_async("message123", "att123") + result = await client.get_attachment("message123", "att123") assert result["id"] == "att123" assert result["name"] == "document.pdf" @@ -729,12 +760,12 @@ async def test_success_without_session_id(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: request = MCPQueryRequest(jsonrpc="2.0", id="1", method="list") - result = await client.mcp_emails_management_async(request) + result = await client.mcp_emails_management(request) mock_send.assert_called_once_with( "POST", @@ -762,12 +793,12 @@ async def test_success_with_session_id(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: request = MCPQueryRequest(jsonrpc="2.0", id="2", method="init") - await client.mcp_emails_management_async( + await client.mcp_emails_management( request, session_id="session-abc" ) @@ -795,13 +826,14 @@ async def test_get_calendars(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.calendar_get_tables_async() - assert "value" in result - assert len(result["value"]) == 1 + result = await resolve_generated_result( + client.list_calendar_get_tables() + ) + assert len(result) == 1 @pytest.mark.asyncio async def test_create_calendar_event(self, mock_credential): @@ -818,12 +850,12 @@ async def test_create_calendar_event(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - event = CalendarEventBackend() - result = await client.calendar_post_item_async("Calendar", event) + event = model_instance(GraphCalendarEventClient) + result = await client.calendar_post_item("Calendar", event) call_args = mock_send.call_args assert call_args[0][0] == "POST" @@ -841,11 +873,11 @@ async def test_delete_calendar_event(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.calendar_delete_item_async("Calendar", "event123") + result = await client.calendar_delete_item("Calendar", "event123") call_args = mock_send.call_args assert call_args[0][0] == "DELETE" @@ -870,11 +902,11 @@ async def test_get_contacts(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await resolve_generated_result(client.contact_get_items_async("Contacts")) + result = await resolve_generated_result(client.list_contact_get_items("Contacts")) assert result diff --git a/tests/test_office365groups.py b/tests/test_office365groups.py index d84fdb4..90ed1eb 100644 --- a/tests/test_office365groups.py +++ b/tests/test_office365groups.py @@ -6,8 +6,8 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.office365groups import Office365groupsClient from azure.connectors.office365groups import ( - Office365groupsClient, ListGroupMembersResponse, OnGroupMemberAddedOrRemovedResponse, ListGroupsResponse, @@ -60,7 +60,7 @@ def test_init_with_custom_settings(self, mock_credential): client = Office365groupsClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -140,12 +140,12 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: result = await resolve_generated_result( - client.list_group_members_async(group_id="group-123") + client.list_group_members(group_id="group-123") ) mock_send.assert_called_once() @@ -168,12 +168,12 @@ async def test_with_top_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: await resolve_generated_result( - client.list_group_members_async(group_id="group-123", top="10") + client.list_group_members(group_id="group-123", top="10") ) call_args = mock_send.call_args @@ -191,12 +191,12 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): result = await resolve_generated_result( - client.list_group_members_async(group_id="group-123") + client.list_group_members(group_id="group-123") ) assert result == [] @@ -212,13 +212,13 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): await resolve_generated_result( - client.list_group_members_async(group_id="group-123") + client.list_group_members(group_id="group-123") ) @@ -240,11 +240,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.list_groups_async()) + result = await resolve_generated_result(client.list_groups()) mock_send.assert_called_once() assert result is not None @@ -262,12 +262,12 @@ async def test_with_filter_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: await resolve_generated_result( - client.list_groups_async(filter="displayName eq 'Engineering'") + client.list_groups(filter="displayName eq 'Engineering'") ) call_args = mock_send.call_args @@ -285,11 +285,11 @@ async def test_with_pagination_parameters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.list_groups_async(top="50", skiptoken="token123")) + await resolve_generated_result(client.list_groups(top="50", skiptoken="token123")) call_args = mock_send.call_args path = call_args[0][1] @@ -312,11 +312,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.add_member_to_group_async( + await client.add_member_to_group( group_id="group-123", user_upn="user@contoso.com" ) @@ -342,11 +342,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.remove_member_from_group_async( + await client.remove_member_from_group( group_id="group-123", user_upn="user@contoso.com" ) @@ -374,16 +374,18 @@ async def test_success(self, mock_credential): event_input = UpdateCalendarEventHTMLRequest( subject="Team Meeting", + start={"dateTime": "2026-10-12T09:00:00Z"}, + end={"dateTime": "2026-10-12T10:00:00Z"}, is_all_day=False ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_calendar_event_async( + result = await client.create_calendar_event( input=event_input, group_id="group-123" ) @@ -410,16 +412,18 @@ async def test_success(self, mock_credential): ) event_input = UpdateCalendarEventHTMLRequest( - subject="Updated Meeting" + subject="Updated Meeting", + start={"dateTime": "2026-10-12T09:00:00Z"}, + end={"dateTime": "2026-10-12T10:00:00Z"}, ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.update_calendar_event_async( + result = await client.update_calendar_event( input=event_input, event="event-123", group_id="group-123" @@ -446,11 +450,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.calendar_delete_item_async( + await client.calendar_delete_item( event="event-123", group_id="group-123" ) @@ -478,11 +482,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.list_deleted_groups_async()) + result = await resolve_generated_result(client.list_deleted_groups()) mock_send.assert_called_once() assert result is not None @@ -500,11 +504,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await resolve_generated_result(client.list_deleted_groups_async()) + result = await resolve_generated_result(client.list_deleted_groups()) assert result == [] @@ -523,11 +527,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.restore_deleted_group_async(group_id="deleted-group-123") + await client.restore_deleted_group(group_id="deleted-group-123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -553,15 +557,14 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.list_owned_groups_async() + result = await resolve_generated_result(client.list_owned_groups()) mock_send.assert_called_once() - assert result is not None - assert "value" in result + assert result == [{"id": "my-group", "displayName": "My Team"}] class TestHttpRequestAsync: @@ -584,11 +587,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.http_request_async(input=request_input) + result = await client.http_request(input=request_input) mock_send.assert_called_once() assert result is not None @@ -607,12 +610,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await client.http_request_async(input=request_input) + await client.http_request(input=request_input) class TestOnGroupMembershipChangeAsync: @@ -657,11 +660,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.list_deleted_groups_by_owner_async()) + result = await resolve_generated_result(client.list_deleted_groups_by_owner()) mock_send.assert_called_once() call_args = mock_send.call_args @@ -762,16 +765,22 @@ def test_list_owned_groups_response_versioned_defaults(self): assert response.context is None assert response.value is None - def test_update_calendar_event_request_defaults(self): - """Test UpdateCalendarEventRequest default values.""" - request = UpdateCalendarEventRequest() - assert request.subject is None + def test_update_calendar_event_request_optional_defaults(self): + """Test UpdateCalendarEventRequest optional default values.""" + request = UpdateCalendarEventRequest( + subject="Team Meeting", + start={"dateTime": "2026-10-12T09:00:00Z"}, + end={"dateTime": "2026-10-12T10:00:00Z"}, + ) + assert request.subject == "Team Meeting" assert request.is_all_day is None def test_update_calendar_event_request_with_values(self): """Test UpdateCalendarEventRequest with values.""" request = UpdateCalendarEventRequest( subject="Team Standup", + start={"dateTime": "2026-10-12T09:00:00Z"}, + end={"dateTime": "2026-10-12T09:30:00Z"}, importance="Normal", is_all_day=False, is_reminder_on=True, @@ -781,16 +790,22 @@ def test_update_calendar_event_request_with_values(self): assert request.is_reminder_on is True assert request.reminder_minutes_before_start == 15 - def test_update_calendar_event_html_request_defaults(self): - """Test UpdateCalendarEventHTMLRequest default values.""" - request = UpdateCalendarEventHTMLRequest() - assert request.subject is None + def test_update_calendar_event_html_request_optional_defaults(self): + """Test UpdateCalendarEventHTMLRequest optional default values.""" + request = UpdateCalendarEventHTMLRequest( + subject="HTML Meeting", + start={"dateTime": "2026-10-12T09:00:00Z"}, + end={"dateTime": "2026-10-12T10:00:00Z"}, + ) + assert request.subject == "HTML Meeting" assert request.body is None def test_update_calendar_event_html_request_with_values(self): """Test UpdateCalendarEventHTMLRequest with values.""" request = UpdateCalendarEventHTMLRequest( subject="HTML Meeting", + start={"dateTime": "2026-10-12T09:00:00Z"}, + end={"dateTime": "2026-10-12T10:00:00Z"}, body={"contentType": "HTML", "content": "

Meeting details

"}, is_all_day=True ) @@ -813,11 +828,11 @@ async def test_pageable_group_operation_empty_response_yields_no_items( "https://example.azure.com/connections/test", credential=mock_credential, ) - method = getattr(client, f"{operation}_async") + method = getattr(client, f"{operation}") arguments = {"group_id": "group-123"} if operation == "list_group_members" else {} with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text=""), ): diff --git a/tests/test_office365groupsmail.py b/tests/test_office365groupsmail.py index 82660c4..019aef7 100644 --- a/tests/test_office365groupsmail.py +++ b/tests/test_office365groupsmail.py @@ -6,12 +6,13 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.office365groupsmail import Office365groupsmailClient from azure.connectors.office365groupsmail import ( Conversation, CreateConversationBody, ForwardPostBody, + GetUsersGraphAction, ListConversationsResponse, - Office365groupsmailClient, ReplyConversationThreadBody, TRIGGER_OPERATIONS, ) @@ -20,93 +21,93 @@ ) from azure.connectors.sdk.serialization import to_wire from tests.conftest import MockResponse -from tests.generated_connector_test_utils import resolve_generated_result +from tests.generated_connector_test_utils import model_instance, resolve_generated_result async def _invoke_operation(client: Office365groupsmailClient, operation: str): """Invoke an operation by name for shared parameterized tests.""" if operation == "list_conversations": - return await resolve_generated_result(client.list_conversations_async(group_id="group123")) + return await resolve_generated_result(client.list_conversations(group_id="group123")) if operation == "create_conversation": - return await client.create_conversation_async( + return await client.create_conversation( input=CreateConversationBody(topic="Hello"), group_id="group123", ) if operation == "get_group_conversation": - return await client.get_group_conversation_async( + return await client.get_group_conversation( group_id="group123", conversation_id="conv123", ) if operation == "list_conversation_threads": - return await resolve_generated_result(client.list_conversation_threads_async( + return await resolve_generated_result(client.list_conversation_threads( group_id="group123", conversation_id="conv123", )) if operation == "create_conversation_thread": - return await client.create_conversation_thread_async( + return await client.create_conversation_thread( input=CreateConversationBody(topic="Thread"), group_id="group123", conversation_id="conv123", ) if operation == "list_group_threads": - return await resolve_generated_result(client.list_group_threads_async(group_id="group123")) + return await resolve_generated_result(client.list_group_threads(group_id="group123")) if operation == "create_group_thread": - return await client.create_group_thread_async( + return await client.create_group_thread( input=CreateConversationBody(topic="Group thread"), group_id="group123", ) if operation == "get_conversation_thread": - return await client.get_conversation_thread_async( + return await client.get_conversation_thread( group_id="group123", thread_id="thread123", ) if operation == "delete_conversation_thread": - return await client.delete_conversation_thread_async( + return await client.delete_conversation_thread( group_id="group123", thread_id="thread123", ) if operation == "list_thread_posts": - return await resolve_generated_result(client.list_thread_posts_async( + return await resolve_generated_result(client.list_thread_posts( group_id="group123", thread_id="thread123", )) if operation == "get_thread": - return await client.get_thread_async( + return await client.get_thread( group_id="group123", thread_id="thread123", post_id="post123", ) - if operation == "get_attachments": - return await resolve_generated_result(client.get_attachments_async( + if operation == "list_attachments": + return await resolve_generated_result(client.list_attachments( group_id="group123", thread_id="thread123", post_id="post123", )) if operation == "reply_to_a_thread": - return await client.reply_to_a_thread_async( + return await client.reply_to_a_thread( input=ReplyConversationThreadBody(), group_id="group123", thread_id="thread123", ) if operation == "reply": - return await client.reply_async( + return await client.reply( input=ReplyConversationThreadBody(), group_id="group123", thread_id="thread123", post_id="post123", ) if operation == "http_request": - return await client.http_request_async(input=b"request") + return await client.http_request(input=b"request") if operation == "forward": - return await client.forward_async( - input=ForwardPostBody(comment="Forward this"), + return await client.forward( + input=model_instance(ForwardPostBody, comment="Forward this"), group_mail="group@contoso.com", conversation_id="conv123", thread_id="thread123", post_id="post123", ) if operation == "list_groups": - return await client.list_groups_async() + return await resolve_generated_result(client.list_groups()) raise ValueError(f"Unsupported operation '{operation}'.") @@ -144,7 +145,7 @@ def test_init_with_custom_settings(self, mock_credential): client = Office365groupsmailClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -202,12 +203,12 @@ async def test_list_conversations_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: result = await resolve_generated_result( - client.list_conversations_async(group_id="group123") + client.list_conversations(group_id="group123") ) assert len(result) == 1 @@ -224,11 +225,11 @@ async def test_create_conversation_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_conversation_async( + result = await client.create_conversation( input=CreateConversationBody(topic="Hi"), group_id="group123", ) @@ -247,11 +248,11 @@ async def test_get_thread_expands_attachments(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.get_thread_async( + await client.get_thread( group_id="group123", thread_id="thread123", post_id="post123", @@ -270,11 +271,11 @@ async def test_list_groups_uses_expected_filters(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.list_groups_async() + await resolve_generated_result(client.list_groups()) call_path = mock_send.call_args[0][1] assert "$filter=" in call_path @@ -300,7 +301,7 @@ class TestOffice365groupsmailClientErrorHandling: "delete_conversation_thread", "list_thread_posts", "get_thread", - "get_attachments", + "list_attachments", "reply_to_a_thread", "reply", "http_request", @@ -322,7 +323,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -359,6 +360,12 @@ def test_dataclass_instances_initialize_expected_defaults(self): def test_forward_post_body_uses_swagger_wire_names(self): """Test the current forward-post request preserves Swagger casing.""" - request = ForwardPostBody(comment="Please review") + request = ForwardPostBody( + to_recipients=[GetUsersGraphAction()], + comment="Please review", + ) - assert to_wire(request) == {"Comment": "Please review"} + assert to_wire(request) == { + "Comment": "Please review", + "ToRecipients": [{}], + } diff --git a/tests/test_office365users.py b/tests/test_office365users.py index aa7f690..4374c90 100644 --- a/tests/test_office365users.py +++ b/tests/test_office365users.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.office365users import Office365usersClient from azure.connectors.office365users import ( - Office365usersClient, GraphUserUpdateable, ) from azure.connectors.sdk import ( @@ -49,7 +49,7 @@ def test_init_with_custom_settings(self, mock_credential): client = Office365usersClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -118,11 +118,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.update_my_profile_async(input=profile_input) + await client.update_my_profile(input=profile_input) mock_send.assert_called_once() call_args = mock_send.call_args @@ -146,11 +146,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.update_my_photo_async(input=photo_input) + await client.update_my_photo(input=photo_input) mock_send.assert_called_once() call_args = mock_send.call_args @@ -176,15 +176,16 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.my_trending_documents_async() + result = await resolve_generated_result( + client.list_my_trending_documents() + ) mock_send.assert_called_once() - assert "value" in result - assert len(result["value"]) == 1 + assert len(result) == 1 @pytest.mark.asyncio async def test_with_filter_parameter(self, mock_credential): @@ -198,11 +199,13 @@ async def test_with_filter_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.my_trending_documents_async(filter="resourceVisualization/type eq 'Excel'") + await resolve_generated_result(client.list_my_trending_documents( + filter="resourceVisualization/type eq 'Excel'" + )) call_args = mock_send.call_args assert "$filter=" in call_args[0][1] @@ -219,12 +222,14 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.my_trending_documents_async() - assert result is None + result = await resolve_generated_result( + client.list_my_trending_documents() + ) + assert result == [] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -238,12 +243,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.my_trending_documents_async() + await resolve_generated_result( + client.list_my_trending_documents() + ) assert exc_info.value.status_code == 401 @@ -266,16 +273,18 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.relevant_people_async(user_id="user123") + result = await resolve_generated_result( + client.list_relevant_people(user_id="user123") + ) mock_send.assert_called_once() call_args = mock_send.call_args assert "users/user123/relevantpeople" in call_args[0][1] - assert "value" in result + assert result[0]["id"] == "person1" @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -289,12 +298,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.relevant_people_async(user_id="invalid") + await resolve_generated_result( + client.list_relevant_people(user_id="invalid") + ) assert exc_info.value.status_code == 404 @@ -317,11 +328,11 @@ async def test_success_with_user_id(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.user_photo_metadata_async(user_id="user123") + result = await client.user_photo_metadata(user_id="user123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -340,11 +351,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.user_photo_metadata_async(user_id=None) + result = await client.user_photo_metadata(user_id=None) assert result is None @@ -366,16 +377,18 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.trending_documents_async(id="user123") + result = await resolve_generated_result( + client.list_trending_documents(id="user123") + ) mock_send.assert_called_once() call_args = mock_send.call_args assert "users/user123/insights/trending" in call_args[0][1] - assert "value" in result + assert result[0]["id"] == "doc1" @pytest.mark.asyncio async def test_with_filter_parameter(self, mock_credential): @@ -389,13 +402,15 @@ async def test_with_filter_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.trending_documents_async( - id="user123", - filter="resourceVisualization/type eq 'Word'" + await resolve_generated_result( + client.list_trending_documents( + id="user123", + filter="resourceVisualization/type eq 'Word'" + ) ) call_args = mock_send.call_args @@ -413,12 +428,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.trending_documents_async(id="user123") + await resolve_generated_result( + client.list_trending_documents(id="user123") + ) assert exc_info.value.status_code == 500 @@ -442,11 +459,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.http_request_async(input=request_input) + result = await client.http_request(input=request_input) mock_send.assert_called_once() call_args = mock_send.call_args @@ -466,11 +483,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.http_request_async(input=b"request content") + result = await client.http_request(input=b"request content") assert result is None @pytest.mark.asyncio @@ -485,12 +502,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.http_request_async(input=b"request content") + await client.http_request(input=b"request content") assert exc_info.value.status_code == 400 @@ -513,16 +530,18 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.direct_reports_async(id="manager123") + result = await resolve_generated_result( + client.list_direct_reports(id="manager123") + ) mock_send.assert_called_once() call_args = mock_send.call_args assert "users/manager123/directReports" in call_args[0][1] - assert "value" in result + assert result[0]["id"] == "report1" @pytest.mark.asyncio async def test_with_select_and_top_parameters(self, mock_credential): @@ -536,14 +555,16 @@ async def test_with_select_and_top_parameters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.direct_reports_async( - id="manager123", - select="displayName,mail", - top="10" + await resolve_generated_result( + client.list_direct_reports( + id="manager123", + select="displayName,mail", + top=10 + ) ) call_args = mock_send.call_args @@ -562,12 +583,14 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.direct_reports_async(id="manager123") - assert result is None + result = await resolve_generated_result( + client.list_direct_reports(id="manager123") + ) + assert result == [] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -581,12 +604,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.direct_reports_async(id="manager123") + await resolve_generated_result( + client.list_direct_reports(id="manager123") + ) assert exc_info.value.status_code == 403 @@ -609,11 +634,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.manager_async(id="user123") + result = await client.manager(id="user123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -632,11 +657,11 @@ async def test_with_select_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.manager_async(id="user123", select="displayName") + await client.manager(id="user123", select="displayName") call_args = mock_send.call_args assert "$select=displayName" in call_args[0][1] @@ -653,12 +678,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.manager_async(id="user123") + await client.manager(id="user123") assert exc_info.value.status_code == 404 @@ -681,11 +706,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.my_profile_async() + result = await client.my_profile() mock_send.assert_called_once() call_args = mock_send.call_args @@ -704,11 +729,11 @@ async def test_with_select_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.my_profile_async(select="displayName,mail") + await client.my_profile(select="displayName,mail") call_args = mock_send.call_args assert "$select=" in call_args[0][1] @@ -725,11 +750,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.my_profile_async() + result = await client.my_profile() assert result is None @pytest.mark.asyncio @@ -744,12 +769,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.my_profile_async() + await client.my_profile() assert exc_info.value.status_code == 401 @@ -772,11 +797,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.search_user_async(search_term="John")) + result = await resolve_generated_result(client.list_search_user(search_term="John")) mock_send.assert_called_once() call_args = mock_send.call_args @@ -795,11 +820,11 @@ async def test_with_all_parameters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.search_user_async( + await resolve_generated_result(client.list_search_user( search_term="John", top=25, is_search_term_required=True @@ -822,11 +847,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await resolve_generated_result(client.search_user_async()) + result = await resolve_generated_result(client.list_search_user()) assert result == [] @pytest.mark.asyncio @@ -841,12 +866,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(client.search_user_async(search_term="test")) + await resolve_generated_result(client.list_search_user(search_term="test")) assert exc_info.value.status_code == 500 @@ -867,11 +892,11 @@ async def test_success_returns_binary_content(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.user_photo_async(id="user123") + result = await client.user_photo(id="user123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -890,12 +915,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.user_photo_async(id="user123") + await client.user_photo(id="user123") assert exc_info.value.status_code == 404 @@ -918,11 +943,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.user_profile_async(id="user123") + result = await client.user_profile(id="user123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -941,11 +966,11 @@ async def test_with_select_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.user_profile_async(id="user123", select="displayName,mail,jobTitle") + await client.user_profile(id="user123", select="displayName,mail,jobTitle") call_args = mock_send.call_args assert "$select=" in call_args[0][1] @@ -962,11 +987,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.user_profile_async(id="user123") + result = await client.user_profile(id="user123") assert result is None @pytest.mark.asyncio @@ -981,11 +1006,11 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.user_profile_async(id="invalid_user") + await client.user_profile(id="invalid_user") assert exc_info.value.status_code == 404 diff --git a/tests/test_onedrive.py b/tests/test_onedrive.py index c41aae1..d86a055 100644 --- a/tests/test_onedrive.py +++ b/tests/test_onedrive.py @@ -7,8 +7,8 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.onedrive import OnedriveClient from azure.connectors.onedrive import ( - OnedriveClient, BlobMetadata, BlobMetadataPage, SharingLink, @@ -55,7 +55,7 @@ def test_init_with_custom_settings(self, mock_credential): client = OnedriveClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -126,11 +126,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_file_metadata_async(id="file123") + result = await client.get_file_metadata(id="file123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -150,11 +150,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_file_metadata_async(id="file123") + result = await client.get_file_metadata(id="file123") assert result is None @@ -166,18 +166,18 @@ async def test_error_response_raises_exception(self, mock_credential): credential=mock_credential ) - mock_response = MockResponse(status=404, text='{"error": "File not found"}') + mock_response = MockResponse(status=500, text='{"error": "Server error"}') with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_file_metadata_async(id="nonexistent") + await client.get_file_metadata(id="nonexistent") - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestGetFileContent: @@ -197,11 +197,11 @@ async def test_success_returns_binary_content(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_file_content_async(id="file123") + result = await client.get_file_content(id="file123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -222,11 +222,11 @@ async def test_with_infer_content_type_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_file_content_async( + await client.get_file_content( id="file123", infer_content_type="true" ) @@ -246,12 +246,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_file_content_async(id="nonexistent") + await client.get_file_content(id="nonexistent") assert exc_info.value.status_code == 404 @@ -273,11 +273,11 @@ async def test_success_returns_binary_content(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_file_content_by_path_async( + result = await client.get_file_content_by_path( path="/Documents/file.txt" ) @@ -299,12 +299,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_file_content_by_path_async(path="/invalid/path") + await client.get_file_content_by_path(path="/invalid/path") assert exc_info.value.status_code == 404 @@ -327,12 +327,12 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = b"file content" - result = await client.create_file_async( + result = await client.create_file( input=input_data, folder_path="/Documents", name="newfile.txt" @@ -357,12 +357,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_file_async( + await client.create_file( input=b"file content", folder_path="/invalid", name="file.txt" @@ -389,12 +389,12 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = b"updated content" - result = await client.update_file_async( + result = await client.update_file( input=input_data, id="file123" ) @@ -417,12 +417,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.update_file_async( + await client.update_file( input=b"updated content", id="nonexistent" ) @@ -445,11 +445,11 @@ async def test_success_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.delete_file_async(id="file123") + await client.delete_file(id="file123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -464,18 +464,18 @@ async def test_error_response_raises_exception(self, mock_credential): credential=mock_credential ) - mock_response = MockResponse(status=404, text='{"error": "File not found"}') + mock_response = MockResponse(status=500, text='{"error": "Server error"}') with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.delete_file_async(id="nonexistent") + await client.delete_file(id="nonexistent") - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestCopyFile: @@ -496,11 +496,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.copy_file_async( + result = await client.copy_file( source="https://example.com/source.txt", destination="/Documents/destination.txt" ) @@ -525,11 +525,11 @@ async def test_with_overwrite_parameter(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.copy_file_async( + await client.copy_file( source="https://example.com/source.txt", destination="/Documents/destination.txt", overwrite="true" @@ -550,12 +550,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.copy_file_async( + await client.copy_file( source="invalid", destination="invalid" ) @@ -581,11 +581,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.copy_drive_file_async( + result = await client.copy_drive_file( id="sourcefile123", destination="/Documents/copy.txt" ) @@ -609,12 +609,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.copy_drive_file_async( + await client.copy_drive_file( id="nonexistent", destination="/Documents/copy.txt" ) @@ -640,11 +640,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.move_file_async( + result = await client.move_file( id="file123", destination="/Archive/moved_file.txt" ) @@ -668,12 +668,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.move_file_async( + await client.move_file( id="nonexistent", destination="/Archive/file.txt" ) @@ -700,11 +700,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.list_folder_async(id="folder123")) + result = await resolve_generated_result(client.list_folder(id="folder123")) mock_send.assert_called_once() call_args = mock_send.call_args @@ -726,23 +726,25 @@ async def test_success_with_json_response(self, mock_credential): mock_response = MockResponse( status=200, - text='{"value": [{"id": "folder1", "name": "Documents"}, ' - '{"id": "folder2", "name": "Pictures"}]}' + text=( + '[{"id": "folder1", "name": "Documents"}, ' + '{"id": "folder2", "name": "Pictures"}]' + ) ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.list_root_folder_async() + result = await resolve_generated_result(client.list_root_folder()) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/folders" in call_args[0][1] - assert len(result["value"]) == 2 + assert len(result) == 2 class TestFindFiles: @@ -758,19 +760,21 @@ async def test_success_with_json_response(self, mock_credential): mock_response = MockResponse( status=200, - text='{"value": [{"id": "file1", "name": "report.docx"}]}' + text='[{"id": "file1", "name": "report.docx"}]' ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.find_files_async( - id="folder123", - query="report", - find_mode="search" + result = await resolve_generated_result( + client.list_find_files( + id="folder123", + query="report", + find_mode="search" + ) ) mock_send.assert_called_once() @@ -778,7 +782,7 @@ async def test_success_with_json_response(self, mock_credential): assert call_args[0][0] == "GET" assert "/search" in call_args[0][1] assert "query=report" in call_args[0][1] - assert len(result["value"]) == 1 + assert len(result) == 1 class TestCreateShareLink: @@ -799,11 +803,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_share_link_async( + result = await client.create_share_link( id="file123", type_="view" ) @@ -829,22 +833,24 @@ async def test_success_with_json_response(self, mock_credential): mock_response = MockResponse( status=200, - text='{"tags": ["important", "work", "2026"]}' + text='{"Tags": ["important", "work", "2026"]}' ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_file_tags_async(id="file123") + result = await resolve_generated_result( + client.list_file_tags(id="file123") + ) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/tags" in call_args[0][1] - assert "important" in result["tags"] + assert "important" in result class TestAddFileTag: @@ -860,18 +866,20 @@ async def test_success_with_json_response(self, mock_credential): mock_response = MockResponse( status=200, - text='{"tags": ["important", "work", "new-tag"]}' + text='{"Tags": ["important", "work", "new-tag"]}' ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.add_file_tag_async( - id="file123", - tag="new-tag" + await resolve_generated_result( + client.add_file_tag( + id="file123", + tag="new-tag" + ) ) mock_send.assert_called_once() @@ -896,11 +904,11 @@ async def test_success_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.remove_file_tag_async( + await client.remove_file_tag( id="file123", tag="old-tag" ) @@ -930,11 +938,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_file_thumbnail_async( + result = await client.get_file_thumbnail( id="file123", size="medium" ) @@ -964,11 +972,11 @@ async def test_success_returns_binary_content(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.convert_file_async( + result = await client.convert_file( id="file123", type_="pdf" ) @@ -994,18 +1002,20 @@ async def test_success_with_json_response(self, mock_credential): mock_response = MockResponse( status=200, - text='{"id": "folder123", "name": "extracted"}' + text='[{"id": "folder123", "name": "extracted"}]' ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.extract_folder_async( - source="/Documents/archive.zip", - destination="/Documents/extracted" + await resolve_generated_result( + client.extract_folder( + source="/Documents/archive.zip", + destination="/Documents/extracted" + ) ) mock_send.assert_called_once() @@ -1088,11 +1098,11 @@ async def test_special_characters_in_path(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_file_metadata_by_path_async( + await client.get_file_metadata_by_path( path="/Documents/My File (2026).docx" ) @@ -1112,15 +1122,15 @@ async def test_multiple_consecutive_calls(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - await client.get_file_metadata_async(id="file1") - await client.get_file_metadata_async(id="file2") - await client.get_file_metadata_async(id="file3") + await client.get_file_metadata(id="file1") + await client.get_file_metadata(id="file2") + await client.get_file_metadata(id="file3") - assert client._http_client.send_async.call_count == 3 + assert client._http_client.send.call_count == 3 @pytest.mark.asyncio async def test_http_client_property_access(self, mock_credential): diff --git a/tests/test_onedriveforbusiness.py b/tests/test_onedriveforbusiness.py index 03df2c9..d9f9475 100644 --- a/tests/test_onedriveforbusiness.py +++ b/tests/test_onedriveforbusiness.py @@ -7,11 +7,11 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.onedriveforbusiness import OnedriveforbusinessClient from azure.connectors.onedriveforbusiness import ( BlobMetadata, BlobMetadataPage, ForASelectedFileResponse, - OnedriveforbusinessClient, SharingLink, Tags, Thumbnail, @@ -24,14 +24,14 @@ METHOD_ARGUMENTS: list[tuple[str, dict]] = [ - ("get_file_metadata_async", {"id": "file123"}), - ("update_file_async", {"id": "file123", "input": b"updated content"}), - ("delete_file_async", {"id": "file123"}), - ("get_file_metadata_by_path_async", {"path": "/Documents/file.txt"}), - ("get_file_content_by_path_async", {"path": "/Documents/file.txt"}), - ("get_file_content_async", {"id": "file123"}), + ("get_file_metadata", {"id": "file123"}), + ("update_file", {"id": "file123", "input": b"updated content"}), + ("delete_file", {"id": "file123"}), + ("get_file_metadata_by_path", {"path": "/Documents/file.txt"}), + ("get_file_content_by_path", {"path": "/Documents/file.txt"}), + ("get_file_content", {"id": "file123"}), ( - "create_file_async", + "create_file", { "input": b"file content", "folder_path": "/Documents", @@ -39,51 +39,51 @@ }, ), ( - "copy_file_async", + "copy_file", {"source": "https://contoso.com/file.txt", "destination": "/Documents/copy.txt"}, ), ( - "copy_drive_file_async", + "copy_drive_file", {"id": "file123", "destination": "/Documents/copy.txt"}, ), ( - "copy_drive_file_by_path_async", + "copy_drive_file_by_path", {"source": "/Documents/source.txt", "destination": "/Documents/copy.txt"}, ), ( - "move_file_async", + "move_file", {"id": "file123", "destination": "/Documents/moved.txt"}, ), ( - "move_file_by_path_async", + "move_file_by_path", {"source": "/Documents/source.txt", "destination": "/Documents/moved.txt"}, ), - ("convert_file_async", {"id": "file123"}), - ("convert_file_by_path_async", {"path": "/Documents/file.docx"}), - ("get_file_thumbnail_async", {"id": "file123", "size": "small"}), - ("list_root_folder_async", {}), + ("convert_file", {"id": "file123"}), + ("convert_file_by_path", {"path": "/Documents/file.docx"}), + ("get_file_thumbnail", {"id": "file123", "size": "small"}), + ("list_root_folder", {}), ( - "find_files_async", + "list_find_files", {"id": "folder123", "query": "report", "find_mode": "search"}, ), ( - "find_files_by_path_async", + "list_find_files_by_path", { "query": "report", "path": "/Documents", "find_mode": "search", }, ), - ("create_share_link_async", {"id": "file123", "type_": "view"}), + ("create_share_link", {"id": "file123", "type_": "view"}), ( - "create_share_link_by_path_async", + "create_share_link_by_path", {"path": "/Documents/file.txt", "type_": "view"}, ), ( - "extract_folder_async", + "extract_folder", {"source": "/Documents/archive.zip", "destination": "/Documents/extracted"}, ), - ("list_folder_async", {"id": "folder123"}), + ("list_folder", {"id": "folder123"}), ] @@ -113,7 +113,7 @@ def test_init_with_custom_settings(self, mock_credential): client = OnedriveforbusinessClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -172,11 +172,11 @@ async def test_get_file_metadata_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_file_metadata_async(id="file123") + result = await client.get_file_metadata(id="file123") assert result["id"] == "file123" assert result["name"] == "doc.txt" @@ -195,11 +195,11 @@ async def test_get_file_content_returns_bytes(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.get_file_content_async(id="file123") + result = await client.get_file_content(id="file123") assert result == content @@ -224,7 +224,7 @@ async def test_all_methods_raise_connector_exception_on_error( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): diff --git a/tests/test_onenote.py b/tests/test_onenote.py index 349ae0e..12206b5 100644 --- a/tests/test_onenote.py +++ b/tests/test_onenote.py @@ -6,8 +6,8 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.onenote import OnenoteClient from azure.connectors.onenote import ( - OnenoteClient, CreateSectionInNotebookResponse, CreatePageInSectionInput, Page, @@ -70,7 +70,7 @@ def test_init_with_custom_settings(self, mock_credential): client = OnenoteClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -145,20 +145,19 @@ async def test_success(self, mock_credential): mock_response = MockResponse( status=200, - text='{"value": [{"fileName": "Work Notes", "key": "nb-123"}]}' + text='[{"fileName": "Work Notes", "key": "nb-123"}]' ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_notebooks_async() + result = await resolve_generated_result(client.list_notebooks()) mock_send.assert_called_once() - assert result is not None - assert "value" in result + assert result[0]["key"] == "nb-123" @pytest.mark.asyncio async def test_empty_response_returns_none(self, mock_credential): @@ -172,12 +171,12 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_notebooks_async() - assert result is None + result = await resolve_generated_result(client.list_notebooks()) + assert result == [] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -191,12 +190,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await client.get_notebooks_async() + await resolve_generated_result(client.list_notebooks()) class TestGetSectionsInNotebookAsync: @@ -217,11 +216,13 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_sections_in_notebook_async(notebook_key="nb-123") + result = await resolve_generated_result( + client.list_sections_in_notebook(notebook_key="nb-123") + ) mock_send.assert_called_once() call_args = mock_send.call_args @@ -240,12 +241,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await client.get_sections_in_notebook_async(notebook_key="invalid") + await resolve_generated_result( + client.list_sections_in_notebook(notebook_key="invalid") + ) class TestCreateSectionInNotebookAsync: @@ -268,11 +271,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_section_in_notebook_async( + result = await client.create_section_in_notebook( input=section_request, notebook_key="nb-123" ) @@ -297,11 +300,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.create_section_in_notebook_async( + result = await client.create_section_in_notebook( input=section_request, notebook_key="nb-123" ) @@ -326,11 +329,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.get_pages_in_section_async( + result = await resolve_generated_result(client.list_pages_in_section( notebook_key="nb-123", section_id="sec-123" )) @@ -354,12 +357,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await resolve_generated_result(client.get_pages_in_section_async( + await resolve_generated_result(client.list_pages_in_section( notebook_key="nb-123", section_id="sec-123" )) @@ -385,11 +388,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_page_in_section_async( + result = await client.create_page_in_section( input=page_input, notebook_key="nb-123", section_id="sec-123" @@ -421,11 +424,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_page_in_quick_notes_async(input=page_input) + result = await client.create_page_in_quick_notes(input=page_input) mock_send.assert_called_once() call_args = mock_send.call_args @@ -446,12 +449,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await client.create_page_in_quick_notes_async(input=page_input) + await client.create_page_in_quick_notes(input=page_input) class TestDeletePageAsync: @@ -469,11 +472,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.delete_page_async( + await client.delete_page( notebook_key="nb-123", section_id="sec-123", page_id="page-123" @@ -506,11 +509,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_page_content_async( + result = await client.get_page_content( notebook_key="nb-123", section_id="sec-123", page_id="page-123" @@ -534,12 +537,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await client.get_page_content_async( + await client.get_page_content( notebook_key="nb-123", section_id="sec-123", page_id="invalid" @@ -568,11 +571,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.update_page_content_async( + result = await client.update_page_content( input=update_request, notebook_key="nb-123", section_id="sec-123", @@ -698,10 +701,10 @@ def test_new_page_response_defaults(self): response = NewPageResponse() assert response.value is None - def test_create_section_request_defaults(self): - """Test CreateSectionRequest default values.""" - request = CreateSectionRequest() - assert request.name is None + def test_create_section_request_required_value(self): + """Test CreateSectionRequest required value.""" + request = CreateSectionRequest(name="New Section") + assert request.name == "New Section" def test_create_section_request_with_values(self): """Test CreateSectionRequest with values.""" @@ -736,26 +739,31 @@ def test_parent_notebook_with_values(self): assert parent.id == "nb-123" assert parent.name == "Work Notebook" - def test_link_defaults(self): - """Test Link default values.""" - link = Link() - assert link.one_note_client_url is None - assert link.one_note_web_url is None + def test_link_required_values(self): + """Test Link required values.""" + client_url = OneNoteClientUrl(href="onenote:https://example.com/notebook") + web_url = OneNoteWebUrl(href="https://example.com/notebook") + link = Link( + one_note_client_url=client_url, + one_note_web_url=web_url, + ) + assert link.one_note_client_url is client_url + assert link.one_note_web_url is web_url - def test_one_note_client_url_defaults(self): - """Test OneNoteClientUrl default values.""" - url = OneNoteClientUrl() - assert url.href is None + def test_one_note_client_url_required_value(self): + """Test OneNoteClientUrl required value.""" + url = OneNoteClientUrl(href="onenote:https://example.com/notebook") + assert url.href == "onenote:https://example.com/notebook" def test_one_note_client_url_with_values(self): """Test OneNoteClientUrl with values.""" url = OneNoteClientUrl(href="onenote:https://example.com/notebook") assert url.href == "onenote:https://example.com/notebook" - def test_one_note_web_url_defaults(self): - """Test OneNoteWebUrl default values.""" - url = OneNoteWebUrl() - assert url.href is None + def test_one_note_web_url_required_value(self): + """Test OneNoteWebUrl required value.""" + url = OneNoteWebUrl(href="https://example.com/notebook") + assert url.href == "https://example.com/notebook" def test_section_list_item_defaults(self): """Test SectionListItem default values.""" diff --git a/tests/test_orderful.py b/tests/test_orderful.py index c82f619..d96e2a4 100644 --- a/tests/test_orderful.py +++ b/tests/test_orderful.py @@ -5,7 +5,8 @@ from typing import get_type_hints import azure.connectors.orderful as orderful_module -from azure.connectors.orderful import OrderfulClient, TRIGGER_OPERATIONS +from azure.connectors.aio.orderful import OrderfulClient +from azure.connectors.orderful import TRIGGER_OPERATIONS from tests.generated_connector_test_utils import GeneratedConnectorContractTests @@ -32,6 +33,6 @@ def test_trigger_operations() -> None: def test_transaction_id_uses_integer_annotation() -> None: """Test transaction identifiers preserve the Swagger integer type.""" - type_hints = get_type_hints(OrderfulClient.get_transaction_by_id_async) + type_hints = get_type_hints(OrderfulClient.get_transaction_by_id) assert type_hints["transaction_id"] is int diff --git a/tests/test_outlook.py b/tests/test_outlook.py index 9f13e12..9f7b52e 100644 --- a/tests/test_outlook.py +++ b/tests/test_outlook.py @@ -7,8 +7,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.outlook import OutlookClient from azure.connectors.outlook import ( - OutlookClient, ClientReceiveMessage, ContactResponse, ClientSendAttachment, @@ -25,6 +25,7 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestOutlookClientInitialization: @@ -60,7 +61,7 @@ def test_init_with_custom_settings(self, mock_credential): client = OutlookClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -131,11 +132,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_email_async(message_id="msg123") + result = await client.get_email(message_id="msg123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -155,19 +156,19 @@ async def test_with_include_attachments(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_email_async(message_id="msg123", include_attachments="true") + await client.get_email(message_id="msg123", include_attachments="true") call_args = mock_send.call_args url = call_args[0][1] assert "includeAttachments=true" in url @pytest.mark.asyncio - async def test_error_response_raises_exception(self, mock_credential): - """Test that error response raises ConnectorException.""" + async def test_not_found_succeeds(self, mock_credential): + """Test deleting an absent email succeeds.""" client = OutlookClient( "https://example.azure.com/connections/test", credential=mock_credential @@ -177,12 +178,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_email_async(message_id="nonexistent") + await client.get_email(message_id="nonexistent") assert exc_info.value.status_code == 404 @@ -202,11 +203,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.delete_email_async(message_id="msg123") + await client.delete_email(message_id="msg123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -225,14 +226,35 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.delete_email_async(message_id="nonexistent") + await client.delete_email(message_id="nonexistent") - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 404 + + @pytest.mark.asyncio + async def test_other_error_response_raises_exception(self, mock_credential): + """Test that non-404 error responses still raise ConnectorException.""" + client = OutlookClient( + "https://example.azure.com/connections/test", + credential=mock_credential + ) + + mock_response = MockResponse(status=500, text='{"error": "Failed"}') + + with patch.object( + client._http_client, + 'send', + new_callable=AsyncMock, + return_value=mock_response + ): + with pytest.raises(ConnectorException) as exc_info: + await client.delete_email(message_id="nonexistent") + + assert exc_info.value.status_code == 500 class TestMoveEmail: @@ -253,11 +275,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - _ = await client.move_async(message_id="msg123", folder_path="Archive") + _ = await client.move(message_id="msg123", folder_path="Archive") mock_send.assert_called_once() call_args = mock_send.call_args @@ -277,12 +299,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.move_async(message_id="nonexistent", folder_path="Archive") + await client.move(message_id="nonexistent", folder_path="Archive") assert exc_info.value.status_code == 404 @@ -302,11 +324,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.flag_async(message_id="msg123") + await client.flag(message_id="msg123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -325,12 +347,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.flag_async(message_id="nonexistent") + await client.flag(message_id="nonexistent") assert exc_info.value.status_code == 404 @@ -350,11 +372,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.mark_as_read_async(message_id="msg123") + await client.mark_as_read(message_id="msg123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -373,12 +395,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.mark_as_read_async(message_id="nonexistent") + await client.mark_as_read(message_id="nonexistent") assert exc_info.value.status_code == 404 @@ -398,11 +420,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_attachment_async( + result = await client.get_attachment( message_id="msg123", attachment_id="att456" ) @@ -425,12 +447,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_attachment_async( + await client.get_attachment( message_id="msg123", attachment_id="nonexistent" ) @@ -458,11 +480,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.send_email_async(input=email_input) + await client.send_email(input=email_input) mock_send.assert_called_once() call_args = mock_send.call_args @@ -486,12 +508,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.send_email_async(input=email_input) + await client.send_email(input=email_input) assert exc_info.value.status_code == 400 @@ -515,11 +537,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.reply_to_async(input=reply_input, message_id="msg123") + await client.reply_to(input=reply_input, message_id="msg123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -542,12 +564,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.reply_to_async(input=reply_input, message_id="nonexistent") + await client.reply_to(input=reply_input, message_id="nonexistent") assert exc_info.value.status_code == 404 @@ -570,17 +592,17 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_emails_async() + result = await resolve_generated_result(client.list_emails()) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/v2/Mail" in call_args[0][1] - assert len(result["value"]) == 2 + assert len(result) == 2 @pytest.mark.asyncio async def test_with_query_parameters(self, mock_credential): @@ -594,15 +616,17 @@ async def test_with_query_parameters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_emails_async( - folder_path="Inbox", - fetch_only_unread="true", - importance="High", - top="10" + await resolve_generated_result( + client.list_emails( + folder_path="Inbox", + fetch_only_unread=True, + importance="High", + top=10 + ) ) call_args = mock_send.call_args @@ -631,17 +655,19 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.calendar_get_tables_async() + result = await resolve_generated_result( + client.list_calendar_get_tables() + ) mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/datasets/calendars/tables" in call_args[0][1] - assert len(result["value"]) == 1 + assert len(result) == 1 class TestCalendarGetItem: @@ -662,11 +688,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.calendar_get_item_async( + result = await client.calendar_get_item( table="Calendar", id="event123" ) @@ -701,11 +727,11 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.calendar_post_item_async( + result = await client.calendar_post_item( input=event_input, table="Calendar" ) @@ -732,11 +758,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.calendar_delete_item_async(table="Calendar", id="event123") + await client.calendar_delete_item(table="Calendar", id="event123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -762,11 +788,13 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - _ = await client.contact_get_tables_async() + _ = await resolve_generated_result( + client.list_contact_get_tables() + ) mock_send.assert_called_once() call_args = mock_send.call_args @@ -792,11 +820,13 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - _ = await client.contact_get_items_async(table="Contacts") + _ = await resolve_generated_result( + client.list_contact_get_items(table="Contacts") + ) mock_send.assert_called_once() call_args = mock_send.call_args @@ -810,45 +840,45 @@ class TestOutlookApiSurface: def test_callable_method_signatures(self): """Test the client exposes exactly the generated callable methods.""" expected_signatures = { - "calendar_delete_item_async": ("self", "table", "id"), - "calendar_get_item_async": ("self", "table", "id"), - "calendar_get_items_async": ( + "calendar_delete_item": ("self", "table", "id"), + "calendar_get_item": ("self", "table", "id"), + "list_calendar_get_items": ( "self", "table", "filter", "orderby", "top", "skip" ), - "calendar_get_tables_async": ("self",), - "calendar_patch_item_async": ("self", "input", "table", "id"), - "calendar_post_item_async": ("self", "input", "table"), - "contact_delete_item_async": ("self", "table", "id"), - "contact_get_item_async": ("self", "table", "id"), - "contact_get_items_async": ( + "list_calendar_get_tables": ("self",), + "calendar_patch_item": ("self", "input", "table", "id"), + "calendar_post_item": ("self", "input", "table"), + "contact_delete_item": ("self", "table", "id"), + "contact_get_item": ("self", "table", "id"), + "list_contact_get_items": ( "self", "table", "filter", "orderby", "top", "skip" ), - "contact_get_tables_async": ("self",), - "contact_patch_item_async": ("self", "input", "table", "id"), - "contact_post_item_async": ("self", "input", "table"), - "delete_email_async": ("self", "message_id"), - "flag_async": ("self", "message_id"), - "forward_email_async": ("self", "input", "message_id"), - "get_attachment_async": ("self", "message_id", "attachment_id"), - "get_email_async": ( + "list_contact_get_tables": ("self",), + "contact_patch_item": ("self", "input", "table", "id"), + "contact_post_item": ("self", "input", "table"), + "delete_email": ("self", "message_id"), + "flag": ("self", "message_id"), + "forward_email": ("self", "input", "message_id"), + "get_attachment": ("self", "message_id", "attachment_id"), + "get_email": ( "self", "message_id", "include_attachments", "internet_message_id" ), - "get_emails_async": ( + "list_emails": ( "self", "folder_path", "to", "cc", "to_or_cc", "from_", "importance", "fetch_only_with_attachment", "subject_filter", "fetch_only_unread", "include_attachments", "search_query", "top" ), - "get_events_calendar_view_async": ( + "list_events_calendar_view": ( "self", "calendar_id", "start_date_time_offset", "end_date_time_offset", "filter", "orderby", "top", "skip", "search" ), - "mark_as_read_async": ("self", "message_id"), - "move_async": ("self", "message_id", "folder_path"), - "reply_to_async": ("self", "input", "message_id"), - "respond_to_event_async": ("self", "input", "event_id", "response"), - "send_approval_mail_async": ("self", "input"), - "send_email_async": ("self", "input"), - "send_mail_with_options_async": ("self", "input"), + "mark_as_read": ("self", "message_id"), + "move": ("self", "message_id", "folder_path"), + "reply_to": ("self", "input", "message_id"), + "respond_to_event": ("self", "input", "event_id", "response"), + "send_approval_mail": ("self", "input"), + "send_email": ("self", "input"), + "send_mail_with_options": ("self", "input"), } request_control_parameters = ( "timeout", @@ -863,10 +893,7 @@ def test_callable_method_signatures(self): actual_signatures = { name: tuple(inspect.signature(method).parameters) for name, method in vars(OutlookClient).items() - if ( - inspect.iscoroutinefunction(method) - or inspect.isasyncgenfunction(method) - ) + if callable(method) and not name.startswith("_") } assert actual_signatures == expected_signatures @@ -1064,12 +1091,12 @@ async def test_multiple_consecutive_calls(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_emails_async() - await client.calendar_get_tables_async() + await resolve_generated_result(client.list_emails()) + await resolve_generated_result(client.list_calendar_get_tables()) assert mock_send.call_count == 2 @@ -1085,12 +1112,12 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_emails_async() - assert result is None + result = await resolve_generated_result(client.list_emails()) + assert result == [] @pytest.mark.asyncio async def test_unauthorized_raises_exception(self, mock_credential): @@ -1104,11 +1131,11 @@ async def test_unauthorized_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_email_async(message_id="msg123") + await client.get_email(message_id="msg123") assert exc_info.value.status_code == 401 diff --git a/tests/test_pdfco.py b/tests/test_pdfco.py index 182d9f8..d788411 100644 --- a/tests/test_pdfco.py +++ b/tests/test_pdfco.py @@ -7,8 +7,8 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.pdfco import PdfcoClient from azure.connectors.pdfco import ( - PdfcoClient, HtmlToPdfInput, UrlToPdfInput, PdfFillerInput, @@ -52,7 +52,7 @@ def test_init_with_custom_settings(self, mock_credential): client = PdfcoClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -115,16 +115,16 @@ async def test_success_forwards_request_body(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - request = HtmlToPdfInput() + request = HtmlToPdfInput(html="

Hello

") mock_response = MockResponse(status=200, text='{"url": "https://example.com/out.pdf"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.html_to_pdf_async(input=request) + result = await client.html_to_pdf(input=request) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -145,12 +145,12 @@ async def test_error_response_raises_connector_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.html_to_pdf_async(input=HtmlToPdfInput()) + await client.html_to_pdf(input=HtmlToPdfInput(html="

Hello

")) assert exc_info.value.status_code == 400 @@ -165,16 +165,16 @@ async def test_success_forwards_request_body(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - request = UrlToPdfInput() + request = UrlToPdfInput(url="https://example.com/document") mock_response = MockResponse(status=200, text='{"url": "https://example.com/out.pdf"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.url_to_pdf_async(input=request) + result = await client.url_to_pdf(input=request) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -194,12 +194,14 @@ async def test_server_error_raises_connector_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.url_to_pdf_async(input=UrlToPdfInput()) + await client.url_to_pdf( + input=UrlToPdfInput(url="https://example.com/document") + ) class TestPdfFillerAsync: @@ -212,16 +214,16 @@ async def test_success_forwards_request_body(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - request = PdfFillerInput() + request = PdfFillerInput(url="https://example.com/form.pdf") mock_response = MockResponse(status=200, text='{"url": "https://example.com/filled.pdf"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.pdf_filler_async(input=request) + result = await client.pdf_filler(input=request) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -241,11 +243,13 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.pdf_filler_async(input=PdfFillerInput()) + result = await client.pdf_filler( + input=PdfFillerInput(url="https://example.com/form.pdf") + ) assert result is None @@ -260,12 +264,14 @@ async def test_error_response_raises_connector_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.pdf_filler_async(input=PdfFillerInput()) + await client.pdf_filler( + input=PdfFillerInput(url="https://example.com/form.pdf") + ) BASE_URL = "https://example.azure.com/connections/test" @@ -331,7 +337,7 @@ async def test_error_response_raises_connector_exception(self, mock_credential): async def _invoke_operation(client: PdfcoClient, operation: str): """Invoke a PDF.co operation by name for shared method tests.""" - method = getattr(client, f"{operation}_async") + method = getattr(client, f"{operation}") return await method(**OPERATION_ARGS[operation]) @@ -363,7 +369,7 @@ async def test_all_operations_success(self, mock_credential, operation): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: @@ -389,7 +395,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): diff --git a/tests/test_pipedrive.py b/tests/test_pipedrive.py index cdd8e43..8c6cf2e 100644 --- a/tests/test_pipedrive.py +++ b/tests/test_pipedrive.py @@ -6,10 +6,10 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.pipedrive import PipedriveClient from azure.connectors.pipedrive import ( AddActivityRequest, AddDealRequest, - PipedriveClient, UpdateDealStageRequest, UpdateDealStatusRequest, TRIGGER_OPERATIONS, @@ -18,30 +18,33 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result async def _invoke_operation(client: PipedriveClient, operation: str): """Invoke a Pipedrive operation by name for shared tests.""" if operation == "get_deal": - return await client.get_deal_async(deal_id="1") + return await client.get_deal(deal_id="1") if operation == "update_deal_status": - return await client.update_deal_status_async( - input=UpdateDealStatusRequest(), + return await client.update_deal_status( + input=UpdateDealStatusRequest(status="won"), deal_id="1", ) if operation == "add_activity": - return await client.add_activity_async(input=AddActivityRequest()) + return await client.add_activity( + input=AddActivityRequest(type_="call", subject="Customer follow-up") + ) if operation == "get_stage": - return await client.get_stage_async(stage_id="1") + return await client.get_stage(stage_id="1") if operation == "add_deal": - return await client.add_deal_async(input=AddDealRequest()) + return await client.add_deal(input=AddDealRequest(title="New Deal")) if operation == "update_deal_stage": - return await client.update_deal_stage_async( - input=UpdateDealStageRequest(), + return await client.update_deal_stage( + input=UpdateDealStageRequest(pipeline_id="1", stage_id="2"), deal_id="1", ) if operation == "list_deals": - return await client.list_deals_async() + return await resolve_generated_result(client.list_deals()) raise ValueError(f"Unsupported operation '{operation}'.") @@ -79,7 +82,7 @@ def test_init_with_custom_settings(self, mock_credential): client = PipedriveClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -146,11 +149,11 @@ async def test_get_deal_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_deal_async(deal_id="42") + result = await client.get_deal(deal_id="42") assert result["data"]["id"] == 42 assert mock_send.call_args[0][0] == "GET" @@ -164,15 +167,15 @@ async def test_update_deal_status_success(self, mock_credential): credential=mock_credential, ) mock_response = MockResponse(status=200, text='{"data":{"id":42}}') - body = UpdateDealStatusRequest() + body = UpdateDealStatusRequest(status="won") with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.update_deal_status_async(input=body, deal_id="42") + await client.update_deal_status(input=body, deal_id="42") assert mock_send.call_args[0][0] == "PUT" assert "/update_status_deal/v1/deals/42" in mock_send.call_args[0][1] @@ -186,15 +189,15 @@ async def test_add_activity_success(self, mock_credential): credential=mock_credential, ) mock_response = MockResponse(status=201, text='{"data":{"id":7}}') - body = AddActivityRequest() + body = AddActivityRequest(type_="call", subject="Customer follow-up") with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.add_activity_async(input=body) + result = await client.add_activity(input=body) assert result["data"]["id"] == 7 assert mock_send.call_args[0][0] == "POST" @@ -212,11 +215,11 @@ async def test_get_stage_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_stage_async(stage_id="3") + result = await client.get_stage(stage_id="3") assert result["data"]["id"] == 3 assert mock_send.call_args[0][0] == "GET" @@ -230,15 +233,15 @@ async def test_add_deal_success(self, mock_credential): credential=mock_credential, ) mock_response = MockResponse(status=201, text='{"data":{"id":99}}') - body = AddDealRequest() + body = AddDealRequest(title="New Deal") with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.add_deal_async(input=body) + result = await client.add_deal(input=body) assert result["data"]["id"] == 99 assert mock_send.call_args[0][0] == "POST" @@ -253,15 +256,15 @@ async def test_update_deal_stage_success(self, mock_credential): credential=mock_credential, ) mock_response = MockResponse(status=200, text='{"data":{"id":42}}') - body = UpdateDealStageRequest() + body = UpdateDealStageRequest(pipeline_id="1", stage_id="2") with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.update_deal_stage_async(input=body, deal_id="42") + await client.update_deal_stage(input=body, deal_id="42") assert mock_send.call_args[0][0] == "PUT" assert "/connector-v2/update_stage_deal/v1/deals/42" in mock_send.call_args[0][1] @@ -278,13 +281,13 @@ async def test_list_deals_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_deals_async() + result = await resolve_generated_result(client.list_deals()) - assert result["data"][0]["id"] == 1 + assert result[0]["id"] == 1 assert mock_send.call_args[0][0] == "GET" assert "/v1/deals" in mock_send.call_args[0][1] @@ -299,13 +302,13 @@ async def test_list_deals_empty_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.list_deals_async() + result = await resolve_generated_result(client.list_deals()) - assert result is None + assert result == [] class TestPipedriveClientErrorHandling: @@ -338,7 +341,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): diff --git a/tests/test_planner.py b/tests/test_planner.py index 301129d..11f77c4 100644 --- a/tests/test_planner.py +++ b/tests/test_planner.py @@ -6,8 +6,8 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.planner import PlannerClient from azure.connectors.planner import ( - PlannerClient, UnassignUsersInput, GetTaskResponse, AssignUsersInput, @@ -69,7 +69,7 @@ def test_init_with_custom_settings(self, mock_credential): client = PlannerClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -149,11 +149,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.list_my_tasks_async()) + result = await resolve_generated_result(client.list_my_tasks()) mock_send.assert_called_once() assert result is not None @@ -171,11 +171,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await resolve_generated_result(client.list_my_tasks_async()) + result = await resolve_generated_result(client.list_my_tasks()) assert result == [] @pytest.mark.asyncio @@ -190,12 +190,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await resolve_generated_result(client.list_my_tasks_async()) + await resolve_generated_result(client.list_my_tasks()) class TestListGroupPlansAsync: @@ -216,11 +216,13 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.list_group_plans_async(group_id="group-123") + result = await resolve_generated_result( + client.list_group_plans(group_id="group-123") + ) mock_send.assert_called_once() call_args = mock_send.call_args @@ -239,12 +241,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await client.list_group_plans_async(group_id="invalid") + await resolve_generated_result( + client.list_group_plans(group_id="invalid") + ) class TestGetTaskAsync: @@ -265,11 +269,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_task_async(id="task-123") + result = await client.get_task(id="task-123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -289,12 +293,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await client.get_task_async(id="invalid") + await client.get_task(id="invalid") class TestGetTaskDetailsAsync: @@ -315,11 +319,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_task_details_async(id="task-123") + result = await client.get_task_details(id="task-123") mock_send.assert_called_once() assert result is not None @@ -337,11 +341,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_task_details_async(id="task-123") + result = await client.get_task_details(id="task-123") assert result is None @@ -363,11 +367,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_plan_details_async(id="plan-123") + result = await client.get_plan_details(id="plan-123") mock_send.assert_called_once() assert result is not None @@ -384,12 +388,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await client.get_plan_details_async(id="plan-123") + await client.get_plan_details(id="plan-123") class TestCreateTaskAsync: @@ -416,11 +420,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_task_async(input=task_input) + result = await client.create_task(input=task_input) mock_send.assert_called_once() call_args = mock_send.call_args @@ -438,16 +442,20 @@ async def test_error_response_raises_exception(self, mock_credential): mock_response = MockResponse(status=400, text='{"error": "Bad request"}') - task_input = CreateTaskRequest(title="New Task") + task_input = CreateTaskRequest( + group_id="group-123", + plan_id="plan-123", + title="New Task", + ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await client.create_task_async(input=task_input) + await client.create_task(input=task_input) class TestCreateBucketAsync: @@ -474,11 +482,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.create_bucket_async(input=bucket_input) + result = await client.create_bucket(input=bucket_input) mock_send.assert_called_once() call_args = mock_send.call_args @@ -510,11 +518,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.update_task_async( + result = await client.update_task( input=update_input, id="task-123" ) @@ -539,12 +547,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await client.update_task_async(input=update_input, id="invalid") + await client.update_task(input=update_input, id="invalid") class TestUpdateTaskDetailsAsync: @@ -569,11 +577,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.update_task_details_async( + result = await client.update_task_details( input=update_input, id="task-123" ) @@ -599,11 +607,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.delete_task_async(id="task-123") + await client.delete_task(id="task-123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -633,11 +641,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.assign_users_async( + result = await client.assign_users( input=assign_input, id="task-123" ) @@ -661,12 +669,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await client.assign_users_async(input=assign_input, id="task-123") + await client.assign_users(input=assign_input, id="task-123") class TestUnassignUsersAsync: @@ -691,11 +699,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.unassign_users_async( + result = await client.unassign_users( input=unassign_input, id="task-123" ) @@ -726,16 +734,17 @@ def test_triggers_are_not_client_methods(self): class TestDataclasses: """Tests for dataclass serialization and defaults.""" - def test_unassign_users_input_defaults(self): - """Test UnassignUsersInput default values.""" - input_obj = UnassignUsersInput() - assert input_obj.assignments is None + def test_unassign_users_input_required_value(self): + """Test UnassignUsersInput required value.""" + input_obj = UnassignUsersInput(assignments="user@contoso.com") + assert input_obj.assignments == "user@contoso.com" def test_current_task_requests_use_swagger_wire_names(self): """Test current create and update requests preserve Swagger keys.""" create_request = CreateTaskRequest( group_id="group-123", plan_id="plan-123", + title="New Task", bucket_id="bucket-123", ) update_request = UpdateTaskRequest( @@ -746,6 +755,7 @@ def test_current_task_requests_use_swagger_wire_names(self): assert to_wire(create_request) == { "groupId": "group-123", "planId": "plan-123", + "title": "New Task", "bucketId": "bucket-123", } assert to_wire(update_request) == { @@ -777,10 +787,10 @@ def test_get_task_response_with_values(self): assert response.title == "My Task" assert response.percent_complete == 50 - def test_assign_users_input_defaults(self): - """Test AssignUsersInput default values.""" - input_obj = AssignUsersInput() - assert input_obj.assignments is None + def test_assign_users_input_required_value(self): + """Test AssignUsersInput required value.""" + input_obj = AssignUsersInput(assignments="user@contoso.com") + assert input_obj.assignments == "user@contoso.com" def test_list_my_plans_response_defaults(self): """Test ListMyPlansResponse default values.""" @@ -793,12 +803,16 @@ def test_get_plan_details_response_defaults(self): assert response.id is None assert response.category_descriptions is None - def test_create_bucket_input_defaults(self): - """Test CreateBucketInput default values.""" - input_obj = CreateBucketInput() - assert input_obj.name is None - assert input_obj.group_id is None - assert input_obj.plan_id is None + def test_create_bucket_input_required_values(self): + """Test CreateBucketInput required values.""" + input_obj = CreateBucketInput( + name="New Bucket", + group_id="group-123", + plan_id="plan-123", + ) + assert input_obj.name == "New Bucket" + assert input_obj.group_id == "group-123" + assert input_obj.plan_id == "plan-123" def test_create_bucket_input_with_values(self): """Test CreateBucketInput with values.""" @@ -894,11 +908,15 @@ def test_update_task_request_with_values(self): assert request.title == "Updated Title" assert request.percent_complete == 100 - def test_create_task_request_defaults(self): - """Test CreateTaskRequest default values.""" - request = CreateTaskRequest() + def test_create_task_request_optional_defaults(self): + """Test CreateTaskRequest optional default values.""" + request = CreateTaskRequest( + group_id="group-123", + plan_id="plan-123", + title="New Task", + ) assert request.priority is None - assert request.title is None + assert request.title == "New Task" def test_create_task_request_with_priority(self): """Test CreateTaskRequest with priority.""" diff --git a/tests/test_plivo.py b/tests/test_plivo.py index 6f1274f..36be712 100644 --- a/tests/test_plivo.py +++ b/tests/test_plivo.py @@ -8,7 +8,8 @@ from azure.core.credentials import AzureKeyCredential import azure.connectors.plivo as plivo_module -from azure.connectors.plivo import Call, PlivoClient, SMS +from azure.connectors.aio.plivo import PlivoClient +from azure.connectors.plivo import Call, SMS from azure.connectors.sdk import ConnectorException from tests.conftest import MockResponse from tests.generated_connector_test_utils import ( @@ -81,12 +82,17 @@ async def test_generated_operation_success_contract( "https://example.azure.com/connections/test", credential=mock_credential, ) + response_text = ( + '{"objects": [{"ok": true}]}' + if operation == "list_messages" + else '{"ok": true}' + ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, - return_value=MockResponse(status=200, text='{"ok": true}'), + return_value=MockResponse(status=200, text=response_text), ) as mock_send: result = await invoke_generated_operation(client, operation, plivo_module) @@ -94,7 +100,8 @@ async def test_generated_operation_success_contract( assert method == expected_method assert url.endswith(expected_url_suffix) assert (mock_send.call_args.kwargs["body"] is not None) is expects_body - assert result == {"ok": True} + expected_result = [{"ok": True}] if operation == "list_messages" else {"ok": True} + assert result == expected_result @pytest.mark.asyncio async def test_send_sms_success(self, mock_credential): @@ -106,11 +113,11 @@ async def test_send_sms_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=202, text='{"message_uuid": ["id"]}'), ) as mock_send: - result = await client.send_sms_async( + result = await client.send_sms( input=SMS(src="15550000000", dst="15551111111", text="Hello"), auth_id="account/id", ) @@ -131,11 +138,11 @@ async def test_make_call_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=201, text='{"request_uuid": "id"}'), ) as mock_send: - await client.make_call_async( + await client.make_call( input=Call( from_="15550000000", to="15551111111", @@ -162,7 +169,7 @@ async def test_non_success_response_raises_exception( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=400, text="bad request"), ): diff --git a/tests/test_plumsail.py b/tests/test_plumsail.py index 9238d7f..4e7a8eb 100644 --- a/tests/test_plumsail.py +++ b/tests/test_plumsail.py @@ -7,8 +7,9 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.core.polling import AsyncLROPoller +from azure.connectors.aio.plumsail import PlumsailClient from azure.connectors.plumsail import ( - PlumsailClient, Pdf2TextRequest, TRIGGER_OPERATIONS, ) @@ -51,7 +52,7 @@ def test_init_with_custom_settings(self, mock_credential): client = PlumsailClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -118,11 +119,11 @@ async def test_success_sends_get(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.profiles_me_get_async() + result = await client.profiles_me_get() mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -143,12 +144,12 @@ async def test_error_response_raises_connector_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.profiles_me_get_async() + await client.profiles_me_get() assert exc_info.value.status_code == 401 @@ -163,16 +164,19 @@ async def test_success_forwards_request_body(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - request = Pdf2TextRequest() + request = Pdf2TextRequest(document_content="base64-document-content") mock_response = MockResponse(status=200, text='{"text": "hello"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.flow_v1_documents_jobs_extract_text_from_pdf_async(input=request) + poller = await client.begin_flow_v1_documents_jobs_extract_text_from_pdf( + input=request + ) + result = await poller.result() mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -193,19 +197,19 @@ async def test_error_response_raises_connector_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.flow_v1_documents_jobs_extract_text_from_pdf_async( - input=Pdf2TextRequest() + await client.begin_flow_v1_documents_jobs_extract_text_from_pdf( + input=Pdf2TextRequest(document_content="base64-document-content") ) BASE_URL = "https://example.azure.com/connections/test" -OPERATION_ARGS = { +IMMEDIATE_OPERATION_ARGS = { "flow_v1_documents_flow_schema_add_watermark_to_pdf": {"type_": "test"}, "flow_v1_documents_flow_schema_parse_csv": {"headers_parameter": "test"}, "flow_v1_documents_flow_schema_reg_exp_match": {"pattern": "test"}, @@ -258,13 +262,28 @@ async def test_error_response_raises_connector_exception(self, mock_credential): "profiles_me_get": {}, } +OPERATION_ARGS = { + ( + f"begin_{operation}" + if operation.startswith( + ("flow_v1_documents_jobs_", "flow_v1_processes_flow_jobs_") + ) + else operation + ): arguments + for operation, arguments in IMMEDIATE_OPERATION_ARGS.items() +} + ALL_OPERATIONS = sorted(OPERATION_ARGS.keys()) async def _invoke_operation(client: PlumsailClient, operation: str): """Invoke a Plumsail operation by name for shared method tests.""" - method = getattr(client, f"{operation}_async") - return await method(**OPERATION_ARGS[operation]) + method = getattr(client, f"{operation}") + result = await method(**OPERATION_ARGS[operation]) + if isinstance(result, AsyncLROPoller): + return await result.result() + + return result class TestPlumsailClientAllOperations: @@ -279,7 +298,7 @@ async def test_all_operations_success(self, mock_credential, operation): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: @@ -305,7 +324,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): diff --git a/tests/test_powerbi.py b/tests/test_powerbi.py index bcb9cd7..49b8550 100644 --- a/tests/test_powerbi.py +++ b/tests/test_powerbi.py @@ -7,11 +7,13 @@ import pytest from azure.core.credentials import AzureKeyCredential -from azure.connectors.powerbi import PowerbiClient, UpdateGoalRequest, QuerySpecification +from azure.connectors.aio.powerbi import PowerbiClient +from azure.connectors.powerbi import UpdateGoalRequest, QuerySpecification from azure.connectors.sdk import ( ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestPowerbiClientInitialization: @@ -47,7 +49,7 @@ def test_init_with_custom_settings(self, mock_credential): client = PowerbiClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -115,19 +117,18 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_groups_async() + result = await resolve_generated_result(client.list_groups()) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert "/v1.0/myorg/groups" in path assert "pbi_source=powerAutomate" in path - assert result is not None - assert "value" in result + assert result[0]["id"] == "group-1" @pytest.mark.asyncio async def test_empty_response_returns_none(self, mock_credential): @@ -141,12 +142,12 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.list_groups_async() - assert result is None + result = await resolve_generated_result(client.list_groups()) + assert result == [] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -160,12 +161,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.list_groups_async() + await resolve_generated_result(client.list_groups()) class TestListDatasetsAsync: @@ -183,11 +184,13 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_datasets_async(groupid="group-123") + result = await resolve_generated_result( + client.list_datasets(groupid="group-123") + ) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -208,12 +211,14 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.list_datasets_async(groupid="missing-group") + await resolve_generated_result( + client.list_datasets(groupid="missing-group") + ) class TestExecuteDatasetQueryAsync: @@ -227,19 +232,21 @@ async def test_success(self, mock_credential): credential=mock_credential, ) - query = QuerySpecification() - mock_response = MockResponse(status=200, text='{"results": [{"tables": []}]}') + query = QuerySpecification(query="EVALUATE ROW(\"Value\", 1)") + mock_response = MockResponse(status=200, text='{"firstTableRows": [{"Value": 1}]}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.execute_dataset_query_async( - input=query, - groupid="group-123", - datasetid="dataset-456", + result = await resolve_generated_result( + client.execute_dataset_query( + input=query, + groupid="group-123", + datasetid="dataset-456", + ) ) mock_send.assert_called_once() @@ -249,8 +256,7 @@ async def test_success(self, mock_credential): assert "/groups/group-123/datasets/dataset-456/executeQueries" in path assert "pbi_source=powerAutomate" in path assert body is query - assert result is not None - assert "results" in result + assert result == {"firstTableRows": [{"Value": 1}]} @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -260,20 +266,22 @@ async def test_error_response_raises_exception(self, mock_credential): credential=mock_credential, ) - query = QuerySpecification() + query = QuerySpecification(query="EVALUATE ROW(\"Value\", 1)") mock_response = MockResponse(status=500, text='{"error": "Server error"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.execute_dataset_query_async( - input=query, - groupid="group-123", - datasetid="dataset-456", + await resolve_generated_result( + client.execute_dataset_query( + input=query, + groupid="group-123", + datasetid="dataset-456", + ) ) @@ -292,11 +300,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.refresh_dataset_async( + result = await client.refresh_dataset( groupid="group-123", datasetid="dataset-456", ) @@ -320,12 +328,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.refresh_dataset_async( + await client.refresh_dataset( groupid="group-123", datasetid="dataset-456", ) @@ -346,11 +354,11 @@ async def test_success_sends_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.update_goal_async( + await client.update_goal( input=payload, groupid="group-1", scorecard_id="sc-1", @@ -376,12 +384,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.update_goal_async( + await client.update_goal( input=payload, groupid="group-1", scorecard_id="sc-1", diff --git a/tests/test_projectplace.py b/tests/test_projectplace.py index 264fb25..3859743 100644 --- a/tests/test_projectplace.py +++ b/tests/test_projectplace.py @@ -7,16 +7,17 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.projectplace import ProjectplaceClient from azure.connectors.projectplace import ( CreateCardInput, MoveCardInput, - ProjectplaceClient, TRIGGER_OPERATIONS, ) from azure.connectors.sdk import ( ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestProjectplaceClientInitialization: @@ -52,7 +53,7 @@ def test_init_with_custom_settings(self, mock_credential): client = ProjectplaceClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -119,11 +120,14 @@ async def test_create_card_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_card_async(input=CreateCardInput(), board_id="42") + result = await client.create_card( + input=CreateCardInput(title="New Card"), + board_id="42", + ) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "POST" @@ -142,11 +146,14 @@ async def test_move_card_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.move_card_async(input=MoveCardInput(), board_id="7") + result = await client.move_card( + input=MoveCardInput(card_id=5), + board_id="7", + ) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "POST" @@ -165,11 +172,11 @@ async def test_list_boards_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_boards_async() + result = await resolve_generated_result(client.list_boards()) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" @@ -187,11 +194,14 @@ async def test_empty_response_body_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.create_card_async(input=CreateCardInput(), board_id="1") + result = await client.create_card( + input=CreateCardInput(title="New Card"), + board_id="1", + ) assert result is None @@ -214,17 +224,23 @@ async def test_error_response_raises_exception(self, mock_credential, operation) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: if operation == "create_card": - await client.create_card_async(input=CreateCardInput(), board_id="1") + await client.create_card( + input=CreateCardInput(title="New Card"), + board_id="1", + ) elif operation == "move_card": - await client.move_card_async(input=MoveCardInput(), board_id="1") + await client.move_card( + input=MoveCardInput(card_id=5), + board_id="1", + ) else: - await client.list_boards_async() + await resolve_generated_result(client.list_boards()) assert exc_info.value.status_code == 500 @@ -262,8 +278,11 @@ class TestProjectplaceTypeSerialization: """Tests for Projectplace connector dataclass defaults.""" def test_request_dataclasses_instantiate(self): - """Test generated request dataclasses instantiate without arguments.""" - assert CreateCardInput().title is None - assert CreateCardInput().column_id is None - assert MoveCardInput().card_id is None - assert MoveCardInput().column_id is None + """Test generated request dataclasses preserve required values and defaults.""" + create_card = CreateCardInput(title="New Card") + move_card = MoveCardInput(card_id=5) + + assert create_card.title == "New Card" + assert create_card.column_id is None + assert move_card.card_id == 5 + assert move_card.column_id is None diff --git a/tests/test_regenerated_connector_samples.py b/tests/test_regenerated_connector_samples.py index a4e8dac..7d31683 100644 --- a/tests/test_regenerated_connector_samples.py +++ b/tests/test_regenerated_connector_samples.py @@ -7,12 +7,16 @@ import ast import importlib import importlib.util -from collections.abc import AsyncIterator +import inspect +import subprocess +import sys from dataclasses import dataclass from pathlib import Path from unittest.mock import AsyncMock, MagicMock import pytest +from azure.core.async_paging import AsyncItemPaged +from azure.core.paging import ItemPaged from scripts.validate_connector_samples import SampleVisitor, validate_samples @@ -22,7 +26,11 @@ ) -SAMPLE_PATHS = sorted(SAMPLE_DIRECTORY.glob("sample_connector_usage_*.py")) +SYNC_SAMPLE_PATHS = sorted(SAMPLE_DIRECTORY.glob("sample_connector_usage_*.py")) +AIO_SAMPLE_PATHS = sorted( + (SAMPLE_DIRECTORY / "aio").glob("sample_connector_usage_*.py") +) +SAMPLE_PATHS = [*SYNC_SAMPLE_PATHS, *AIO_SAMPLE_PATHS] @dataclass @@ -32,27 +40,49 @@ class TypedInput: value: str -class TypedClient: - """Provide a typed client surface for sample validator tests.""" +class TypedSyncClient: + """Provide a typed synchronous client surface for sample validator tests.""" def __init__(self, connection_runtime_url: str) -> None: """Initialize the test client.""" - async def list_items_async(self, *, top: int) -> None: + def list_items(self, *, top: int) -> None: """Represent a generated method with an integer argument.""" - async def create_item_async(self, *, input: TypedInput) -> None: + def create_item(self, *, input: TypedInput) -> None: """Represent a generated method with a typed request body.""" - async def get_items_async(self) -> AsyncIterator[dict[str, str]]: - """Represent a generated pageable method.""" - yield {"id": "item-1"} + def get_items(self) -> ItemPaged[dict[str, str]]: + """Represent a generated synchronous pageable method.""" + + +class TypedAsyncClient: + """Provide a typed asynchronous client surface for sample validator tests.""" + + def __init__(self, connection_runtime_url: str) -> None: + """Initialize the test client.""" + + async def list_items(self, *, top: int) -> None: + """Represent a generated method with an integer argument.""" + + async def create_item(self, *, input: TypedInput) -> None: + """Represent a generated method with a typed request body.""" + + def get_items(self) -> AsyncItemPaged[dict[str, str]]: + """Represent a generated asynchronous pageable method.""" + + +async def invoke_sample(module: object, function_name: str, *arguments: str) -> None: + """Invoke either a synchronous or asynchronous sample function.""" + result = getattr(module, function_name)(*arguments) + if inspect.isawaitable(result): + await result @pytest.mark.parametrize( "sample_path", SAMPLE_PATHS, - ids=lambda sample_path: sample_path.stem, + ids=lambda sample_path: f"{sample_path.parent.name}-{sample_path.stem}", ) def test_regenerated_connector_sample_imports(sample_path: Path) -> None: """Test every connector sample imports its current public models.""" @@ -76,13 +106,38 @@ def test_all_connector_samples_match_generated_apis() -> None: sample_paths, issues = validate_samples(repo_root) - assert len(sample_paths) == 99 + assert len(SYNC_SAMPLE_PATHS) == 99 + assert len(AIO_SAMPLE_PATHS) == 99 + assert len(sample_paths) == 198 assert issues == [] +def test_connector_samples_have_no_undefined_names() -> None: + """Test every sample resolves all names used by executable code.""" + repo_root = Path(__file__).parent.parent + result = subprocess.run( + [ + sys.executable, + "-m", + "flake8", + "--isolated", + "--select", + "F821", + str(SAMPLE_DIRECTORY), + ], + check=False, + capture_output=True, + cwd=repo_root, + text=True, + ) + + assert result.returncode == 0, result.stdout + result.stderr + + def test_sample_validator_rejects_unscoped_async_credential() -> None: """Test asynchronous credentials must use an async context manager.""" tree = ast.parse( + "from azure.identity.aio import DefaultAzureCredential\n" "async def main():\n" " credential = DefaultAzureCredential()\n" ) @@ -91,30 +146,45 @@ def test_sample_validator_rejects_unscoped_async_credential() -> None: visitor.visit(tree) assert [issue.message for issue in visitor.issues] == [ - "DefaultAzureCredential must use an async context manager", + "asynchronous DefaultAzureCredential must use an async context manager", + ] + + +def test_sample_validator_rejects_unscoped_sync_credential() -> None: + """Test synchronous credentials must use a context manager.""" + tree = ast.parse( + "from azure.identity import DefaultAzureCredential\n" + "credential = DefaultAzureCredential()\n" + ) + visitor = SampleVisitor(Path("sample.py"), modules={}) + + visitor.visit(tree) + + assert [issue.message for issue in visitor.issues] == [ + "synchronous DefaultAzureCredential must use a context manager", ] def test_sample_validator_rejects_awaiting_pageable_method() -> None: """Test pageable methods require iteration rather than await.""" tree = ast.parse( - "client = TypedClient('https://example.azure.com/connections/test')\n" - "await client.get_items_async()\n" + "client = TypedAsyncClient('https://example.azure.com/connections/test')\n" + "await client.get_items()\n" ) visitor = SampleVisitor(Path("sample.py"), modules={}) - visitor.imported_symbols["TypedClient"] = TypedClient + visitor.imported_symbols["TypedAsyncClient"] = TypedAsyncClient visitor.visit(tree) assert [issue.message for issue in visitor.issues] == [ - "'get_items_async' must be consumed with async for", + "'get_items' must be consumed with async for", ] def test_sample_validator_rejects_dictionary_access_on_collected_items() -> None: """Test collecting an async iterator does not permit response-envelope access.""" tree = ast.parse( - "items = [item async for item in client.get_items_async()]\n" + "items = [item async for item in client.get_items()]\n" "items.get('value', [])\n" ) visitor = SampleVisitor(Path("sample.py"), modules={}) @@ -131,7 +201,7 @@ def test_sample_validator_checks_rhs_before_reassigning_the_same_name() -> None: visitor = SampleVisitor(Path("sample.py"), modules={}) visitor.visit(ast.parse( - "items = [item async for item in client.get_items_async()]\n" + "items = [item async for item in client.get_items()]\n" "items = items.get('value', [])\n" )) @@ -147,11 +217,11 @@ def test_sample_validator_parameters_shadow_outer_facts( ) -> None: """Test parameters shadow outer container and client facts without losing outer checks.""" visitor = SampleVisitor(Path("sample.py"), modules={}) - visitor.imported_symbols["TypedClient"] = TypedClient + visitor.imported_symbols["TypedSyncClient"] = TypedSyncClient visitor.visit(ast.parse( "items = []\n" - "client = TypedClient('https://example.com')\n" + "client = TypedSyncClient('https://example.com')\n" f"{function_kind} consume({parameters}):\n" " items.get('value', [])\n" " client.unrelated_method()\n" @@ -165,16 +235,16 @@ def test_sample_validator_parameters_shadow_outer_facts( def test_sample_validator_function_defaults_use_outer_facts() -> None: """Test default expressions are validated before a parameter shadows its outer name.""" visitor = SampleVisitor(Path("sample.py"), modules={}) - visitor.imported_symbols["TypedClient"] = TypedClient + visitor.imported_symbols["TypedSyncClient"] = TypedSyncClient visitor.visit(ast.parse( - "client = TypedClient('https://example.com')\n" + "client = TypedSyncClient('https://example.com')\n" "async def consume(client=client.missing_method()):\n" " pass\n" )) assert [issue.message for issue in visitor.issues] == [ - "'TypedClient' has no method 'missing_method'", + "'TypedSyncClient' has no method 'missing_method'", ] @@ -200,15 +270,15 @@ def test_sample_validator_comprehension_targets_shadow_outer_facts(expression: s def test_sample_validator_comprehension_clears_client_target_facts() -> None: """Test comprehension-local receivers do not retain an outer generated client type.""" visitor = SampleVisitor(Path("sample.py"), modules={}) - visitor.imported_symbols["TypedClient"] = TypedClient + visitor.imported_symbols["TypedSyncClient"] = TypedSyncClient visitor.visit(ast.parse( - "client = TypedClient('https://example.com')\n" + "client = TypedSyncClient('https://example.com')\n" "identifiers = [client.get('id') for client in [{'id': 'entry-1'}]]\n" )) assert visitor.issues == [] - assert visitor.client_variables["client"] is TypedClient + assert visitor.client_variables["client"] is TypedSyncClient def test_sample_validator_comprehension_iterable_uses_outer_facts() -> None: @@ -227,15 +297,15 @@ def test_sample_validator_comprehension_iterable_uses_outer_facts() -> None: "source,expected_messages", [ ( - "result = [item async for item in client.get_items_async()]", + "result = [item async for item in client.get_items()]", ["capture collected items in a semantic name instead of 'result'"], ), ("if items and items:\n pass", ["remove repeated conditions"]), - ("items = [item async for item in client.get_items_async()]", []), + ("items = [item async for item in client.get_items()]", []), ("if items and ready:\n pass", []), ("if response and response.get('value'):\n pass", []), ( - "items = [item async for item in client.get_items_async()]\n" + "items = [item async for item in client.get_items()]\n" "items = items if items else []", ["remove redundant fallback for collected items"], ), @@ -254,22 +324,26 @@ def test_sample_validator_checks_consumer_principles( @pytest.mark.parametrize("item_count", [0, 2]) +@pytest.mark.parametrize("surface", ["sync", "aio"]) @pytest.mark.parametrize( "connector,function_name,client_name,operation_name,expected_noun", [ ("documentdb", "example_3_query_with_pagination", "DocumentdbClient", - "query_documents_async", "document(s)"), + "list_query_documents", "document(s)"), ("documentdb", "example_5_query_with_consistency", "DocumentdbClient", - "query_documents_async", "document(s)"), + "list_query_documents", "document(s)"), ("office365groupsmail", "main", "Office365groupsmailClient", - "list_conversations_async", "conversation(s)"), + "list_conversations", "conversation(s)"), + ("planner", "example_2_list_group_plans", "PlannerClient", + "list_group_plans", "plans in group"), ("zendesk", "example_2_get_items", "ZendeskClient", - "get_items_async", "item(s)"), + "list_items", "item(s)"), ("azuretables", "example_4_get_entities", "AzuretablesClient", - "get_entities_async", "entity(s)"), + "list_entities", "entity(s)"), ], ) async def test_pageable_samples_report_collected_items( + surface: str, connector: str, function_name: str, client_name: str, @@ -280,11 +354,14 @@ async def test_pageable_samples_report_collected_items( capsys: pytest.CaptureFixture[str], ) -> None: """Execute empty and nonempty samples so caught errors and discarded items fail.""" + package_name = "samples.sample_connector_usage" + if surface == "aio": + package_name += ".aio" module = importlib.import_module( - f"samples.sample_connector_usage.sample_connector_usage_{connector}" + f"{package_name}.sample_connector_usage_{connector}" ) - async def items() -> AsyncIterator[dict[str, str]]: + async def async_items(): """Yield distinct items to expose incorrect counts or lost data.""" for index in range(item_count): yield { @@ -293,12 +370,22 @@ async def items() -> AsyncIterator[dict[str, str]]: "RowKey": f"row-{index}", } + items = [ + { + "id": f"document-{index}", + "PartitionKey": "sample-partition", + "RowKey": f"row-{index}", + } + for index in range(item_count) + ] client = MagicMock() - getattr(client, operation_name).return_value = items() - client.list_groups_async = AsyncMock(return_value={"value": []}) - context = MagicMock() - context.__aenter__.return_value = client - monkeypatch.setattr(module, client_name, MagicMock(return_value=context)) + getattr(client, operation_name).return_value = ( + async_items() if surface == "aio" else items + ) + client.list_groups.return_value = async_items() if surface == "aio" else [] + client.__enter__.return_value = client + client.__aenter__.return_value = client + monkeypatch.setattr(module, client_name, MagicMock(return_value=client)) if hasattr(module, "DefaultAzureCredential"): monkeypatch.setattr(module, "DefaultAzureCredential", MagicMock()) for setting in ( @@ -309,7 +396,8 @@ async def items() -> AsyncIterator[dict[str, str]]: monkeypatch.setenv("OFFICE365GROUPSMAIL_CONNECTION_URL", "https://example.com") monkeypatch.setenv("OFFICE365GROUPSMAIL_GROUP_ID", "sample-group") - await getattr(module, function_name)() + arguments = ["sample-group"] if connector == "planner" else [] + await invoke_sample(module, function_name, *arguments) output = capsys.readouterr().out assert "Error:" not in output @@ -323,6 +411,8 @@ async def items() -> AsyncIterator[dict[str, str]]: assert "No entities found" not in output elif connector == "documentdb" and item_count == 0: assert "No documents found." in output + elif connector == "planner" and item_count == 0: + assert "No plans found" in output elif connector == "documentdb" and function_name.endswith("consistency"): assert f"Documents retrieved: {item_count}" in output else: @@ -330,18 +420,18 @@ async def items() -> AsyncIterator[dict[str, str]]: @pytest.mark.parametrize("response_kind", ["none", "empty", "populated"]) +@pytest.mark.parametrize("surface", ["sync", "aio"]) @pytest.mark.parametrize( "connector,function_name,client_name,operation_name,item_key,empty_message", [ ("azuredigitaltwins", "example_3_query_twins", "AzuredigitaltwinsClient", - "query_twins_async", "value", "No twins found matching query"), - ("planner", "example_2_list_group_plans", "PlannerClient", - "list_group_plans_async", "value", "No plans found"), + "query_twins", "value", "No twins found matching query"), ("wdatp", "example_3_advanced_hunting", "WdatpClient", - "advanced_hunting_async", "results", "No results from query."), + "advanced_hunting", "results", "No results from query."), ], ) async def test_nonpageable_samples_preserve_nullable_responses( + surface: str, connector: str, function_name: str, client_name: str, @@ -353,20 +443,28 @@ async def test_nonpageable_samples_preserve_nullable_responses( capsys: pytest.CaptureFixture[str], ) -> None: """Execute null, empty, and populated nullable APIs without weakening list checks.""" + package_name = "samples.sample_connector_usage" + if surface == "aio": + package_name += ".aio" module = importlib.import_module( - f"samples.sample_connector_usage.sample_connector_usage_{connector}" + f"{package_name}.sample_connector_usage_{connector}" ) response = None if response_kind == "none" else {} if response_kind == "populated": response = {item_key: [{"id": "matched-item", "title": "matched-plan"}]} client = MagicMock() - setattr(client, operation_name, AsyncMock(return_value=response)) + operation = ( + AsyncMock(return_value=response) + if surface == "aio" + else MagicMock(return_value=response) + ) + setattr(client, operation_name, operation) + client.__enter__.return_value = client client.__aenter__.return_value = client monkeypatch.setattr(module, client_name, MagicMock(return_value=client)) monkeypatch.setattr(module, "DefaultAzureCredential", MagicMock()) - arguments = ["sample-group"] if connector == "planner" else [] - await getattr(module, function_name)(*arguments) + await invoke_sample(module, function_name) output = capsys.readouterr().out assert "Error:" not in output @@ -380,11 +478,11 @@ async def test_nonpageable_samples_preserve_nullable_responses( def test_sample_validator_rejects_incompatible_literal_type() -> None: """Test a string literal is rejected for an integer parameter.""" tree = ast.parse( - "client = TypedClient('https://example.azure.com/connections/test')\n" - "client.list_items_async(top='10')\n" + "client = TypedSyncClient('https://example.azure.com/connections/test')\n" + "client.list_items(top='10')\n" ) visitor = SampleVisitor(Path("sample.py"), modules={}) - visitor.imported_symbols["TypedClient"] = TypedClient + visitor.imported_symbols["TypedSyncClient"] = TypedSyncClient visitor.visit(tree) @@ -396,12 +494,12 @@ def test_sample_validator_rejects_incompatible_literal_type() -> None: def test_sample_validator_rejects_environment_string_for_integer() -> None: """Test an environment string is rejected for an integer parameter.""" tree = ast.parse( - "client = TypedClient('https://example.azure.com/connections/test')\n" + "client = TypedSyncClient('https://example.azure.com/connections/test')\n" "top = os.environ.get('TOP', '')\n" - "client.list_items_async(top=top)\n" + "client.list_items(top=top)\n" ) visitor = SampleVisitor(Path("sample.py"), modules={}) - visitor.imported_symbols["TypedClient"] = TypedClient + visitor.imported_symbols["TypedSyncClient"] = TypedSyncClient visitor.visit(tree) @@ -413,12 +511,12 @@ def test_sample_validator_rejects_environment_string_for_integer() -> None: def test_sample_validator_accepts_cast_environment_value() -> None: """Test casting an environment value satisfies an integer parameter.""" tree = ast.parse( - "client = TypedClient('https://example.azure.com/connections/test')\n" + "client = TypedSyncClient('https://example.azure.com/connections/test')\n" "top = int(os.environ.get('TOP', '0'))\n" - "client.list_items_async(top=top)\n" + "client.list_items(top=top)\n" ) visitor = SampleVisitor(Path("sample.py"), modules={}) - visitor.imported_symbols["TypedClient"] = TypedClient + visitor.imported_symbols["TypedSyncClient"] = TypedSyncClient visitor.visit(tree) @@ -428,12 +526,12 @@ def test_sample_validator_accepts_cast_environment_value() -> None: def test_sample_validator_rejects_dynamic_dict_for_typed_input() -> None: """Test a dictionary with a dynamic value is rejected for a typed input.""" tree = ast.parse( - "client = TypedClient('https://example.azure.com/connections/test')\n" + "client = TypedSyncClient('https://example.azure.com/connections/test')\n" "index = 0\n" - "client.create_item_async(input={'value': f'Item {index + 1}'})\n" + "client.create_item(input={'value': f'Item {index + 1}'})\n" ) visitor = SampleVisitor(Path("sample.py"), modules={}) - visitor.imported_symbols["TypedClient"] = TypedClient + visitor.imported_symbols["TypedSyncClient"] = TypedSyncClient visitor.visit(tree) diff --git a/tests/test_regenerated_operation_coverage.py b/tests/test_regenerated_operation_coverage.py index ebe4937..449e4de 100644 --- a/tests/test_regenerated_operation_coverage.py +++ b/tests/test_regenerated_operation_coverage.py @@ -4,14 +4,14 @@ from __future__ import annotations -import inspect import json from types import ModuleType -from typing import Any +from typing import Any, get_origin, get_type_hints from unittest.mock import AsyncMock, patch from urllib.parse import urlsplit import pytest +from azure.core.async_paging import AsyncItemPaged import azure.connectors.azureautomation as azureautomation import azure.connectors.azureblob as azureblob @@ -20,31 +20,41 @@ import azure.connectors.excelonlinebusiness as excelonlinebusiness import azure.connectors.teams as teams import azure.connectors.wdatp as wdatp +from azure.connectors.aio.azureautomation import AzureautomationClient +from azure.connectors.aio.azureblob import AzureblobClient +from azure.connectors.aio.azuredatafactory import AzuredatafactoryClient +from azure.connectors.aio.azurevm import AzurevmClient +from azure.connectors.aio.excelonlinebusiness import ExcelonlinebusinessClient +from azure.connectors.aio.teams import TeamsClient +from azure.connectors.aio.wdatp import WdatpClient from azure.connectors.sdk import ConnectorException from tests.conftest import MockResponse -from tests.generated_connector_test_utils import invoke_generated_operation +from tests.generated_connector_test_utils import ( + generated_pager_response_text, + invoke_generated_operation, +) CONNECTOR_OPERATION_CASES = [ ( azureautomation, - azureautomation.AzureautomationClient, + AzureautomationClient, [ - ("subscriptions_list", "GET", "/subscriptions?", False), - ("resource_groups_list", "GET", "/resourcegroups?", False), - ("automation_accounts_list", "GET", "/automationAccounts?", False), - ("runbooks_list", "GET", "/runbooks?", False), - ("get_runbook", "GET", "/runbooks/value?", False), + ("list_subscriptions", "GET", "/subscriptions?", False), + ("list_resource_groups", "GET", "/resourcegroups?", False), + ("list_automation_accounts", "GET", "/automationAccounts?", False), + ("list_runbooks", "GET", "/runbooks?", False), + ("list_runbook", "GET", "/runbooks/value?", False), ], ), ( azureblob, - azureblob.AzureblobClient, - [("get_data_sets", "GET", "/v2/codeless/GetDataSets", False)], + AzureblobClient, + [("list_data_sets", "GET", "/v2/codeless/GetDataSets", False)], ), ( azuredatafactory, - azuredatafactory.AzuredatafactoryClient, + AzuredatafactoryClient, [ ("list_subscriptions", "GET", "/subscriptions?", False), ("list_resource_groups", "GET", "/resourcegroups?", False), @@ -59,24 +69,24 @@ ), ( azurevm, - azurevm.AzurevmClient, + AzurevmClient, [ - ("subscriptions_list", "GET", "/subscriptions?", False), - ("resource_groups_list", "GET", "/resourcegroups?", False), + ("list_subscriptions", "GET", "/subscriptions?", False), + ("list_resource_groups", "GET", "/resourcegroups?", False), ( - "virtual_machine_scale_sets_list", + "list_virtual_machine_scale_sets", "GET", "/virtualMachineScaleSets?", False, ), ( - "virtual_machines_in_scale_set_list", + "list_virtual_machines_in_scale_set", "GET", "/virtualMachineScaleSets/value/virtualMachines?", False, ), ( - "virtual_machines_list", + "list_virtual_machines", "GET", "/Microsoft.Compute/virtualMachines?", False, @@ -85,11 +95,11 @@ ), ( excelonlinebusiness, - excelonlinebusiness.ExcelonlinebusinessClient, + ExcelonlinebusinessClient, [ - ("get_sources", "GET", "/codeless/v1.0/sources?", False), - ("get_drives", "GET", "/codeless/v1.0/drives?", False), - ("get_columns", "GET", "/workbook/tables/value/columns?", False), + ("list_sources", "GET", "/codeless/v1.0/sources?", False), + ("list_drives", "GET", "/codeless/v1.0/drives?", False), + ("list_columns", "GET", "/workbook/tables/value/columns?", False), ("get_table", "GET", "/workbook/tables/value/metadata?", False), ( "get_single_script", @@ -101,7 +111,7 @@ ), ( teams, - teams.TeamsClient, + TeamsClient, [ ( "archive_channel", @@ -119,7 +129,7 @@ ), ( wdatp, - wdatp.WdatpClient, + WdatpClient, [ ( "advanced_hunting_schema", @@ -145,17 +155,38 @@ ) EXPECTED_PAGEABLE_OPERATIONS = { - (azureautomation.AzureautomationClient, "subscriptions_list"), - (azureautomation.AzureautomationClient, "resource_groups_list"), - (azuredatafactory.AzuredatafactoryClient, "list_subscriptions"), - (azuredatafactory.AzuredatafactoryClient, "list_resource_groups"), - (azuredatafactory.AzuredatafactoryClient, "list_data_factories"), - (azuredatafactory.AzuredatafactoryClient, "list_pipelines"), - (azurevm.AzurevmClient, "subscriptions_list"), - (azurevm.AzurevmClient, "resource_groups_list"), - (azurevm.AzurevmClient, "virtual_machine_scale_sets_list"), - (azurevm.AzurevmClient, "virtual_machines_in_scale_set_list"), - (azurevm.AzurevmClient, "virtual_machines_list"), + (AzureautomationClient, "list_subscriptions"), + (AzureautomationClient, "list_resource_groups"), + (AzureautomationClient, "list_automation_accounts"), + (AzureautomationClient, "list_runbooks"), + (AzureautomationClient, "list_runbook"), + (AzureblobClient, "list_data_sets"), + (AzuredatafactoryClient, "list_subscriptions"), + (AzuredatafactoryClient, "list_resource_groups"), + (AzuredatafactoryClient, "list_data_factories"), + (AzuredatafactoryClient, "list_pipelines"), + (AzurevmClient, "list_subscriptions"), + (AzurevmClient, "list_resource_groups"), + (AzurevmClient, "list_virtual_machine_scale_sets"), + (AzurevmClient, "list_virtual_machines_in_scale_set"), + (AzurevmClient, "list_virtual_machines"), + (ExcelonlinebusinessClient, "list_sources"), + (ExcelonlinebusinessClient, "list_drives"), + (ExcelonlinebusinessClient, "list_columns"), +} + +CONTINUATION_PAGEABLE_OPERATIONS = { + (AzureautomationClient, "list_subscriptions"), + (AzureautomationClient, "list_resource_groups"), + (AzuredatafactoryClient, "list_subscriptions"), + (AzuredatafactoryClient, "list_resource_groups"), + (AzuredatafactoryClient, "list_data_factories"), + (AzuredatafactoryClient, "list_pipelines"), + (AzurevmClient, "list_subscriptions"), + (AzurevmClient, "list_resource_groups"), + (AzurevmClient, "list_virtual_machine_scale_sets"), + (AzurevmClient, "list_virtual_machines_in_scale_set"), + (AzurevmClient, "list_virtual_machines"), } PAGEABLE_OPERATION_CASES = [ @@ -163,20 +194,29 @@ if (operation_case[1], operation_case[2]) in EXPECTED_PAGEABLE_OPERATIONS ] +CONTINUATION_PAGEABLE_OPERATION_CASES = [ + operation_case for operation_case in OPERATION_CASES + if (operation_case[1], operation_case[2]) in CONTINUATION_PAGEABLE_OPERATIONS +] + def test_expected_pageable_operations_remain_iterator_contracts() -> None: - """Test every declared pageable operation stays in coverage and is an async iterator.""" + """Test every declared pageable operation returns an asynchronous pager.""" assert {(case[1], case[2]) for case in PAGEABLE_OPERATION_CASES} == EXPECTED_PAGEABLE_OPERATIONS - assert len(PAGEABLE_OPERATION_CASES) == 11 + assert len(PAGEABLE_OPERATION_CASES) == 18 for client_type, operation in EXPECTED_PAGEABLE_OPERATIONS: - assert inspect.isasyncgenfunction(getattr(client_type, f"{operation}_async")), operation + return_type = get_type_hints(getattr(client_type, operation))["return"] + assert get_origin(return_type) is AsyncItemPaged, operation @pytest.mark.parametrize("empty_first_page", [False, True]) @pytest.mark.parametrize( CASE_PARAMETER_NAMES, - PAGEABLE_OPERATION_CASES, - ids=[f"{case[0].__name__}.{case[2]}" for case in PAGEABLE_OPERATION_CASES], + CONTINUATION_PAGEABLE_OPERATION_CASES, + ids=[ + f"{case[0].__name__}.{case[2]}" + for case in CONTINUATION_PAGEABLE_OPERATION_CASES + ], ) @pytest.mark.asyncio async def test_newly_generated_pageable_contract_follows_later_pages( @@ -199,7 +239,7 @@ async def test_newly_generated_pageable_contract_follows_later_pages( ) as client: with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, side_effect=[ MockResponse(status=200, text=json.dumps({ @@ -230,11 +270,55 @@ async def test_newly_generated_pageable_contract_follows_later_pages( } +@pytest.mark.asyncio +async def test_relative_continuation_resolves_against_current_page( + mock_credential: Any, +) -> None: + """Test a bare relative continuation keeps the current nested route.""" + async with AzurevmClient( + "https://example.azure.com/connections/test", + credential=mock_credential, + ) as client: + with patch.object( + client._http_client, + "send", + new_callable=AsyncMock, + side_effect=[ + MockResponse( + status=200, + text=json.dumps({"value": [], "nextLink": "next-page"}), + ), + MockResponse( + status=200, + text=json.dumps({"value": [{"id": "vm-2"}]}), + ), + ], + ) as transport: + items = [ + item async for item in client.list_virtual_machines_in_scale_set( + subscription_id="subscription", + resource_group_name="group", + virtual_machine_scale_set_name="scale-set", + ) + ] + + assert items == [{"id": "vm-2"}] + assert transport.await_args_list[1].args == ( + "GET", + "https://example.azure.com/connections/test/subscriptions/subscription/" + "resourcegroups/group/providers/Microsoft.Compute/virtualMachineScaleSets/" + "scale-set/next-page", + ) + + @pytest.mark.parametrize("status,body", [(200, ""), (200, '{"value": []}'), (204, "")]) @pytest.mark.parametrize( CASE_PARAMETER_NAMES, - PAGEABLE_OPERATION_CASES, - ids=[f"{case[0].__name__}.{case[2]}" for case in PAGEABLE_OPERATION_CASES], + CONTINUATION_PAGEABLE_OPERATION_CASES, + ids=[ + f"{case[0].__name__}.{case[2]}" + for case in CONTINUATION_PAGEABLE_OPERATION_CASES + ], ) @pytest.mark.asyncio async def test_newly_generated_pageable_contract_preserves_empty_response( @@ -255,7 +339,7 @@ async def test_newly_generated_pageable_contract_preserves_empty_response( ) as client: with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=status, text=body), ) as transport: @@ -288,13 +372,17 @@ async def test_newly_generated_operation_success_contract( credential=mock_credential, ) is_pageable = (client_type, operation) in EXPECTED_PAGEABLE_OPERATIONS - response_payload = {"value": [{"id": "item-1"}]} if is_pageable else {"ok": True} + response_text = ( + generated_pager_response_text(getattr(client_type, operation)) + if is_pageable + else '{"ok": true}' + ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, - return_value=MockResponse(status=200, text=json.dumps(response_payload)), + return_value=MockResponse(status=200, text=response_text), ) as mock_send: result = await invoke_generated_operation( client, @@ -307,7 +395,7 @@ async def test_newly_generated_operation_success_contract( assert method == expected_method assert expected_path in request_url assert (mock_send.call_args.kwargs["body"] is not None) is expects_body - assert result == (response_payload["value"] if is_pageable else response_payload) + assert result == ([{"ok": True}] if is_pageable else {"ok": True}) @pytest.mark.parametrize( @@ -333,7 +421,7 @@ async def test_newly_generated_operation_rejects_error_response( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=400, text="bad request"), ): diff --git a/tests/test_replicon.py b/tests/test_replicon.py index 172c29b..e40dca8 100644 --- a/tests/test_replicon.py +++ b/tests/test_replicon.py @@ -3,7 +3,8 @@ """Contract tests for RepliconClient.""" import azure.connectors.replicon as replicon_module -from azure.connectors.replicon import RepliconClient, TRIGGER_OPERATIONS +from azure.connectors.aio.replicon import RepliconClient +from azure.connectors.replicon import TRIGGER_OPERATIONS from tests.generated_connector_test_utils import GeneratedConnectorContractTests diff --git a/tests/test_retry_safety.py b/tests/test_retry_safety.py index e05534a..f803e3b 100644 --- a/tests/test_retry_safety.py +++ b/tests/test_retry_safety.py @@ -10,7 +10,7 @@ from azure.core.exceptions import ServiceRequestError from azure.core.pipeline.transport import AsyncHttpTransport -from azure.connectors.sdk.http_client import ConnectorHttpClient +from azure.connectors.sdk.aio.http_client import ConnectorHttpClient class RecordingTransport(AsyncHttpTransport): @@ -78,7 +78,7 @@ async def send_with_transport( retry_unsafe_http_methods=retry_unsafe_http_methods, transport=transport, ) - response = await client.send_async( + response = await client.send( method, "https://example.com/action", body=body, @@ -136,7 +136,7 @@ async def test_method_case_is_normalized_before_retry_and_dispatch( transport=transport, ) with pytest.raises(ServiceRequestError): - await client.send_async(method, "https://example.com/action") + await client.send(method, "https://example.com/action") else: response, transport = await send_with_transport(method, *outcomes) assert response.status == (200 if expected_attempts == 2 else 500) @@ -234,7 +234,7 @@ async def test_cancellation_does_not_retry() -> None: ) with pytest.raises(asyncio.CancelledError): - await client.send_async("GET", "https://example.com/action") + await client.send("GET", "https://example.com/action") assert len(transport.requests) == 1 diff --git a/tests/test_revai.py b/tests/test_revai.py index 917955c..ce11284 100644 --- a/tests/test_revai.py +++ b/tests/test_revai.py @@ -8,10 +8,12 @@ from azure.core.credentials import AzureKeyCredential import azure.connectors.revai as revai_module -from azure.connectors.revai import AlignmentInput, RevaiClient, TranscriptionInput +from azure.connectors.aio.revai import RevaiClient +from azure.connectors.revai import AlignmentInput, TranscriptionInput from azure.connectors.sdk import ConnectorException from tests.conftest import MockResponse from tests.generated_connector_test_utils import ( + generated_pager_response_text, get_generated_operations, invoke_generated_operation, ) @@ -22,16 +24,16 @@ "alignment": ("POST", "/alignment/v1/jobs", True), "alignment_delete": ("DELETE", "/alignment/v1/jobs/value", False), "alignment_get": ("GET", "/alignment/v1/jobs/value", False), - "alignment_transcript_get": ( + "list_alignment_transcript_get": ( "GET", "/alignment/v1/jobs/value/transcript", False, ), - "alignments_get": ("GET", "/alignment/v1/jobs", False), + "list_alignments_get": ("GET", "/alignment/v1/jobs", False), "analysis": ("POST", "/sentiment_analysis/v1/jobs", True), "analysis_delete": ("DELETE", "/sentiment_analysis/v1/jobs/value", False), "analysis_get": ("GET", "/sentiment_analysis/v1/jobs/value", False), - "analysis_result_get": ( + "list_analysis_result_get": ( "GET", "/sentiment_analysis/v1/jobs/value/result", False, @@ -45,12 +47,12 @@ "extraction": ("POST", "/topic_extraction/v1/jobs", True), "extraction_delete": ("DELETE", "/topic_extraction/v1/jobs/value", False), "extraction_get": ("GET", "/topic_extraction/v1/jobs/value", False), - "extraction_result_get": ( + "list_extraction_result_get": ( "GET", "/topic_extraction/v1/jobs/value/result", False, ), - "extractions_get": ("GET", "/topic_extraction/v1/jobs", False), + "list_extractions_get": ("GET", "/topic_extraction/v1/jobs", False), "identification": ("POST", "/languageid/v1/jobs", True), "identification_delete": ("DELETE", "/languageid/v1/jobs/value", False), "identification_get": ("GET", "/languageid/v1/jobs/value", False), @@ -59,8 +61,8 @@ "/languageid/v1/jobs/value/result", False, ), - "identifications_get": ("GET", "/languageid/v1/jobs", False), - "transcript_get": ( + "list_identifications_get": ("GET", "/languageid/v1/jobs", False), + "list_transcript_get": ( "GET", "/speechtotext/v1/jobs/value/transcript", False, @@ -68,8 +70,8 @@ "transcription": ("POST", "/speechtotext/v1/jobs", True), "transcription_delete": ("DELETE", "/speechtotext/v1/jobs/value", False), "transcription_get": ("GET", "/speechtotext/v1/jobs/value", False), - "transcriptions_get": ("GET", "/speechtotext/v1/jobs", False), - "vocabularies_get": ("GET", "/speechtotext/v1/vocabularies", False), + "list_transcriptions_get": ("GET", "/speechtotext/v1/jobs", False), + "list_vocabularies_get": ("GET", "/speechtotext/v1/vocabularies", False), "vocabulary": ("POST", "/speechtotext/v1/vocabularies", True), "vocabulary_delete": ( "DELETE", @@ -79,7 +81,14 @@ "vocabulary_get": ("GET", "/speechtotext/v1/vocabularies/value", False), } ALL_OPERATIONS = list(SUCCESS_CONTRACTS) -NO_RESULT_OPERATIONS = {"analysises_get"} +NO_RESULT_OPERATIONS = { + "analysises_get", +} +PAGEABLE_OPERATIONS = { + operation + for operation in ALL_OPERATIONS + if operation.startswith("list_") +} class TestRevaiClient: @@ -137,12 +146,17 @@ async def test_generated_operation_success_contract( "https://example.azure.com/connections/test", credential=mock_credential, ) + response_text = ( + generated_pager_response_text(getattr(client, operation)) + if operation in PAGEABLE_OPERATIONS + else '{"ok": true}' + ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, - return_value=MockResponse(status=200, text='{"ok": true}'), + return_value=MockResponse(status=200, text=response_text), ) as mock_send: result = await invoke_generated_operation(client, operation, revai_module) @@ -150,7 +164,13 @@ async def test_generated_operation_success_contract( assert method == expected_method assert url.endswith(expected_url_suffix) assert (mock_send.call_args.kwargs["body"] is not None) is expects_body - expected_result = None if operation in NO_RESULT_OPERATIONS else {"ok": True} + expected_result = ( + None + if operation in NO_RESULT_OPERATIONS + else [{"ok": True}] + if operation in PAGEABLE_OPERATIONS + else {"ok": True} + ) assert result == expected_result @pytest.mark.asyncio @@ -163,12 +183,13 @@ async def test_create_transcription_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"id": "job-1"}'), ) as mock_send: - result = await client.transcription_async( + result = await client.transcription( input=TranscriptionInput( + notification_config={"url": "https://example.com/callback"}, source_config={"url": "https://example.com/audio.wav"}, metadata="sample", ), @@ -190,11 +211,11 @@ async def test_alignment_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"id": "alignment-1"}'), ) as mock_send: - await client.alignment_async( + await client.alignment( input=AlignmentInput( source_config={"url": "https://example.com/audio.wav"}, transcript_text="Hello world", @@ -215,11 +236,11 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=204, text=""), ): - result = await client.account_get_async() + result = await client.account_get() assert result is None @@ -238,7 +259,7 @@ async def test_non_success_response_raises_exception( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=400, text="bad request"), ): diff --git a/tests/test_root_client_exports.py b/tests/test_root_client_exports.py new file mode 100644 index 0000000..500b82e --- /dev/null +++ b/tests/test_root_client_exports.py @@ -0,0 +1,68 @@ +# ------------------------------------------------------------ +# Copyright (c) Microsoft Corporation. All rights reserved. +# ------------------------------------------------------------ + +"""Tests for lazy package-root connector exports.""" + +from __future__ import annotations + +import subprocess +import sys + +import pytest + +import azure.connectors as connectors +import azure.connectors.aio as aio_connectors + + +@pytest.mark.parametrize( + ("package_name", "module_name"), + [ + ("azure.connectors", "azure.connectors.arm"), + ("azure.connectors.aio", "azure.connectors.aio.arm"), + ], +) +def test_client_export_is_loaded_lazily( + package_name: str, + module_name: str, +) -> None: + """Keep connector modules unloaded until a package export is requested.""" + script = f""" +import importlib +import sys + +package = importlib.import_module("{package_name}") +assert "{module_name}" not in sys.modules +client_type = package.ArmClient +assert "{module_name}" in sys.modules +assert client_type is sys.modules["{module_name}"].ArmClient +""" + + subprocess.run([sys.executable, "-c", script], check=True) + + +@pytest.mark.parametrize("package", [connectors, aio_connectors]) +def test_client_export_propagates_import_error( + package: object, + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Raise a connector import failure instead of hiding it.""" + monkeypatch.delitem(vars(package), "ArmClient", raising=False) + + def fail_import(name: str, package_name: str) -> None: + raise ImportError(f"Failed to import '{name}' from '{package_name}'.") + + monkeypatch.setattr(package, "import_module", fail_import) + + with pytest.raises(ImportError, match="Failed to import '.arm'"): + getattr(package, "ArmClient") + + +def test_client_inventory_matches_generated_registry() -> None: + """Expose every generated client through both package roots.""" + expected_names = set(connectors.CLIENT_REGISTRY) + + assert expected_names <= set(dir(connectors)) + assert expected_names <= set(connectors.__all__) + assert expected_names <= set(dir(aio_connectors)) + assert expected_names <= set(aio_connectors.__all__) diff --git a/tests/test_root_schema_serialization.py b/tests/test_root_schema_serialization.py index baac85a..a82fb28 100644 --- a/tests/test_root_schema_serialization.py +++ b/tests/test_root_schema_serialization.py @@ -7,7 +7,7 @@ import pytest -from azure.connectors.sdk.http_client import ConnectorHttpClient +from azure.connectors.sdk.aio.http_client import ConnectorHttpClient from azure.connectors.sdk.serialization import to_wire from azure.connectors.signinghub import HandSignature, ValidationRule from azure.connectors.teams import ( @@ -62,7 +62,7 @@ async def test_array_root_is_serialized_through_send_async( new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.send_async( + await client.send( "POST", "https://api.example.com/messages", body=messages, diff --git a/tests/test_rss.py b/tests/test_rss.py index 780e0c6..efcad15 100644 --- a/tests/test_rss.py +++ b/tests/test_rss.py @@ -8,9 +8,9 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.rss import RssClient from azure.connectors.rss import ( FeedItem, - RssClient, TRIGGER_OPERATIONS, TriggerBatchResponseFeedItem, ) @@ -18,15 +18,18 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result async def _invoke_operation(client: RssClient, operation: str): """Invoke an RSS operation by name for shared parameterized tests.""" if operation == "list_feed_items": - return await client.list_feed_items_async( - feed_url="https://contoso.example/feed.xml", - since="2026-01-01T00:00:00Z", - since_property="UpdatedOn", + return await resolve_generated_result( + client.list_feed_items( + feed_url="https://contoso.example/feed.xml", + since="2026-01-01T00:00:00Z", + since_property="UpdatedOn", + ) ) raise ValueError(f"Unsupported operation '{operation}'.") @@ -65,7 +68,7 @@ def test_init_with_custom_settings(self, mock_credential): client = RssClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -123,14 +126,16 @@ async def test_list_feed_items_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_feed_items_async( - feed_url="https://contoso.example/feed.xml", - since="2026-01-01T00:00:00Z", - since_property="UpdatedOn", + result = await resolve_generated_result( + client.list_feed_items( + feed_url="https://contoso.example/feed.xml", + since="2026-01-01T00:00:00Z", + since_property="UpdatedOn", + ) ) assert len(result) == 1 @@ -161,7 +166,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -179,11 +184,11 @@ def test_callable_method_signatures(self): actual_signatures = { name: tuple(inspect.signature(method).parameters) for name, method in vars(RssClient).items() - if inspect.iscoroutinefunction(method) + if callable(method) and not name.startswith("_") } assert actual_signatures == { - "list_feed_items_async": ( + "list_feed_items": ( "self", "feed_url", "since", @@ -213,9 +218,9 @@ class TestRssTypeSerialization: def test_dataclass_instances_initialize_expected_defaults(self): """Test generated dataclasses initialize with expected default values.""" - feed_item = FeedItem() + feed_item = FeedItem(title="Item") trigger_response = TriggerBatchResponseFeedItem() assert feed_item.id is None - assert feed_item.title is None + assert feed_item.title == "Item" assert trigger_response.value is None diff --git a/tests/test_salesforce.py b/tests/test_salesforce.py index 8a2bd6c..8e530d1 100644 --- a/tests/test_salesforce.py +++ b/tests/test_salesforce.py @@ -7,9 +7,9 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.salesforce import SalesforceClient from azure.connectors.salesforce import ( CloseJobRequest, - SalesforceClient, TRIGGER_OPERATIONS, ) from azure.connectors.sdk import ( @@ -58,7 +58,7 @@ def test_init_with_custom_settings(self, mock_credential): client = SalesforceClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -141,11 +141,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await resolve_generated_result(client.get_tables_async()) + result = await resolve_generated_result(client.list_tables()) mock_send.assert_called_once() call_args = mock_send.call_args @@ -165,12 +165,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(client.get_tables_async()) + await resolve_generated_result(client.list_tables()) assert exc_info.value.status_code == 401 @@ -190,11 +190,11 @@ async def test_with_query_parameters(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await resolve_generated_result(client.get_items_async( + await resolve_generated_result(client.list_items( table="account", filter="Name eq 'Contoso'", top="5", @@ -229,11 +229,11 @@ async def test_sends_request_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_job_async(input=payload) + result = await client.create_job(input=payload) call_args = mock_send.call_args assert call_args[0][0] == "POST" @@ -257,12 +257,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: with pytest.raises(ConnectorException) as exc_info: - await client.create_job_async(input=payload) + await client.create_job(input=payload) mock_send.assert_called_once_with( "POST", @@ -295,11 +295,11 @@ async def test_sends_request_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.post_item_async(input=payload, table="account") + result = await client.post_item(input=payload, table="account") call_args = mock_send.call_args assert call_args[0][0] == "POST" @@ -322,11 +322,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.delete_item_async(table="account", id="001xx0000000001") + await client.delete_item(table="account", id="001xx0000000001") mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -340,16 +340,16 @@ async def test_error_response_raises_exception(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=404, text='{"error": "Not found"}') + mock_response = MockResponse(status=500, text='{"error": "Server error"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.delete_item_async(table="account", id="missing-id") + await client.delete_item(table="account", id="missing-id") class TestUploadJobDataAsync: @@ -367,11 +367,11 @@ async def test_success_sends_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.upload_job_data_async(input=payload, job_id="job-1") + await client.upload_job_data(input=payload, job_id="job-1") mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -395,12 +395,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.upload_job_data_async(input=payload, job_id="job-1") + await client.upload_job_data(input=payload, job_id="job-1") class TestHttpRequestAsync: @@ -418,11 +418,11 @@ async def test_success_sends_raw_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.http_request_async(input=payload) + result = await client.http_request(input=payload) mock_send.assert_called_once_with( "POST", @@ -447,12 +447,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.http_request_async(input=b"invalid request") + await client.http_request(input=b"invalid request") assert exc_info.value.status_code == 400 @@ -471,11 +471,11 @@ async def test_success_uses_acronym_aware_name(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.execute_sosl_query_async(q="FIND {Contoso}") + result = await client.execute_sosl_query(q="FIND {Contoso}") assert mock_send.call_args.args[0] == "GET" assert "/codeless/search?q=FIND%20%7BContoso%7D" in ( @@ -495,12 +495,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.execute_sosl_query_async(q="FIND") + await client.execute_sosl_query(q="FIND") class TestCloseJobAsync: @@ -518,11 +518,11 @@ async def test_success_sends_body_and_returns_result(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.close_job_async(input=payload, job_id="job-1") + result = await client.close_job(input=payload, job_id="job-1") mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -544,12 +544,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.close_job_async(input=payload, job_id="missing-job") + await client.close_job(input=payload, job_id="missing-job") class TestSalesforceDiscoveryOperations: @@ -560,23 +560,23 @@ class TestSalesforceDiscoveryOperations: ("method_name", "path_suffix"), [ ( - "get_external_id_fields_async", + "list_external_id_fields", "/datasets/default/tables/account/externalIdFields", ), ( - "get_metadata_for_get_item_async", + "get_metadata_for_get_item", "/$metadata.json/datasets/default/tables/account/getitem", ), ( - "get_metadata_for_patch_item_async", + "get_metadata_for_patch_item", "/$metadata.json/datasets/default/tables/account/patchitem", ), ( - "get_metadata_for_post_item_async", + "get_metadata_for_post_item", "/$metadata.json/datasets/default/tables/account/postitem", ), ( - "get_table_async", + "get_table", "/$metadata.json/datasets/default/tables/account", ), ], @@ -592,15 +592,22 @@ async def test_success_uses_expected_path( "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"name": "account"}') + response_text = ( + '{"value": [{"name": "account"}]}' + if method_name == "list_external_id_fields" + else '{"name": "account"}' + ) + mock_response = MockResponse(status=200, text=response_text) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await getattr(client, method_name)(table="account") + result = await resolve_generated_result( + getattr(client, method_name)(table="account") + ) mock_send.assert_called_once_with( "GET", @@ -611,17 +618,22 @@ async def test_success_uses_expected_path( client_request_id=None, response_hook=None, ) - assert result == {"name": "account"} + expected_result = ( + [{"name": "account"}] + if method_name == "list_external_id_fields" + else {"name": "account"} + ) + assert result == expected_result @pytest.mark.asyncio @pytest.mark.parametrize( "method_name", [ - "get_external_id_fields_async", - "get_metadata_for_get_item_async", - "get_metadata_for_patch_item_async", - "get_metadata_for_post_item_async", - "get_table_async", + "list_external_id_fields", + "get_metadata_for_get_item", + "get_metadata_for_patch_item", + "get_metadata_for_post_item", + "get_table", ], ) async def test_error_response_raises_exception( @@ -638,12 +650,14 @@ async def test_error_response_raises_exception( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await getattr(client, method_name)(table="account") + await resolve_generated_result( + getattr(client, method_name)(table="account") + ) assert exc_info.value.status_code == 404 diff --git a/tests/test_sdk_azure_core_pipeline.py b/tests/test_sdk_azure_core_pipeline.py index f142198..17f56ca 100644 --- a/tests/test_sdk_azure_core_pipeline.py +++ b/tests/test_sdk_azure_core_pipeline.py @@ -23,8 +23,9 @@ AsyncioRequestsTransport, ) -from azure.connectors.sdk import ConnectorClientBase, ConnectorException, ConnectorHttpClient -from azure.connectors.sdk.http_client import _JitterRetryPolicy +from azure.connectors.sdk.aio import ConnectorClientBase, ConnectorHttpClient +from azure.connectors.sdk.aio.http_client import _JitterRetryPolicy +from azure.connectors.sdk.exceptions import ConnectorException class RecordingCredential: @@ -134,7 +135,7 @@ async def test_token_credential_uses_fixed_scope_and_remains_open() -> None: transport = RecordingTransport(create_response(status=204, content=b"")) client = ConnectorHttpClient(credential, transport=transport) - await client.send_async("GET", "https://example.test/items") + await client.send("GET", "https://example.test/items") await client.close() assert credential.scopes == ("https://apihub.azure.com/.default",) @@ -152,7 +153,7 @@ async def test_key_credential_uses_bearer_authorization() -> None: transport=transport, ) - await client.send_async("GET", "https://example.test/items") + await client.send("GET", "https://example.test/items") assert transport.requests[0].headers["Authorization"] == "Bearer test-key" @@ -170,7 +171,7 @@ async def test_request_controls_and_response_hook_are_applied() -> None: transport=transport, ) - response = await client.send_async( + response = await client.send( "GET", "https://example.test/items", timeout=5.0, @@ -204,7 +205,7 @@ async def test_request_controls_override_client_default_headers() -> None: transport=transport, ) - await client.send_async( + await client.send( "GET", "https://example.test/items", headers={"x-custom": "operation"}, @@ -252,7 +253,7 @@ async def delayed_body(request: web.Request) -> web.StreamResponse: try: with pytest.raises(ServiceResponseTimeoutError): - await client.send_async( + await client.send( "GET", str(server.make_url("/")), timeout=request_timeout, @@ -284,7 +285,7 @@ async def test_nonpositive_timeout_disables_request_deadlines( transport=transport, ) - response = await client.send_async( + response = await client.send( "GET", "https://example.test/items", timeout=request_timeout, @@ -329,7 +330,7 @@ async def delayed_body(request: web.Request) -> web.StreamResponse: ) try: - response = await client.send_async( + response = await client.send( "GET", str(server.make_url("/")), timeout=request_timeout, @@ -372,7 +373,7 @@ async def empty_response(request: web.Request) -> web.Response: ) try: - response = await client.send_async( + response = await client.send( method, str(server.make_url("/")), response_hook=hook, @@ -406,7 +407,7 @@ async def empty_error(request: web.Request) -> web.Response: try: with pytest.raises(ConnectorException) as error: - await client.get_async(str(server.make_url("/"))) + await client.get(str(server.make_url("/"))) finally: await client.close() await server.close() @@ -439,7 +440,7 @@ async def test_requests_transport_accepts_timeout_controls( side_effect=requests.ConnectionError("synthetic connection error"), ) as request: with pytest.raises(ServiceRequestError): - await client.send_async( + await client.send( "GET", "https://example.test/items", **request_options, @@ -481,7 +482,7 @@ async def test_unsafe_method_does_not_retry_by_default() -> None: transport=transport, ) - response = await client.send_async("POST", "https://example.test/items") + response = await client.send("POST", "https://example.test/items") assert response.status == 500 assert len(transport.requests) == 1 @@ -502,7 +503,7 @@ async def test_unsafe_method_retries_when_enabled() -> None: transport=transport, ) - response = await client.send_async("POST", "https://example.test/items") + response = await client.send("POST", "https://example.test/items") assert response.status == 200 assert len(transport.requests) == 2 @@ -533,7 +534,7 @@ def test_jitter_retry_policy_adds_bounded_positive_jitter( } with patch( - "azure.connectors.sdk.http_client.random.uniform", + "azure.connectors.sdk.aio.http_client.random.uniform", return_value=jitter, ) as mock_uniform: backoff = policy.get_backoff_time(settings) @@ -555,7 +556,7 @@ def test_jitter_retry_policy_caps_backoff_after_jitter() -> None: } with patch( - "azure.connectors.sdk.http_client.random.uniform", + "azure.connectors.sdk.aio.http_client.random.uniform", return_value=0.5, ): backoff = policy.get_backoff_time(settings) @@ -581,7 +582,7 @@ async def test_injected_policies_run_at_their_configured_retry_scope() -> None: transport=transport, ) - response = await client.send_async("GET", "https://example.test/items") + response = await client.send("GET", "https://example.test/items") assert response.status == 200 assert events == [ @@ -610,7 +611,7 @@ async def test_explicit_chain_composes_injected_policy_scopes() -> None: transport=transport, ) - response = await client.send_async("GET", "https://example.test/items") + response = await client.send("GET", "https://example.test/items") assert response.status == 200 assert events == [ @@ -674,7 +675,7 @@ async def successful_response(request: web.Request) -> web.Response: ) try: - response = await client.send_async( + response = await client.send( "GET", str(server.make_url("/")), **request_options, @@ -700,7 +701,7 @@ async def test_explicit_no_retry_chain_omits_retry_policy_options() -> None: transport=transport, ) - response = await client.send_async("POST", "https://example.test/items") + response = await client.send("POST", "https://example.test/items") assert response.status == 200 assert "timeout" not in transport.request_options[0] diff --git a/tests/test_sdk_client_base.py b/tests/test_sdk_client_base.py index 6a825b2..8292dda 100644 --- a/tests/test_sdk_client_base.py +++ b/tests/test_sdk_client_base.py @@ -7,7 +7,7 @@ import pytest from azure.core.credentials import AzureKeyCredential -from azure.connectors.sdk.client_base import ConnectorClientBase +from azure.connectors.sdk.aio.client_base import ConnectorClientBase class TestClient(ConnectorClientBase): @@ -48,12 +48,12 @@ def test_init_with_none_credential_raises_error(self) -> None: def test_init_forwards_pipeline_settings(self, mock_credential) -> None: """Test that direct settings are forwarded to the HTTP client.""" with patch( - "azure.connectors.sdk.client_base.ConnectorHttpClient" + "azure.connectors.sdk.aio.client_base.ConnectorHttpClient" ) as mock_http_client: TestClient( mock_credential, max_retry_attempts=5, - timeout_seconds=60.0, + timeout=60.0, retry_unsafe_http_methods=True, retry_status=2, ) diff --git a/tests/test_sdk_exceptions.py b/tests/test_sdk_exceptions.py index 24977d2..e289f86 100644 --- a/tests/test_sdk_exceptions.py +++ b/tests/test_sdk_exceptions.py @@ -1,8 +1,10 @@ """Unit tests for SDK exceptions module.""" import pytest +from azure.core.exceptions import HttpResponseError from azure.connectors.sdk.exceptions import ConnectorException +from azure.connectors.sdk.response import ConnectorResponseSnapshot class TestConnectorException: @@ -55,6 +57,46 @@ def test_exception_inherits_from_exception(self): assert isinstance(ex, Exception) + def test_exception_inherits_from_http_response_error(self): + """Test that connector failures use the Azure Core HTTP hierarchy.""" + ex = ConnectorException("GET", "/", 500, "error") + + assert isinstance(ex, HttpResponseError) + assert ex.status_code == 500 + assert ex.reason == "Internal Server Error" + assert ex.response is not None + assert ex.response.status_code == 500 + assert ex.response.body() == b"error" + + def test_exception_preserves_completed_response(self): + """Expose response headers and content through the Azure Core contract.""" + response = ConnectorResponseSnapshot( + status=429, + headers={"Content-Type": "application/json", "Retry-After": "30"}, + text='{"error": "throttled"}', + content=b'{"error": "throttled"}', + ) + + ex = ConnectorException( + "POST", + "/items", + 429, + response.text, + response=response, + ) + + assert ex.reason == "Too Many Requests" + assert ex.response is not None + assert ex.response.request.method == "POST" + assert ex.response.request.url == "/items" + assert ex.response.headers["Retry-After"] == "30" + assert ex.response.content_type == "application/json" + assert ex.response.text() == response.text + assert ex.message == ( + 'POST /items failed with status 429: {"error": "throttled"}' + ) + assert str(ex).endswith('\nContent: {"error": "throttled"}') + def test_exception_can_be_raised_and_caught(self): """Test that exception can be raised and caught.""" with pytest.raises(ConnectorException) as exc_info: diff --git a/tests/test_sdk_http_client.py b/tests/test_sdk_http_client.py index 49d438b..cb4bde1 100644 --- a/tests/test_sdk_http_client.py +++ b/tests/test_sdk_http_client.py @@ -7,10 +7,10 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest -from azure.core.pipeline.transport import AsyncHttpTransport +from azure.core.pipeline.transport import AioHttpTransport, AsyncHttpTransport from azure.connectors.sdk.exceptions import ConnectorException -from azure.connectors.sdk.http_client import ConnectorHttpClient, ConnectorResponse +from azure.connectors.sdk.aio.http_client import ConnectorHttpClient, ConnectorResponse from azure.connectors.sdk.response import ConnectorResponseSnapshot @@ -115,6 +115,21 @@ def test_init_rejects_none_credential(self) -> None: with pytest.raises(ValueError, match="credential cannot be None"): ConnectorHttpClient(None) + def test_default_transport_uses_standard_tls_options( + self, + mock_credential, + ) -> None: + """Forward standard TLS options to the owned aio transport.""" + client = ConnectorHttpClient( + mock_credential, + connection_verify=False, + connection_cert="client.pem", + ) + + assert isinstance(client._transport, AioHttpTransport) + assert client._transport.connection_config.verify is False + assert client._transport.connection_config.cert == "client.pem" + def test_api_hub_scopes_constant(self) -> None: """Keep the fixed API Hub token scope.""" assert ConnectorHttpClient.API_HUB_SCOPES == [ @@ -134,7 +149,7 @@ async def test_close_exits_transport_not_credential(self, mock_credential) -> No mock_credential.close.assert_not_awaited() @pytest.mark.asyncio - async def test_send_async_serializes_dataclass_body(self, mock_credential) -> None: + async def test_send_serializes_dataclass_body(self, mock_credential) -> None: """Serialize dataclasses as JSON and omit None fields.""" client = ConnectorHttpClient(mock_credential) body = TestDataClass(name="test", value=42) @@ -145,7 +160,7 @@ async def test_send_async_serializes_dataclass_body(self, mock_credential) -> No new_callable=AsyncMock, return_value=create_snapshot(), ) as mock_send: - await client.send_async( + await client.send( "POST", "https://api.example.com/items", body=body, @@ -156,7 +171,7 @@ async def test_send_async_serializes_dataclass_body(self, mock_credential) -> No assert call.args[3]["Content-Type"] == "application/json" @pytest.mark.asyncio - async def test_send_async_preserves_wire_names_and_extensions( + async def test_send_preserves_wire_names_and_extensions( self, mock_credential, ) -> None: @@ -175,7 +190,7 @@ async def test_send_async_preserves_wire_names_and_extensions( new_callable=AsyncMock, return_value=create_snapshot(), ) as mock_send: - await client.send_async( + await client.send( "POST", "https://api.example.com/items", body=body, @@ -189,7 +204,7 @@ async def test_send_async_preserves_wire_names_and_extensions( } @pytest.mark.asyncio - async def test_send_async_serializes_dict_and_none_bodies( + async def test_send_serializes_dict_and_none_bodies( self, mock_credential, ) -> None: @@ -202,12 +217,12 @@ async def test_send_async_serializes_dict_and_none_bodies( new_callable=AsyncMock, return_value=create_snapshot(), ) as mock_send: - await client.send_async( + await client.send( "POST", "https://api.example.com/items", body={"key": "value"}, ) - await client.send_async( + await client.send( "GET", "https://api.example.com/items", body=None, @@ -224,7 +239,7 @@ async def test_send_async_serializes_dict_and_none_bodies( ("application/pdf", "application/pdf"), ], ) - async def test_send_async_sends_binary_body_verbatim( + async def test_send_sends_binary_body_verbatim( self, mock_credential, content_type: str | None, @@ -240,7 +255,7 @@ async def test_send_async_sends_binary_body_verbatim( new_callable=AsyncMock, return_value=create_snapshot(), ) as mock_send: - await client.send_async( + await client.send( "POST", "https://api.example.com/upload", body=body, @@ -252,7 +267,7 @@ async def test_send_async_sends_binary_body_verbatim( assert call.args[4] == body @pytest.mark.asyncio - async def test_send_async_filters_protected_headers(self, mock_credential) -> None: + async def test_send_filters_protected_headers(self, mock_credential) -> None: """Prevent callers from replacing authentication and request identity.""" client = ConnectorHttpClient(mock_credential) @@ -262,7 +277,7 @@ async def test_send_async_filters_protected_headers(self, mock_credential) -> No new_callable=AsyncMock, return_value=create_snapshot(), ) as mock_send: - await client.send_async( + await client.send( "GET", "https://api.example.com/items", headers={ @@ -279,7 +294,7 @@ async def test_send_async_filters_protected_headers(self, mock_credential) -> No } @pytest.mark.asyncio - async def test_send_async_forwards_controls_and_invokes_hook( + async def test_send_forwards_controls_and_invokes_hook( self, mock_credential, ) -> None: @@ -294,7 +309,7 @@ async def test_send_async_forwards_controls_and_invokes_hook( new_callable=AsyncMock, return_value=response, ) as mock_send: - result = await client.send_async( + result = await client.send( "GET", "https://api.example.com/items", timeout=5.0, @@ -313,9 +328,9 @@ async def test_send_async_forwards_controls_and_invokes_hook( @pytest.mark.parametrize( "method_name, expected_method, arguments", [ - ("get_async", "GET", ("https://api.example.com/item",)), + ("get", "GET", ("https://api.example.com/item",)), ( - "post_async", + "post", "POST", ("https://api.example.com/item", {"name": "item"}), ), @@ -330,22 +345,22 @@ async def test_json_helpers_return_successful_payloads( ) -> None: """Deserialize successful GET and POST helper responses.""" client = ConnectorHttpClient(mock_credential) - client.send_async = AsyncMock( + client.send = AsyncMock( return_value=create_snapshot(text='{"name": "item"}') ) result = await getattr(client, method_name)(*arguments) assert result == {"name": "item"} - assert client.send_async.await_args.args[0] == expected_method + assert client.send.await_args.args[0] == expected_method @pytest.mark.asyncio @pytest.mark.parametrize( "method_name, expected_method, arguments", [ - ("get_async", "GET", ("https://api.example.com/item",)), + ("get", "GET", ("https://api.example.com/item",)), ( - "post_async", + "post", "POST", ("https://api.example.com/item", {"name": "item"}), ), @@ -360,7 +375,7 @@ async def test_json_helpers_raise_for_non_success( ) -> None: """Raise ConnectorException for non-success helper responses.""" client = ConnectorHttpClient(mock_credential) - client.send_async = AsyncMock( + client.send = AsyncMock( return_value=create_snapshot(status=404, text="missing") ) @@ -372,7 +387,7 @@ async def test_json_helpers_raise_for_non_success( assert exc_info.value.status_code == 404 @pytest.mark.asyncio - @pytest.mark.parametrize("method_name", ["get_async", "post_async"]) + @pytest.mark.parametrize("method_name", ["get", "post"]) async def test_json_helpers_return_none_for_empty_body( self, mock_credential, @@ -380,10 +395,10 @@ async def test_json_helpers_return_none_for_empty_body( ) -> None: """Return None for a successful response without content.""" client = ConnectorHttpClient(mock_credential) - client.send_async = AsyncMock(return_value=create_snapshot(text="")) + client.send = AsyncMock(return_value=create_snapshot(text="")) arguments = ( ("https://api.example.com/item", {}) - if method_name == "post_async" + if method_name == "post" else ("https://api.example.com/item",) ) diff --git a/tests/test_sdk_polling.py b/tests/test_sdk_polling.py new file mode 100644 index 0000000..32a04a8 --- /dev/null +++ b/tests/test_sdk_polling.py @@ -0,0 +1,327 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Unit tests for connector long-running operation polling.""" + +from datetime import datetime, timedelta, timezone +from email.utils import format_datetime +from unittest.mock import AsyncMock, MagicMock, patch + +import pytest +from azure.core.polling import AsyncLROPoller, LROPoller + +from azure.connectors.sdk.aio.polling import ( + ConnectorPollingMethod as AsyncConnectorPollingMethod, +) +from azure.connectors.sdk._polling import ( + get_retry_after_seconds, + resolve_polling_url, +) +from azure.connectors.sdk.exceptions import ConnectorException +from azure.connectors.sdk.polling import ConnectorPollingMethod +from azure.connectors.sdk.response import ConnectorResponseSnapshot + + +def create_response( + status: int, + headers: dict[str, str] | None = None, + text: str = "", +) -> ConnectorResponseSnapshot: + """Create an immutable connector response for polling tests.""" + return ConnectorResponseSnapshot( + status=status, + headers=headers or {}, + text=text, + content=text.encode("utf-8"), + ) + + +def test_sync_poller_follows_location_and_forwards_request_controls() -> None: + """Poll synchronously through the runtime URL with all request controls.""" + initial_response = create_response( + 202, + {"location": "https://backend.example/jobs/42", "Retry-After": "2"}, + ) + http_client = MagicMock() + http_client.send.return_value = create_response(200, text='{"status": "done"}') + client = MagicMock() + client._connection_runtime_url = "https://runtime.example/connections/1" + response_hook = MagicMock() + polling_method = ConnectorPollingMethod( + http_client=http_client, + polling_header_name="location", + timeout=5.0, + headers={"x-test": "value"}, + client_request_id="request-id", + response_hook=response_hook, + ) + + with patch("azure.connectors.sdk.polling.time.sleep") as sleep: + poller = LROPoller( + client, + initial_response, + lambda response: response.text, + polling_method, + ) + result = poller.result() + + assert result == '{"status": "done"}' + sleep.assert_called_once_with(2.0) + http_client.send.assert_called_once_with( + "GET", + "https://runtime.example/connections/1/jobs/42", + body=None, + timeout=5.0, + headers={"x-test": "value"}, + client_request_id="request-id", + response_hook=response_hook, + ) + assert poller.done() is True + assert poller.status() == "Succeeded" + + +@pytest.mark.parametrize( + ("updated_location", "expected_url"), + [ + ("43", "https://runtime.example/connections/1/jobs/pending/43"), + ("../43", "https://runtime.example/connections/1/jobs/43"), + ], +) +def test_sync_poller_resolves_relative_location_against_current_url( + updated_location: str, + expected_url: str, +) -> None: + """Resolve sync Location updates relative to the current polling request.""" + http_client = MagicMock() + http_client.send.side_effect = [ + create_response(202, {"Location": updated_location, "Retry-After": "0"}), + create_response(200), + ] + client = MagicMock() + client._connection_runtime_url = "https://runtime.example/connections/1" + + with patch("azure.connectors.sdk.polling.time.sleep"): + poller = LROPoller( + client, + create_response( + 202, + {"Location": "/jobs/pending/42", "Retry-After": "0"}, + ), + lambda response: response.text, + ConnectorPollingMethod(http_client, "Location"), + ) + poller.result() + + assert [call.args[1] for call in http_client.send.call_args_list] == [ + "https://runtime.example/connections/1/jobs/pending/42", + expected_url, + ] + + +@pytest.mark.asyncio +async def test_async_poller_updates_location_until_terminal_response() -> None: + """Poll asynchronously and honor a changed Location header.""" + initial_response = create_response( + 202, + {"Location": "/jobs/42", "Retry-After": "0"}, + ) + http_client = MagicMock() + http_client.send = AsyncMock( + side_effect=[ + create_response(202, {"Location": "?step=2", "Retry-After": "0"}), + create_response(204), + ] + ) + client = MagicMock() + client._connection_runtime_url = "https://runtime.example/connections/1" + polling_method = AsyncConnectorPollingMethod(http_client, "Location") + poller = AsyncLROPoller( + client, + initial_response, + lambda response: response.text or None, + polling_method, + ) + + with patch( + "azure.connectors.sdk.aio.polling.asyncio.sleep", + new_callable=AsyncMock, + ) as sleep: + result = await poller.result() + + assert result is None + assert sleep.await_count == 2 + assert [call.args[1] for call in http_client.send.await_args_list] == [ + "https://runtime.example/connections/1/jobs/42", + "https://runtime.example/connections/1/jobs/42?step=2", + ] + assert poller.done() is True + assert poller.status() == "Succeeded" + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + ("updated_location", "expected_url"), + [ + ("43", "https://runtime.example/connections/1/jobs/pending/43"), + ("../43", "https://runtime.example/connections/1/jobs/43"), + ], +) +async def test_async_poller_resolves_relative_location_against_current_url( + updated_location: str, + expected_url: str, +) -> None: + """Resolve async Location updates relative to the current polling request.""" + http_client = MagicMock() + http_client.send = AsyncMock( + side_effect=[ + create_response( + 202, + {"Location": updated_location, "Retry-After": "0"}, + ), + create_response(200), + ] + ) + client = MagicMock() + client._connection_runtime_url = "https://runtime.example/connections/1" + poller = AsyncLROPoller( + client, + create_response( + 202, + {"Location": "/jobs/pending/42", "Retry-After": "0"}, + ), + lambda response: response.text, + AsyncConnectorPollingMethod(http_client, "Location"), + ) + + with patch( + "azure.connectors.sdk.aio.polling.asyncio.sleep", + new_callable=AsyncMock, + ): + await poller.result() + + assert [call.args[1] for call in http_client.send.await_args_list] == [ + "https://runtime.example/connections/1/jobs/pending/42", + expected_url, + ] + + +def test_immediate_success_requires_no_polling() -> None: + """Return an immediate successful response without issuing a poll request.""" + http_client = MagicMock() + client = MagicMock() + client._connection_runtime_url = "https://runtime.example/connections/1" + poller = LROPoller( + client, + create_response(200, text='{"status": "done"}'), + lambda response: response.text, + ConnectorPollingMethod(http_client, "Location"), + ) + + assert poller.result() == '{"status": "done"}' + http_client.send.assert_not_called() + + +def test_missing_location_rejects_accepted_response() -> None: + """Reject an accepted response that cannot identify a polling URL.""" + client = MagicMock() + client._connection_runtime_url = "https://runtime.example/connections/1" + + with pytest.raises(ValueError, match="Location"): + LROPoller( + client, + create_response(202), + lambda response: response.text, + ConnectorPollingMethod(MagicMock(), "Location"), + ) + + +def test_terminal_error_raises_connector_exception() -> None: + """Raise a connector exception for a failed terminal polling response.""" + http_client = MagicMock() + http_client.send.return_value = create_response(500, text="failed") + client = MagicMock() + client._connection_runtime_url = "https://runtime.example/connections/1" + + with patch("azure.connectors.sdk.polling.time.sleep"): + poller = LROPoller( + client, + create_response(202, {"Location": "/jobs/42", "Retry-After": "0"}), + lambda response: response.text, + ConnectorPollingMethod(http_client, "Location"), + ) + with pytest.raises(ConnectorException): + poller.result() + + assert poller.status() == "Failed" + + +def test_resource_rejects_access_before_completion() -> None: + """Reject terminal resource access while polling remains in progress.""" + client = MagicMock() + client._connection_runtime_url = "https://runtime.example/connections/1" + polling_method = ConnectorPollingMethod(MagicMock(), "Location") + polling_method.initialize( + client, + create_response(202, {"Location": "/jobs/42"}), + lambda response: response.text, + ) + + with pytest.raises(RuntimeError, match="has not completed"): + polling_method.resource() + + +def test_continuation_tokens_are_explicitly_unsupported() -> None: + """Defer poller serialization to a later protocol phase.""" + polling_method = ConnectorPollingMethod(MagicMock(), "Location") + + with pytest.raises(TypeError, match="doesn't support"): + polling_method.get_continuation_token() + + +def test_retry_after_supports_http_dates_and_defaults() -> None: + """Parse HTTP-date delays and use the bounded default for malformed values.""" + retry_at = datetime.now(timezone.utc) + timedelta(seconds=60) + + delay = get_retry_after_seconds( + create_response(202, {"Retry-After": format_datetime(retry_at)}) + ) + + assert 55.0 <= delay <= 60.0 + assert get_retry_after_seconds(create_response(202)) == 1.0 + assert get_retry_after_seconds( + create_response(202, {"Retry-After": "invalid"}) + ) == 1.0 + + +@pytest.mark.parametrize("retry_after", ["Infinity", "-Infinity", "NaN", "1e309"]) +def test_retry_after_defaults_for_non_finite_numbers(retry_after: str) -> None: + """Use the finite default when Retry-After cannot represent a sleep delay.""" + assert get_retry_after_seconds( + create_response(202, {"Retry-After": retry_after}) + ) == 1.0 + + +def test_foreign_polling_url_is_rebased_without_forwarding_its_origin() -> None: + """Preserve backend path and query while using the authenticated runtime.""" + resolved = resolve_polling_url( + "https://backend.example/jobs/42?state=running", + "https://runtime.example/connections/1", + ) + + assert resolved == ( + "https://runtime.example/connections/1/jobs/42?state=running" + ) + + +def test_same_host_polling_url_rejects_scheme_or_port_changes() -> None: + """Reject an origin that resembles the runtime but changes its security boundary.""" + with pytest.raises(ValueError, match="scheme and port"): + resolve_polling_url( + "http://runtime.example/jobs/42", + "https://runtime.example/connections/1", + ) + + +def test_polling_method_rejects_unsupported_header_protocol() -> None: + """Reject status-document protocols outside the current Location contract.""" + with pytest.raises(ValueError, match="Only the 'Location'"): + ConnectorPollingMethod(MagicMock(), "Azure-AsyncOperation") diff --git a/tests/test_sdk_serialization.py b/tests/test_sdk_serialization.py index b8f84dd..046a2a5 100644 --- a/tests/test_sdk_serialization.py +++ b/tests/test_sdk_serialization.py @@ -1,6 +1,8 @@ """Unit tests for SDK wire serialization module.""" +from collections import UserDict from dataclasses import dataclass, field +from types import MappingProxyType from azure.connectors.sdk.serialization import to_wire @@ -87,3 +89,20 @@ def test_dict_values_are_converted_and_none_omitted(self): result = to_wire({"a": Leaf(leaf_value="x"), "b": None, "c": 1}) assert result == {"a": {"leafValue": "x"}, "c": 1} + + def test_mapping_values_are_recursively_converted(self): + """Test arbitrary mappings recurse and omit None values.""" + payload = UserDict( + { + "nested": MappingProxyType( + { + "model": Leaf(leaf_value="deep"), + "omitted": None, + } + ) + } + ) + + result = to_wire(payload) + + assert result == {"nested": {"model": {"leafValue": "deep"}}} diff --git a/tests/test_sdk_sync_runtime.py b/tests/test_sdk_sync_runtime.py new file mode 100644 index 0000000..5c7ea7c --- /dev/null +++ b/tests/test_sdk_sync_runtime.py @@ -0,0 +1,425 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. + +"""Tests for the Azure Core synchronous connector runtime.""" + +import json +import threading +import time +from dataclasses import dataclass +from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer +from unittest.mock import MagicMock + +import pytest +from azure.core.credentials import AccessToken, AzureKeyCredential +from azure.core.exceptions import ServiceResponseTimeoutError +from azure.core.pipeline.policies import HeadersPolicy, RetryPolicy, SansIOHTTPPolicy +from azure.core.pipeline.transport import HttpTransport + +from azure.connectors.sdk import ConnectorClientBase, ConnectorHttpClient + + +class RecordingCredential: + """Record token requests and lifecycle calls.""" + + def __init__(self) -> None: + """Initialize the credential.""" + self.scopes: tuple[str, ...] | None = None + self.closed = False + + def get_token(self, *scopes: str, **kwargs: object) -> AccessToken: + """Return a test token.""" + del kwargs + self.scopes = scopes + return AccessToken("test-token", 4_102_444_800) + + def close(self) -> None: + """Record an ownership violation.""" + self.closed = True + + +class RecordingTransport(HttpTransport): + """Record requests and return configured responses.""" + + def __init__(self, *responses: object) -> None: + """Initialize the transport.""" + self.responses = list(responses) + self.requests: list[object] = [] + self.request_options: list[dict[str, object]] = [] + self.sleep_durations: list[float] = [] + self.closed = False + + def send(self, request: object, **kwargs: object) -> MagicMock: + """Record and answer a request.""" + self.requests.append(request) + self.request_options.append(kwargs) + response = self.responses.pop(0) + if isinstance(response, Exception): + raise response + return response + + def open(self) -> None: + """Open the transport.""" + + def close(self) -> None: + """Close the transport.""" + self.closed = True + + def __enter__(self): + """Enter the transport context.""" + return self + + def __exit__(self, *args: object) -> None: + """Exit the transport context.""" + self.close() + + def sleep(self, duration: float) -> None: + """Record a retry delay without waiting.""" + self.sleep_durations.append(duration) + + +class RecordingPolicy(SansIOHTTPPolicy): + """Record policy execution and authorization state.""" + + def __init__(self, name: str, events: list[tuple[str, str | None]]) -> None: + """Initialize the recording policy.""" + self._name = name + self._events = events + + def on_request(self, request) -> None: + """Record request processing.""" + self._events.append( + (self._name, request.http_request.headers.get("Authorization")) + ) + + +class ConcreteConnectorClient(ConnectorClientBase): + """Provide a concrete generated-client lifecycle test double.""" + + @property + def connector_name(self) -> str: + """Get the connector name.""" + return "test" + + +@dataclass +class RequestBody: + """Represent a serializable request body.""" + + item_name: str + omitted: str | None = None + + +def create_response( + status: int = 200, + *, + headers: dict[str, str] | None = None, + content: bytes = b"{}", +) -> MagicMock: + """Create a response accepted by the Azure Core pipeline.""" + response = MagicMock() + response.status_code = status + response.headers = headers or {} + response.body = MagicMock(return_value=content) + response.text = MagicMock(return_value=content.decode("utf-8")) + return response + + +def test_token_credential_uses_fixed_scope_and_remains_open() -> None: + """Use the API Hub scope without taking credential ownership.""" + credential = RecordingCredential() + transport = RecordingTransport(create_response(status=204, content=b"")) + client = ConnectorHttpClient(credential, transport=transport) + + client.send("GET", "https://example.test/items") + client.close() + + assert credential.scopes == ("https://apihub.azure.com/.default",) + assert transport.requests[0].headers["Authorization"] == "Bearer test-token" + assert credential.closed is False + assert transport.closed is True + + +def test_request_controls_and_serialization_are_applied() -> None: + """Protect auth headers, serialize bodies, and invoke response hooks.""" + transport = RecordingTransport(create_response(headers={"x-result": "complete"})) + hook = MagicMock() + client = ConnectorHttpClient( + AzureKeyCredential("test-key"), + transport=transport, + ) + + response = client.send( + "POST", + "https://example.test/items", + RequestBody(item_name="item"), + headers={"x-custom": "value", "Authorization": "ignored"}, + client_request_id="request-id", + response_hook=hook, + ) + + request = transport.requests[0] + assert request.headers["Authorization"] == "Bearer test-key" + assert request.headers["x-custom"] == "value" + assert request.headers["x-ms-client-request-id"] == "request-id" + assert json.loads(request.content) == {"item_name": "item"} + hook.assert_called_once_with(response, response.headers) + + +@pytest.mark.parametrize( + ("default_timeout", "request_timeout"), + [ + (0.1, None), + (1.0, 0.1), + ], +) +def test_timeout_request_runs_transport_on_calling_thread( + default_timeout: float, + request_timeout: float | None, +) -> None: + """Keep timed synchronous transport work on the caller thread.""" + + class ThreadRecordingTransport(RecordingTransport): + """Record the thread that executes the transport request.""" + + def __init__(self, *responses: object) -> None: + """Initialize the transport.""" + super().__init__(*responses) + self.send_thread_id: int | None = None + + def send(self, request: object, **kwargs: object) -> MagicMock: + """Record the current thread before sending the request.""" + self.send_thread_id = threading.get_ident() + return super().send(request, **kwargs) + + transport = ThreadRecordingTransport(create_response()) + client = ConnectorHttpClient( + AzureKeyCredential("test-key"), + max_retry_attempts=1, + timeout_seconds=default_timeout, + transport=transport, + ) + + client.send( + "GET", + "https://example.test/items", + timeout=request_timeout, + ) + client.close() + + assert transport.send_thread_id == threading.get_ident() + assert transport.closed is True + + +def test_timeout_bounds_slow_drip_response_body() -> None: + """Enforce one elapsed deadline while a response body keeps producing data.""" + + class SlowDripHandler(BaseHTTPRequestHandler): + """Write response bytes frequently enough to evade a socket idle timeout.""" + + def do_GET(self) -> None: + """Write one byte per interval until the client closes the response.""" + self.send_response(200) + self.send_header("Content-Length", "10") + self.end_headers() + try: + for _ in range(10): + self.wfile.write(b"x") + self.wfile.flush() + time.sleep(0.04) + except (BrokenPipeError, ConnectionResetError): + pass + + def log_message(self, format: str, *args: object) -> None: + """Suppress local server request logs.""" + del format, args + + server = ThreadingHTTPServer(("127.0.0.1", 0), SlowDripHandler) + server_thread = threading.Thread(target=server.serve_forever, daemon=True) + server_thread.start() + client = ConnectorHttpClient( + AzureKeyCredential("test-key"), + max_retry_attempts=1, + timeout_seconds=0.1, + ) + + try: + started_at = time.monotonic() + with pytest.raises(ServiceResponseTimeoutError): + client.send("GET", f"http://127.0.0.1:{server.server_port}/") + elapsed = time.monotonic() - started_at + finally: + client.close() + server.shutdown() + server.server_close() + server_thread.join() + + assert elapsed < 0.3 + + +def test_timeout_uses_remaining_budget_for_blocking_body_read() -> None: + """Reduce the body socket timeout by time already spent receiving headers.""" + + class DelayedBodyHandler(BaseHTTPRequestHandler): + """Delay both response headers and the complete response body.""" + + def do_GET(self) -> None: + """Send headers after a delay, then stall before writing the body.""" + time.sleep(0.1) + self.send_response(200) + self.send_header("Content-Length", "1") + self.end_headers() + time.sleep(0.4) + try: + self.wfile.write(b"x") + self.wfile.flush() + except (BrokenPipeError, ConnectionResetError): + pass + + def log_message(self, format: str, *args: object) -> None: + """Suppress local server request logs.""" + del format, args + + server = ThreadingHTTPServer(("127.0.0.1", 0), DelayedBodyHandler) + server_thread = threading.Thread(target=server.serve_forever, daemon=True) + server_thread.start() + client = ConnectorHttpClient( + AzureKeyCredential("test-key"), + max_retry_attempts=1, + timeout_seconds=0.3, + ) + + try: + started_at = time.monotonic() + with pytest.raises(ServiceResponseTimeoutError): + client.send("GET", f"http://127.0.0.1:{server.server_port}/") + elapsed = time.monotonic() - started_at + finally: + client.close() + server.shutdown() + server.server_close() + server_thread.join() + + assert elapsed < 0.42 + + +def test_default_transport_uses_standard_tls_options() -> None: + """Apply standard Azure Core TLS options to the owned Requests transport.""" + client = ConnectorHttpClient( + AzureKeyCredential("test-key"), + connection_verify=False, + connection_cert="client.pem", + ) + + try: + assert client._transport.connection_config.verify is False + assert client._transport.connection_config.cert == "client.pem" + finally: + client.close() + + +def test_unsafe_method_does_not_retry_by_default() -> None: + """Keep unsafe connector operations to one attempt by default.""" + transport = RecordingTransport( + create_response(status=500), + create_response(status=200), + ) + client = ConnectorHttpClient( + AzureKeyCredential("test-key"), + max_retry_attempts=2, + initial_retry_delay_seconds=0, + transport=transport, + ) + + response = client.send("POST", "https://example.test/items") + + assert response.status == 500 + assert len(transport.requests) == 1 + + +def test_unsafe_method_retries_when_enabled() -> None: + """Retry an unsafe method only after explicit client opt-in.""" + transport = RecordingTransport( + create_response(status=500), + create_response(status=200), + ) + client = ConnectorHttpClient( + AzureKeyCredential("test-key"), + max_retry_attempts=2, + initial_retry_delay_seconds=0, + retry_unsafe_http_methods=True, + transport=transport, + ) + + response = client.send("POST", "https://example.test/items") + + assert response.status == 200 + assert len(transport.requests) == 2 + + +def test_explicit_chain_composes_injected_policy_scopes() -> None: + """Compose per-call and per-retry extensions with an explicit chain.""" + events: list[tuple[str, str | None]] = [] + transport = RecordingTransport( + create_response(status=500), + create_response(status=200), + ) + client = ConnectorHttpClient( + AzureKeyCredential("test-key"), + policies=[HeadersPolicy(), RetryPolicy(retry_total=1, retry_backoff_factor=0)], + per_call_policies=RecordingPolicy("per-call", events), + per_retry_policies=[RecordingPolicy("per-retry", events)], + transport=transport, + ) + + response = client.send("GET", "https://example.test/items") + + assert response.status == 200 + assert events == [ + ("per-call", None), + ("per-retry", None), + ("per-retry", None), + ] + + +def test_explicit_chain_rejects_per_retry_policy_without_retry() -> None: + """Reject per-retry extensions when an explicit chain cannot run them.""" + with pytest.raises(ValueError, match="no RetryPolicy"): + ConnectorHttpClient( + AzureKeyCredential("test-key"), + policies=[HeadersPolicy()], + per_retry_policies=RecordingPolicy("per-retry", []), + ) + + +def test_explicit_no_retry_chain_preserves_transport_timeout() -> None: + """Forward positive timeouts when an explicit chain omits retry policy.""" + transport = RecordingTransport(create_response()) + client = ConnectorHttpClient( + AzureKeyCredential("test-key"), + policies=[HeadersPolicy()], + transport=transport, + ) + + response = client.send( + "GET", + "https://example.test/items", + timeout=5.0, + ) + + assert response.status == 200 + assert transport.request_options[0]["connection_timeout"] == 5.0 + + +def test_generated_client_uses_synchronous_context_lifecycle() -> None: + """Close the owned transport through the generated client lifecycle.""" + transport = RecordingTransport(create_response()) + + with ConcreteConnectorClient( + AzureKeyCredential("test-key"), + timeout=60.0, + transport=transport, + ) as client: + assert client.connector_name == "test" + assert client.http_client._timeout_seconds == 60.0 + + assert transport.closed is True diff --git a/tests/test_seismicplanner.py b/tests/test_seismicplanner.py index 7836d71..4e73f1d 100644 --- a/tests/test_seismicplanner.py +++ b/tests/test_seismicplanner.py @@ -2,42 +2,45 @@ """Contract tests for SeismicplannerClient.""" -from typing import Any, Dict, Optional, get_type_hints +from typing import Any, Dict, Mapping, Optional, get_type_hints from unittest.mock import AsyncMock, patch import pytest import azure.connectors.seismicplanner as seismicplanner_module +from azure.connectors.aio.seismicplanner import SeismicplannerClient from azure.connectors.seismicplanner import ( CustomPropertyDataDisplay, CustomPropertyValues, - SeismicplannerClient, ) from tests.conftest import MockResponse -from tests.generated_connector_test_utils import GeneratedConnectorContractTests +from tests.generated_connector_test_utils import ( + GeneratedConnectorContractTests, + resolve_generated_result, +) OPERATION_CONTRACTS = { - "get_comments": ("GET", False), + "list_comments": ("GET", False), "create_comment": ("POST", True), "get_comment": ("GET", False), "delete_comment": ("DELETE", False), "update_comment": ("PUT", True), - "get_projects": ("GET", False), + "list_projects": ("GET", False), "delete_projects": ("DELETE", False), "create_project": ("POST", True), "get_project": ("GET", False), "delete_project": ("DELETE", False), "update_project": ("PUT", True), - "get_requests": ("GET", False), + "list_requests": ("GET", False), "delete_requests": ("DELETE", True), "create_request": ("POST", True), "get_request": ("GET", False), "delete_request": ("DELETE", False), "update_request": ("PUT", True), - "get_status_schemas": ("GET", False), + "list_status_schemas": ("GET", False), "get_status_schema": ("GET", False), - "get_tasks": ("GET", False), + "list_tasks": ("GET", False), "create_task": ("POST", True), "get_task": ("GET", False), "delete_task": ("DELETE", False), @@ -73,11 +76,13 @@ async def test_get_requests_encodes_csv_and_compatibility_values( ) as client: with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"value": []}'), ) as transport: - await client.get_requests_async(space_id="space-id", ids=identifiers) + await resolve_generated_result( + client.list_requests(space_id="space-id", ids=identifiers) + ) transport.assert_awaited_once() method, request_url = transport.await_args.args @@ -96,7 +101,7 @@ def test_localizations_use_typed_map_values(self) -> None: ) assert type_hints["localizations"] == Optional[ - Dict[str, CustomPropertyDataDisplay] + Dict[str, CustomPropertyDataDisplay | Mapping[str, Any]] ] assert model.localizations is not None assert model.localizations["en-US"].name == "English" diff --git a/tests/test_sendgrid.py b/tests/test_sendgrid.py index 5b236cc..cbd95ac 100644 --- a/tests/test_sendgrid.py +++ b/tests/test_sendgrid.py @@ -7,15 +7,16 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.sendgrid import SendgridClient from azure.connectors.sendgrid import ( AddGlobalSuppressRequestAndResponse, EmailRequest, - SendgridClient, ) from azure.connectors.sdk import ( ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import model_instance, resolve_generated_result class TestSendgridClientInitialization: @@ -51,7 +52,7 @@ def test_init_with_custom_settings(self, mock_credential): client = SendgridClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -114,23 +115,30 @@ async def test_add_global_suppression_success(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"recipient_emails": []}') + mock_response = MockResponse( + status=200, + text='{"recipient_emails": ["a@b.com"]}', + ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.add_global_suppression_async( - input=AddGlobalSuppressRequestAndResponse(recipient_emails=["a@b.com"]), + result = await resolve_generated_result( + client.add_global_suppression( + input=AddGlobalSuppressRequestAndResponse( + recipient_emails=["a@b.com"] + ), + ) ) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "POST" assert url.endswith("/suppressions/global") assert mock_send.call_args.kwargs["body"] is not None - assert result == {"recipient_emails": []} + assert result == {"recipient_emails": ["a@b.com"]} @pytest.mark.asyncio async def test_get_global_suppression_success(self, mock_credential): @@ -143,11 +151,11 @@ async def test_get_global_suppression_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_global_suppression_async(email="a@b.com") + result = await client.get_global_suppression(email="a@b.com") method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" @@ -165,11 +173,11 @@ async def test_delete_global_suppression_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.delete_global_suppression_async(email="a@b.com") + result = await client.delete_global_suppression(email="a@b.com") method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "DELETE" @@ -187,11 +195,11 @@ async def test_add_recipient_to_list_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.add_recipient_to_list_async( + result = await client.add_recipient_to_list( list_id="L1", recipient_id="R1", ) @@ -208,20 +216,22 @@ async def test_get_bounce_success(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"email": "a@b.com"}') + mock_response = MockResponse(status=200, text='[{"email": "a@b.com"}]') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_bounce_async(email="a@b.com") + result = await resolve_generated_result( + client.list_bounce(email="a@b.com") + ) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert url.endswith("/suppression/bounces/a%40b.com") - assert result == {"email": "a@b.com"} + assert result == [{"email": "a@b.com"}] @pytest.mark.asyncio async def test_delete_bounce_success(self, mock_credential): @@ -234,11 +244,11 @@ async def test_delete_bounce_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.delete_bounce_async(email="a@b.com") + result = await client.delete_bounce(email="a@b.com") method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "DELETE" @@ -256,11 +266,11 @@ async def test_check_email_is_in_unsubscribes_list_success(self, mock_credential with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.check_email_is_in_unsubscribes_list_async(email="a@b.com") + result = await client.check_email_is_in_unsubscribes_list(email="a@b.com") method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" @@ -278,12 +288,17 @@ async def test_send_email_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.send_email_async( - input=EmailRequest(to="a@b.com", subject="Hi", text="Hello"), + result = await client.send_email( + input=model_instance( + EmailRequest, + to="a@b.com", + subject="Hi", + text="Hello", + ), ) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -303,16 +318,16 @@ async def test_list_recipient_lists_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_recipient_lists_async() + result = await resolve_generated_result(client.list_recipient_lists()) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert url.endswith("/v3/contactdb/lists") - assert result == {"lists": []} + assert result == [] @pytest.mark.asyncio async def test_list_recipients_success(self, mock_credential): @@ -325,20 +340,20 @@ async def test_list_recipients_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_recipients_async() + result = await resolve_generated_result(client.list_recipients()) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert url.endswith("/v3/contactdb/recipients") - assert result == {"recipients": []} + assert result == [] @pytest.mark.asyncio - async def test_empty_response_body_returns_none(self, mock_credential): - """Test a 2xx response with no body returns None.""" + async def test_empty_response_body_returns_empty_page(self, mock_credential): + """Test a paged 2xx response with no body returns no items.""" client = SendgridClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -347,13 +362,13 @@ async def test_empty_response_body_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.list_recipients_async() + result = await resolve_generated_result(client.list_recipients()) - assert result is None + assert result == [] class TestSendgridClientErrorHandling: @@ -367,7 +382,7 @@ class TestSendgridClientErrorHandling: "get_global_suppression", "delete_global_suppression", "add_recipient_to_list", - "get_bounce", + "list_bounce", "delete_bounce", "check_email_is_in_unsubscribes_list", "send_email", @@ -385,35 +400,39 @@ async def test_error_response_raises_exception(self, mock_credential, operation) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: if operation == "add_global_suppression": - await client.add_global_suppression_async( - input=AddGlobalSuppressRequestAndResponse() + await resolve_generated_result( + client.add_global_suppression( + input=AddGlobalSuppressRequestAndResponse() + ) ) elif operation == "get_global_suppression": - await client.get_global_suppression_async(email="a@b.com") + await client.get_global_suppression(email="a@b.com") elif operation == "delete_global_suppression": - await client.delete_global_suppression_async(email="a@b.com") + await client.delete_global_suppression(email="a@b.com") elif operation == "add_recipient_to_list": - await client.add_recipient_to_list_async( + await client.add_recipient_to_list( list_id="L1", recipient_id="R1" ) - elif operation == "get_bounce": - await client.get_bounce_async(email="a@b.com") + elif operation == "list_bounce": + await resolve_generated_result( + client.list_bounce(email="a@b.com") + ) elif operation == "delete_bounce": - await client.delete_bounce_async(email="a@b.com") + await client.delete_bounce(email="a@b.com") elif operation == "check_email_is_in_unsubscribes_list": - await client.check_email_is_in_unsubscribes_list_async(email="a@b.com") + await client.check_email_is_in_unsubscribes_list(email="a@b.com") elif operation == "send_email": - await client.send_email_async(input=EmailRequest()) + await client.send_email(input=model_instance(EmailRequest)) elif operation == "list_recipient_lists": - await client.list_recipient_lists_async() + await resolve_generated_result(client.list_recipient_lists()) else: - await client.list_recipients_async() + await resolve_generated_result(client.list_recipients()) assert exc_info.value.status_code == 500 @@ -423,6 +442,8 @@ class TestSendgridTypeSerialization: def test_dataclass_defaults(self): """Test dataclasses default to None and reserved names are renamed.""" - assert EmailRequest().from_ is None - assert EmailRequest().subject is None + email_request = model_instance(EmailRequest) + + assert email_request.from_ == "value" + assert email_request.attachments is None assert AddGlobalSuppressRequestAndResponse().recipient_emails is None diff --git a/tests/test_servicebus.py b/tests/test_servicebus.py index 140d1e7..dc6faf1 100644 --- a/tests/test_servicebus.py +++ b/tests/test_servicebus.py @@ -6,8 +6,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.servicebus import ServicebusClient from azure.connectors.servicebus import ( - ServicebusClient, ServiceBusMessage, SendMessagesInput, CreateTopicSubscriptionInput, @@ -17,16 +17,17 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result DISCOVERY_OPERATIONS = [ - ("get_entities", {}, "/entities"), - ("get_system_properties", {}, "/systemproperties"), - ("get_queues", {}, "/queues"), - ("get_session_options", {}, "/sessionoptions"), - ("get_topics", {}, "/topics"), + ("list_entities", {}, "/entities"), + ("list_system_properties", {}, "/systemproperties"), + ("list_queues", {}, "/queues"), + ("list_session_options", {}, "/sessionoptions"), + ("list_topics", {}, "/topics"), ( - "get_subscriptions", + "list_subscriptions", {"topic_name": "topic/one"}, "/topics/topic%252Fone/subscriptions", ), @@ -71,7 +72,7 @@ def test_init_with_custom_settings(self, mock_credential): client = ServicebusClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -137,10 +138,10 @@ async def test_send_message_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: message = ServiceBusMessage(content_data="Test message") - await client.send_message_async(input=message, entity_name="myqueue") + await client.send_message(input=message, entity_name="myqueue") mock_send.assert_called_once() call_args = mock_send.call_args @@ -157,10 +158,10 @@ async def test_send_message_with_system_properties(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: message = ServiceBusMessage(content_data="Test message") - await client.send_message_async( + await client.send_message( input=message, entity_name="myqueue", system_properties="true" @@ -183,10 +184,10 @@ async def test_send_messages_batch_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data: SendMessagesInput = [ServiceBusMessage(content_data="message")] - await client.send_messages_async(input=input_data, entity_name="myqueue") + await client.send_messages(input=input_data, entity_name="myqueue") mock_send.assert_called_once() call_args = mock_send.call_args @@ -203,11 +204,11 @@ async def test_send_messages_error_response(self, mock_credential): mock_response = MockResponse(400, '{"error": "Invalid batch format"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: input_data: SendMessagesInput = [] - await client.send_messages_async(input=input_data, entity_name="myqueue") + await client.send_messages(input=input_data, entity_name="myqueue") assert exc_info.value.status_code == 400 @@ -257,18 +258,19 @@ async def test_success_returns_json( "https://example.azure.com/connections/test", credential=mock_credential, ) + is_pageable = operation.startswith("list_") with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse( status=200, - text='{"value": ["item"]}', + text='["item"]' if is_pageable else '{"value": ["item"]}', ), ) as mock_send: - method = getattr(client, f"{operation}_async") - result = await method(**operation_args) + method = getattr(client, f"{operation}") + result = await resolve_generated_result(method(**operation_args)) mock_send.assert_called_once_with( "GET", @@ -279,7 +281,8 @@ async def test_success_returns_json( client_request_id=None, response_hook=None, ) - assert result == {"value": ["item"]} + expected_result = ["item"] if is_pageable else {"value": ["item"]} + assert result == expected_result @pytest.mark.asyncio @pytest.mark.parametrize( @@ -301,13 +304,13 @@ async def test_error_response_raises_exception( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=500, text="Server error"), ): - method = getattr(client, f"{operation}_async") + method = getattr(client, f"{operation}") with pytest.raises(ConnectorException) as exc_info: - await method(**operation_args) + await resolve_generated_result(method(**operation_args)) assert expected_path in exc_info.value.operation assert exc_info.value.status_code == 500 @@ -326,9 +329,9 @@ async def test_complete_message_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.complete_message_in_queue_async( + await client.complete_message_in_queue( queue_name="myqueue", lock_token="token-123" ) @@ -347,17 +350,17 @@ async def test_complete_message_error_response(self, mock_credential): credential=mock_credential ) - mock_response = MockResponse(404, '{"error": "Lock token expired"}') + mock_response = MockResponse(500, '{"error": "Server error"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.complete_message_in_queue_async( + await client.complete_message_in_queue( queue_name="myqueue", lock_token="expired-token" ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestAbandonMessageInQueue: @@ -373,9 +376,9 @@ async def test_abandon_message_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.abandon_message_in_queue_async( + await client.abandon_message_in_queue( queue_name="myqueue", lock_token="token-123" ) @@ -395,10 +398,10 @@ async def test_abandon_message_error_response(self, mock_credential): mock_response = MockResponse(404, '{"error": "Lock token expired"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.abandon_message_in_queue_async( + await client.abandon_message_in_queue( queue_name="myqueue", lock_token="expired-token" ) @@ -419,9 +422,9 @@ async def test_defer_message_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.defer_message_in_queue_async( + await client.defer_message_in_queue( queue_name="myqueue", lock_token="token-123" ) @@ -440,10 +443,10 @@ async def test_defer_message_error_response(self, mock_credential): mock_response = MockResponse(404, '{"error": "Lock token expired"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.defer_message_in_queue_async( + await client.defer_message_in_queue( queue_name="myqueue", lock_token="expired-token" ) @@ -465,9 +468,9 @@ async def test_get_deferred_message_success(self, mock_credential): response_data = {"contentData": "Deferred message", "sequenceNumber": 42} mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_deferred_message_from_queue_async( + result = await client.get_deferred_message_from_queue( queue_name="myqueue", sequence_number="42" ) @@ -487,10 +490,10 @@ async def test_get_deferred_message_error_response(self, mock_credential): mock_response = MockResponse(404, '{"error": "Message not found"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_deferred_message_from_queue_async( + await client.get_deferred_message_from_queue( queue_name="myqueue", sequence_number="999" ) @@ -511,9 +514,9 @@ async def test_dead_letter_message_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.dead_letter_message_in_queue_async( + await client.dead_letter_message_in_queue( queue_name="myqueue", lock_token="token-123", dead_letter_reason="Processing failed" @@ -534,10 +537,10 @@ async def test_dead_letter_error_response(self, mock_credential): mock_response = MockResponse(404, '{"error": "Lock token expired"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.dead_letter_message_in_queue_async( + await client.dead_letter_message_in_queue( queue_name="myqueue", lock_token="expired-token", dead_letter_reason="Failed" @@ -559,9 +562,9 @@ async def test_renew_lock_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.renew_lock_on_message_in_queue_async( + await client.renew_lock_on_message_in_queue( queue_name="myqueue", lock_token="token-123" ) @@ -584,9 +587,9 @@ async def test_close_session_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.close_session_in_queue_async( + await client.close_session_in_queue( queue_name="myqueue", session_id="session-123" ) @@ -604,17 +607,17 @@ async def test_close_session_error_response(self, mock_credential): credential=mock_credential ) - mock_response = MockResponse(404, '{"error": "Session not found"}') + mock_response = MockResponse(500, '{"error": "Server error"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.close_session_in_queue_async( + await client.close_session_in_queue( queue_name="myqueue", session_id="nonexistent" ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestRenewLockOnSessionInQueue: @@ -630,9 +633,9 @@ async def test_renew_session_lock_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.renew_lock_on_session_in_queue_async( + await client.renew_lock_on_session_in_queue( queue_name="myqueue", session_id="session-123" ) @@ -651,10 +654,10 @@ async def test_renew_session_lock_error_response(self, mock_credential): mock_response = MockResponse(404, '{"error": "Session not found"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.renew_lock_on_session_in_queue_async( + await client.renew_lock_on_session_in_queue( queue_name="myqueue", session_id="nonexistent" ) @@ -675,9 +678,9 @@ async def test_complete_topic_message_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.complete_message_in_topic_async( + await client.complete_message_in_topic( topic_name="mytopic", subscription_name="mysub", lock_token="token-123" @@ -696,18 +699,18 @@ async def test_complete_topic_message_error_response(self, mock_credential): credential=mock_credential ) - mock_response = MockResponse(404, '{"error": "Lock token expired"}') + mock_response = MockResponse(500, '{"error": "Server error"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.complete_message_in_topic_async( + await client.complete_message_in_topic( topic_name="mytopic", subscription_name="mysub", lock_token="expired-token" ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestAbandonMessageInTopic: @@ -723,9 +726,9 @@ async def test_abandon_topic_message_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.abandon_message_in_topic_async( + await client.abandon_message_in_topic( topic_name="mytopic", subscription_name="mysub", lock_token="token-123" @@ -745,10 +748,10 @@ async def test_abandon_topic_message_error_response(self, mock_credential): mock_response = MockResponse(404, '{"error": "Lock token expired"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.abandon_message_in_topic_async( + await client.abandon_message_in_topic( topic_name="mytopic", subscription_name="mysub", lock_token="expired-token" @@ -771,10 +774,10 @@ async def test_create_subscription_success(self, mock_credential): response_data = {"subscriptionName": "newsub"} mock_response = MockResponse(201, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = CreateTopicSubscriptionInput() - result = await client.create_topic_subscription_async( + result = await client.create_topic_subscription( input=input_data, topic_name="mytopic", subscription_name="newsub" @@ -795,11 +798,11 @@ async def test_create_subscription_error_response(self, mock_credential): mock_response = MockResponse(400, '{"error": "Invalid subscription name"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: input_data = CreateTopicSubscriptionInput() - await client.create_topic_subscription_async( + await client.create_topic_subscription( input=input_data, topic_name="mytopic", subscription_name="invalid" @@ -821,9 +824,9 @@ async def test_delete_subscription_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.delete_topic_subscription_async( + await client.delete_topic_subscription( topic_name="mytopic", subscription_name="mysub" ) @@ -841,17 +844,17 @@ async def test_delete_subscription_error_response(self, mock_credential): credential=mock_credential ) - mock_response = MockResponse(404, '{"error": "Subscription not found"}') + mock_response = MockResponse(500, '{"error": "Server error"}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.delete_topic_subscription_async( + await client.delete_topic_subscription( topic_name="mytopic", subscription_name="nonexistent" ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestDeadLetterMessageInTopic: @@ -867,9 +870,9 @@ async def test_dead_letter_topic_message_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.dead_letter_message_in_topic_async( + await client.dead_letter_message_in_topic( topic_name="mytopic", subscription_name="mysub", lock_token="token-123", @@ -893,9 +896,9 @@ async def test_close_topic_session_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.close_session_in_topic_async( + await client.close_session_in_topic( topic_name="mytopic", subscription_name="mysub", session_id="session-456" @@ -919,9 +922,9 @@ async def test_renew_topic_session_lock_success(self, mock_credential): mock_response = MockResponse(200) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.renew_lock_on_session_in_topic_async( + await client.renew_lock_on_session_in_topic( topic_name="mytopic", subscription_name="mysub", session_id="session-456" diff --git a/tests/test_sharepointonline.py b/tests/test_sharepointonline.py index 34dc175..9e72b34 100644 --- a/tests/test_sharepointonline.py +++ b/tests/test_sharepointonline.py @@ -6,8 +6,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.sharepointonline import SharepointonlineClient from azure.connectors.sharepointonline import ( - SharepointonlineClient, PostItemInput, PatchItemInput, CreateApprovalRequestInput, @@ -26,7 +26,7 @@ ) from azure.connectors.sdk.serialization import to_wire from tests.conftest import MockResponse -from tests.generated_connector_test_utils import resolve_generated_result +from tests.generated_connector_test_utils import model_instance, resolve_generated_result class TestSharepointonlineClientInitialization: @@ -62,7 +62,7 @@ def test_init_with_custom_settings(self, mock_credential): client = SharepointonlineClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -136,18 +136,19 @@ async def test_success_with_json_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_all_tables_async("https://contoso.sharepoint.com/sites/site1") + result = await resolve_generated_result( + client.list_all_tables("https://contoso.sharepoint.com/sites/site1") + ) call_args = mock_send.call_args assert call_args[0][0] == "GET" assert "/datasets/" in call_args[0][1] assert "/alltables" in call_args[0][1] - assert "value" in result - assert len(result["value"]) == 2 + assert len(result) == 2 @pytest.mark.asyncio async def test_dataset_url_encoding(self, mock_credential): @@ -161,12 +162,14 @@ async def test_dataset_url_encoding(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_all_tables_async( - "https://contoso.sharepoint.com/sites/site with spaces" + await resolve_generated_result( + client.list_all_tables( + "https://contoso.sharepoint.com/sites/site with spaces" + ) ) call_args = mock_send.call_args @@ -175,8 +178,8 @@ async def test_dataset_url_encoding(self, mock_credential): assert "/datasets/" in path @pytest.mark.asyncio - async def test_empty_response_returns_none(self, mock_credential): - """Test that empty response returns None.""" + async def test_empty_response_returns_empty_page(self, mock_credential): + """Test that an empty paged response returns no items.""" client = SharepointonlineClient( "https://example.azure.com/connections/test", credential=mock_credential @@ -186,12 +189,14 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_all_tables_async("https://contoso.sharepoint.com/sites/site1") - assert result is None + result = await resolve_generated_result( + client.list_all_tables("https://contoso.sharepoint.com/sites/site1") + ) + assert result == [] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -208,12 +213,16 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_all_tables_async("https://contoso.sharepoint.com/sites/missing") + await resolve_generated_result( + client.list_all_tables( + "https://contoso.sharepoint.com/sites/missing" + ) + ) assert exc_info.value.status_code == 404 @@ -239,12 +248,12 @@ async def test_create_file_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = b"document content" - result = await client.create_file_async( + result = await client.create_file( input_data, "https://contoso.sharepoint.com/sites/site1", "/Shared Documents", @@ -271,11 +280,11 @@ async def test_get_file_metadata(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_file_metadata_async( + result = await client.get_file_metadata( "https://contoso.sharepoint.com/sites/site1", "file123" ) @@ -299,12 +308,12 @@ async def test_update_file(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = b"updated document content" - result = await client.update_file_async( + result = await client.update_file( "https://contoso.sharepoint.com/sites/site1", "file123", input_data @@ -326,11 +335,11 @@ async def test_delete_file(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.delete_file_async( + result = await client.delete_file( "https://contoso.sharepoint.com/sites/site1", "file123" ) @@ -355,11 +364,11 @@ async def test_get_file_content(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_file_content_async( + result = await client.get_file_content( "https://contoso.sharepoint.com/sites/site1", "file123" ) @@ -381,12 +390,12 @@ async def test_create_file_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_file_async( + await client.create_file( b"document content", "https://contoso.sharepoint.com/sites/site1", "/Shared Documents", @@ -410,12 +419,12 @@ async def test_get_file_metadata_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_file_metadata_async( + await client.get_file_metadata( "https://contoso.sharepoint.com/sites/site1", "missing_file" ) @@ -437,12 +446,12 @@ async def test_delete_file_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.delete_file_async( + await client.delete_file( "https://contoso.sharepoint.com/sites/site1", "protected_file" ) @@ -468,15 +477,15 @@ async def test_create_new_folder(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.create_new_folder_async( + result = await client.create_new_folder( "https://contoso.sharepoint.com/sites/site1", "Documents", "/Shared Documents", - "NewFolder" + view="NewFolder" ) assert result["Name"] == "NewFolder" @@ -496,11 +505,11 @@ async def test_get_folder_metadata(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_folder_metadata_async( + result = await client.get_folder_metadata( "https://contoso.sharepoint.com/sites/site1", "folder123" ) @@ -522,16 +531,16 @@ async def test_create_folder_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_new_folder_async( + await client.create_new_folder( "https://contoso.sharepoint.com/sites/site1", "Documents", "/Shared Documents", - "ExistingFolder" + view="ExistingFolder" ) assert exc_info.value.status_code == 409 @@ -551,12 +560,12 @@ async def test_get_folder_metadata_error_raises_exception(self, mock_credential) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_folder_metadata_async( + await client.get_folder_metadata( "https://contoso.sharepoint.com/sites/site1", "missing_folder" ) @@ -582,11 +591,11 @@ async def test_get_items(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await resolve_generated_result(client.get_items_async( + result = await resolve_generated_result(client.list_items( "https://contoso.sharepoint.com/sites/site1", "CustomList" )) @@ -609,12 +618,12 @@ async def test_post_item(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = PostItemInput() - result = await client.post_item_async( + result = await client.post_item( "https://contoso.sharepoint.com/sites/site1", "CustomList", input_data @@ -639,11 +648,11 @@ async def test_get_item(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_item_async( + result = await client.get_item( "https://contoso.sharepoint.com/sites/site1", "CustomList", 1 @@ -667,12 +676,12 @@ async def test_patch_item(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = PatchItemInput() - result = await client.patch_item_async( + result = await client.patch_item( "https://contoso.sharepoint.com/sites/site1", "CustomList", 1, @@ -695,11 +704,11 @@ async def test_delete_item(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.delete_item_async( + result = await client.delete_item( "https://contoso.sharepoint.com/sites/site1", "CustomList", 1 @@ -724,12 +733,12 @@ async def test_get_items_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(client.get_items_async( + await resolve_generated_result(client.list_items( "https://contoso.sharepoint.com/sites/site1", "MissingList" )) @@ -751,12 +760,12 @@ async def test_post_item_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.post_item_async( + await client.post_item( "https://contoso.sharepoint.com/sites/site1", "CustomList", PostItemInput() @@ -779,12 +788,12 @@ async def test_delete_item_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.delete_item_async( + await client.delete_item( "https://contoso.sharepoint.com/sites/site1", "CustomList", 999 @@ -811,12 +820,12 @@ async def test_create_sharing_link(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - input_data = ItemPermissionCreateLinkBody() - result = await client.create_sharing_link_async( + input_data = model_instance(ItemPermissionCreateLinkBody) + result = await client.create_sharing_link( input_data, "https://contoso.sharepoint.com/sites/site1", "Documents", @@ -837,13 +846,13 @@ async def test_grant_access(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: from azure.connectors.sharepointonline import ItemGrantAccessBody - input_data = ItemGrantAccessBody() - result = await client.grant_access_async( + input_data = model_instance(ItemGrantAccessBody) + result = await client.grant_access( input_data, "https://contoso.sharepoint.com/sites/site1", "Documents", @@ -869,13 +878,13 @@ async def test_create_sharing_link_error_raises_exception(self, mock_credential) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_sharing_link_async( - ItemPermissionCreateLinkBody(), + await client.create_sharing_link( + model_instance(ItemPermissionCreateLinkBody), "https://contoso.sharepoint.com/sites/site1", "Documents", "item123" @@ -898,13 +907,13 @@ async def test_grant_access_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.grant_access_async( - ItemGrantAccessBody(), + await client.grant_access( + model_instance(ItemGrantAccessBody), "https://contoso.sharepoint.com/sites/site1", "Documents", "item123" @@ -931,11 +940,11 @@ async def test_copy_file(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.copy_file_async( + result = await client.copy_file( dataset="https://contoso.sharepoint.com/sites/site1", source="/Shared Documents/document.docx", destination="/Shared Documents/Backup/document_copy.docx" @@ -955,16 +964,19 @@ async def test_copy_file_async_route_is_preserved(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential ) - input_data = CopyFileParameters(source_file_id="file123") + input_data = model_instance( + CopyFileParameters, + source_file_id="file123", + ) mock_response = MockResponse(status=200, text='{"Name": "copy.docx"}') with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.copy_file_2_async( + result = await client.copy_file_2( input=input_data, dataset="https://contoso.sharepoint.com/sites/site1" ) @@ -1000,7 +1012,10 @@ async def test_copy_file_async_error_raises_exception( "https://example.azure.com/connections/test", credential=mock_credential ) - input_data = CopyFileParameters(source_file_id="file123") + input_data = model_instance( + CopyFileParameters, + source_file_id="file123", + ) mock_response = MockResponse( status=409, text='{"error": "Destination already exists"}' @@ -1008,12 +1023,12 @@ async def test_copy_file_async_error_raises_exception( with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.copy_file_2_async( + await client.copy_file_2( input=input_data, dataset="https://contoso.sharepoint.com/sites/site1" ) @@ -1035,13 +1050,13 @@ async def test_move_file(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): from azure.connectors.sharepointonline import MoveFileParameters - input_data = MoveFileParameters() - result = await client.move_file_async( + input_data = model_instance(MoveFileParameters) + result = await client.move_file( input_data, "https://contoso.sharepoint.com/sites/site1" ) @@ -1060,12 +1075,12 @@ async def test_copy_folder(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - input_data = CopyFolderParameters() - result = await client.copy_folder_async( + input_data = model_instance(CopyFolderParameters) + result = await client.copy_folder( input_data, "https://contoso.sharepoint.com/sites/site1" ) @@ -1087,12 +1102,12 @@ async def test_copy_file_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.copy_file_async( + await client.copy_file( dataset="https://contoso.sharepoint.com/sites/site1", source="/Shared Documents/missing.docx", destination="/Backup/missing.docx" @@ -1115,13 +1130,13 @@ async def test_move_file_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.move_file_async( - MoveFileParameters(), + await client.move_file( + model_instance(MoveFileParameters), "https://contoso.sharepoint.com/sites/site1" ) @@ -1146,12 +1161,12 @@ async def test_create_approval_request(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): input_data = CreateApprovalRequestInput() - result = await client.create_approval_request_async( + result = await client.create_approval_request( input_data, "https://contoso.sharepoint.com/sites/site1", "Documents", @@ -1173,11 +1188,11 @@ async def test_set_approval_status(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.set_approval_status_async( + result = await client.set_approval_status( "https://contoso.sharepoint.com/sites/site1", "Documents", "item123", @@ -1201,12 +1216,12 @@ async def test_create_approval_request_error_raises_exception(self, mock_credent with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_approval_request_async( + await client.create_approval_request( CreateApprovalRequestInput(), "https://contoso.sharepoint.com/sites/site1", "Documents", @@ -1231,12 +1246,12 @@ async def test_set_approval_status_error_raises_exception(self, mock_credential) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.set_approval_status_async( + await client.set_approval_status( "https://contoso.sharepoint.com/sites/site1", "Documents", "missing_item", @@ -1271,21 +1286,27 @@ async def test_multiple_consecutive_calls(self, mock_credential): credential=mock_credential ) - mock_response_1 = MockResponse(status=200, text='{"result": "first"}') - mock_response_2 = MockResponse(status=200, text='{"result": "second"}') + mock_response_1 = MockResponse( + status=200, + text='{"value": [{"result": "first"}]}', + ) + mock_response_2 = MockResponse( + status=200, + text='{"value": [{"result": "second"}]}', + ) with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, side_effect=[mock_response_1, mock_response_2] ): site_url = "https://contoso.sharepoint.com/sites/site1" - result_1 = await client.get_all_tables_async(site_url) - result_2 = await client.get_all_tables_async(site_url) + result_1 = await resolve_generated_result(client.list_all_tables(site_url)) + result_2 = await resolve_generated_result(client.list_all_tables(site_url)) - assert result_1 == {"result": "first"} - assert result_2 == {"result": "second"} + assert result_1 == [{"result": "first"}] + assert result_2 == [{"result": "second"}] @pytest.mark.asyncio async def test_json_parse_error_raises_exception(self, mock_credential): @@ -1299,12 +1320,16 @@ async def test_json_parse_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(json.JSONDecodeError): - await client.get_all_tables_async("https://contoso.sharepoint.com/sites/site1") + await resolve_generated_result( + client.list_all_tables( + "https://contoso.sharepoint.com/sites/site1" + ) + ) @pytest.mark.asyncio async def test_url_construction_with_multiple_trailing_slashes(self): @@ -1338,12 +1363,14 @@ async def test_dataset_with_special_characters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_all_tables_async( - "https://contoso.sharepoint.com/sites/site-name/subsite" + await resolve_generated_result( + client.list_all_tables( + "https://contoso.sharepoint.com/sites/site-name/subsite" + ) ) # Verify the call was made (URL encoding handled internally) @@ -1364,12 +1391,16 @@ async def test_server_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_all_tables_async("https://contoso.sharepoint.com/sites/site1") + await resolve_generated_result( + client.list_all_tables( + "https://contoso.sharepoint.com/sites/site1" + ) + ) assert exc_info.value.status_code == 500 @@ -1389,11 +1420,11 @@ async def test_check_out_file(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.check_out_file_async( + await client.check_out_file( "https://contoso.sharepoint.com/sites/site1", "Documents", "file123" @@ -1415,12 +1446,12 @@ async def test_check_in_file(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - input_data = FileCheckInParameters() - await client.check_in_file_async( + input_data = model_instance(FileCheckInParameters) + await client.check_in_file( input_data, "https://contoso.sharepoint.com/sites/site1", "Documents", @@ -1443,11 +1474,11 @@ async def test_discard_check_out(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.discard_file_check_out_async( + await client.discard_file_check_out( "https://contoso.sharepoint.com/sites/site1", "Documents", "file123" @@ -1472,12 +1503,12 @@ async def test_check_out_file_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.check_out_file_async( + await client.check_out_file( "https://contoso.sharepoint.com/sites/site1", "Documents", "locked_file" @@ -1504,14 +1535,16 @@ async def test_get_item_attachments(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_item_attachments_async( - "https://contoso.sharepoint.com/sites/site1", - "CustomList", - "1" + result = await resolve_generated_result( + client.list_item_attachments( + "https://contoso.sharepoint.com/sites/site1", + "CustomList", + "1" + ) ) assert isinstance(result, list) @@ -1531,12 +1564,12 @@ async def test_create_attachment(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = b"attachment content" - result = await client.create_attachment_async( + result = await client.create_attachment( input_data, "https://contoso.sharepoint.com/sites/site1", "CustomList", @@ -1562,11 +1595,11 @@ async def test_delete_attachment(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.delete_attachment_async( + await client.delete_attachment( "https://contoso.sharepoint.com/sites/site1", "CustomList", "1", @@ -1592,11 +1625,11 @@ async def test_get_attachment_content(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_attachment_content_async( + result = await client.get_attachment_content( "https://contoso.sharepoint.com/sites/site1", "CustomList", "1", @@ -1620,12 +1653,12 @@ async def test_create_attachment_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_attachment_async( + await client.create_attachment( b"attachment content", "https://contoso.sharepoint.com/sites/site1", "CustomList", @@ -1654,11 +1687,11 @@ async def test_search_for_user(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.search_for_user_async( + result = await client.search_for_user( "https://contoso.sharepoint.com/sites/site1", "CustomList", "entity1", @@ -1682,12 +1715,12 @@ async def test_search_for_user_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.search_for_user_async( + await client.search_for_user( "https://contoso.sharepoint.com/sites/site1", "CustomList", "entity1", @@ -1715,11 +1748,11 @@ async def test_get_file_item(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_file_item_async( + result = await client.get_file_item( "https://contoso.sharepoint.com/sites/site1", "Documents", "file123" @@ -1742,12 +1775,12 @@ async def test_patch_file_item(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = PatchFileItemInput() - result = await client.patch_file_item_async( + result = await client.patch_file_item( input_data, "https://contoso.sharepoint.com/sites/site1", "Documents", @@ -1770,11 +1803,11 @@ async def test_unshare_item(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.unshare_item_async( + await client.unshare_item( "https://contoso.sharepoint.com/sites/site1", "Documents", "item123" @@ -1799,12 +1832,12 @@ async def test_get_file_item_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_file_item_async( + await client.get_file_item( "https://contoso.sharepoint.com/sites/site1", "Documents", "missing_file" @@ -1831,12 +1864,12 @@ async def test_move_folder(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - input_data = MoveFolderParameters() - result = await client.move_folder_async( + input_data = model_instance(MoveFolderParameters) + result = await client.move_folder( input_data, "https://contoso.sharepoint.com/sites/site1" ) @@ -1858,13 +1891,13 @@ async def test_move_folder_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.move_folder_async( - MoveFolderParameters(), + await client.move_folder( + model_instance(MoveFolderParameters), "https://contoso.sharepoint.com/sites/site1" ) @@ -1887,7 +1920,7 @@ class TestGeneratedContractSurface: def test_day_of_week_discovery_is_generated(self): """Test day-of-week option discovery is callable.""" - assert hasattr(SharepointonlineClient, "get_day_of_week_options_async") + assert hasattr(SharepointonlineClient, "get_day_of_week_options") class TestByPathOperations: @@ -1909,11 +1942,11 @@ async def test_get_file_metadata_by_path(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_file_metadata_by_path_async( + result = await client.get_file_metadata_by_path( "https://contoso.sharepoint.com/sites/site1", "/Shared Documents/document.docx" ) @@ -1936,11 +1969,11 @@ async def test_get_file_content_by_path(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_file_content_by_path_async( + result = await client.get_file_content_by_path( "https://contoso.sharepoint.com/sites/site1", "/Shared Documents/document.docx" ) @@ -1962,11 +1995,11 @@ async def test_get_folder_metadata_by_path(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_folder_metadata_by_path_async( + result = await client.get_folder_metadata_by_path( "https://contoso.sharepoint.com/sites/site1", "/Shared Documents" ) @@ -1988,12 +2021,12 @@ async def test_get_file_metadata_by_path_error_raises_exception(self, mock_crede with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_file_metadata_by_path_async( + await client.get_file_metadata_by_path( "https://contoso.sharepoint.com/sites/site1", "/Shared Documents/missing.docx" ) diff --git a/tests/test_shifts.py b/tests/test_shifts.py index bfdc928..2d401e7 100644 --- a/tests/test_shifts.py +++ b/tests/test_shifts.py @@ -7,9 +7,9 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.shifts import ShiftsClient from azure.connectors.shifts import ( TRIGGER_OPERATIONS, - ShiftsClient, CreateShiftRequest, EditOpenShiftRequest, WebhookPushResponseResourceEntity, @@ -19,7 +19,7 @@ ) from azure.connectors.sdk.serialization import to_wire from tests.conftest import MockResponse -from tests.generated_connector_test_utils import resolve_generated_result +from tests.generated_connector_test_utils import model_instance, resolve_generated_result class TestShiftsClientInitialization: @@ -55,7 +55,7 @@ def test_init_with_custom_settings(self, mock_credential): client = ShiftsClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -139,18 +139,17 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_all_teams_async() + result = await resolve_generated_result(client.list_all_teams()) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert "/v1.0/me/joinedTeams" in path - assert result is not None - assert "value" in result + assert result == [{"id": "team-1", "displayName": "Store Team"}] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -163,12 +162,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.get_all_teams_async() + await resolve_generated_result(client.list_all_teams()) class TestGetScheduleAsync: @@ -185,11 +184,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_schedule_async(team_id="team-123") + result = await client.get_schedule(team_id="team-123") mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -209,12 +208,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.get_schedule_async(team_id="missing-team") + await client.get_schedule(team_id="missing-team") class TestListShiftsAsync: @@ -231,11 +230,11 @@ async def test_success_with_query_params(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await resolve_generated_result(client.list_shifts_async( + result = await resolve_generated_result(client.list_shifts( team_id="team-123", start_time="2026-07-01T00:00:00Z", end_time="2026-07-31T00:00:00Z", @@ -262,12 +261,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await resolve_generated_result(client.list_shifts_async(team_id="team-123")) + await resolve_generated_result(client.list_shifts(team_id="team-123")) class TestCreateShiftAsync: @@ -280,16 +279,20 @@ async def test_success(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - payload = CreateShiftRequest(scheduling_group_id="group-1", user_id="user-1") + payload = model_instance( + CreateShiftRequest, + scheduling_group_id="group-1", + user_id="user-1", + ) mock_response = MockResponse(status=201, text='{"id": "shift-1"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_shift_async(input=payload, team_id="team-123") + result = await client.create_shift(input=payload, team_id="team-123") mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -306,17 +309,21 @@ async def test_error_response_raises_exception(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - payload = CreateShiftRequest(scheduling_group_id="group-1", user_id="user-1") + payload = model_instance( + CreateShiftRequest, + scheduling_group_id="group-1", + user_id="user-1", + ) mock_response = MockResponse(status=400, text='{"error": "Bad request"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.create_shift_async(input=payload, team_id="team-123") + await client.create_shift(input=payload, team_id="team-123") class TestTriggerForShifts: @@ -346,11 +353,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.delete_time_off_async(team_id="team-1", time_off_id="toff-1") + await client.delete_time_off(team_id="team-1", time_off_id="toff-1") mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -364,16 +371,16 @@ async def test_error_response_raises_exception(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=404, text='{"error": "Time off not found"}') + mock_response = MockResponse(status=500, text='{"error": "Server error"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.delete_time_off_async(team_id="team-1", time_off_id="missing") + await client.delete_time_off(team_id="team-1", time_off_id="missing") class TestUpdateOpenShiftAsync: @@ -391,11 +398,11 @@ async def test_success_sends_body_and_returns_result(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.update_open_shift_async( + result = await client.update_open_shift( input=payload, team_id="team-1", open_shift_id="oshift-1", @@ -421,12 +428,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.update_open_shift_async( + await client.update_open_shift( input=payload, team_id="team-1", open_shift_id="oshift-1", diff --git a/tests/test_signinghub.py b/tests/test_signinghub.py index d6a884a..14480f0 100644 --- a/tests/test_signinghub.py +++ b/tests/test_signinghub.py @@ -7,8 +7,8 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.signinghub import SigninghubClient from azure.connectors.signinghub import ( - SigninghubClient, CheckBoxFieldRequest, UploadDocument, UpdateCheckBoxFieldRequest, @@ -18,6 +18,8 @@ ) from azure.connectors.sdk.serialization import to_wire from tests.conftest import MockResponse +from tests.generated_connector_test_utils import model_instance +from tests.generated_connector_test_utils import resolve_generated_result class TestSigninghubClientInitialization: @@ -53,7 +55,7 @@ def test_init_with_custom_settings(self, mock_credential): client = SigninghubClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -99,7 +101,8 @@ class TestSigninghubModelSerialization: def test_upload_document_preserves_colliding_document_ids(self): """Test that all three document ID wire names survive serialization.""" - model = UploadDocument( + model = model_instance( + UploadDocument, document_id_2=101, documentid=102, document_id=103, @@ -127,11 +130,11 @@ async def test_forwards_exact_bytes_and_media_type(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.documents_upload_stream_async( + await client.documents_upload_stream( input=document, package_id="package-1", ) @@ -153,7 +156,7 @@ async def test_context_manager(self, mock_credential): class TestContactsGetAsync: - """Tests for contacts_get_async method (GET with query parameters).""" + """Tests for list_contacts_get method (GET with query parameters).""" @pytest.mark.asyncio async def test_success_serializes_path_and_query(self, mock_credential): @@ -166,15 +169,17 @@ async def test_success_serializes_path_and_query(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.contacts_get_async( - record_per_page="10", - page_no="1", - sort_by="name", - asc="true", + result = await resolve_generated_result( + client.list_contacts_get( + record_per_page="10", + page_no="1", + sort_by="name", + asc="true", + ) ) mock_send.assert_called_once() @@ -197,12 +202,14 @@ async def test_error_response_raises_connector_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.contacts_get_async(record_per_page="10", page_no="1") + await resolve_generated_result( + client.list_contacts_get(record_per_page="10", page_no="1") + ) assert exc_info.value.status_code == 404 @@ -217,16 +224,16 @@ async def test_success_forwards_request_body(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - request = CheckBoxFieldRequest() + request = model_instance(CheckBoxFieldRequest) mock_response = MockResponse(status=200, text='{"field_id": "cb-1"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.checkbox_add_check_box_async( + result = await client.checkbox_add_check_box( input=request, package_id="pkg-1", document_id="doc-1", @@ -250,13 +257,13 @@ async def test_error_response_raises_connector_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.checkbox_add_check_box_async( - input=CheckBoxFieldRequest(), + await client.checkbox_add_check_box( + input=model_instance(CheckBoxFieldRequest), package_id="pkg-1", document_id="doc-1", ) @@ -272,16 +279,16 @@ async def test_success_forwards_request_body(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - request = UpdateCheckBoxFieldRequest() + request = model_instance(UpdateCheckBoxFieldRequest) mock_response = MockResponse(status=200, text='{"field_id": "cb-1"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.checkbox_update_check_box_async( + result = await client.checkbox_update_check_box( input=request, package_id="pkg-1", document_id="doc-1", @@ -303,13 +310,13 @@ async def test_error_response_raises_connector_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.checkbox_update_check_box_async( - input=UpdateCheckBoxFieldRequest(), + await client.checkbox_update_check_box( + input=model_instance(UpdateCheckBoxFieldRequest), package_id="pkg-1", document_id="doc-1", ) @@ -329,11 +336,11 @@ async def test_success_completes_without_error(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.attachment_delete_attachment_async( + result = await client.attachment_delete_attachment( package_id="pkg-1", document_id="doc-1", attachment_id="att-1", @@ -349,7 +356,7 @@ async def test_success_completes_without_error(self, mock_credential): @pytest.mark.asyncio async def test_not_found_raises_connector_exception(self, mock_credential): - """Test that a 404 response raises ConnectorException.""" + """Test that an uncurated DELETE preserves a not-found response.""" client = SigninghubClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -358,18 +365,18 @@ async def test_not_found_raises_connector_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.attachment_delete_attachment_async( + await client.attachment_delete_attachment( package_id="pkg-1", document_id="doc-1", attachment_id="missing", ) - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 404 @pytest.mark.asyncio async def test_server_error_raises_connector_exception(self, mock_credential): @@ -382,12 +389,12 @@ async def test_server_error_raises_connector_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.attachment_delete_attachment_async( + await client.attachment_delete_attachment( package_id="pkg-1", document_id="doc-1", attachment_id="att-1", @@ -407,7 +414,10 @@ async def test_server_error_raises_connector_exception(self, mock_credential): "document_id": "doc-1", "attachment_id": "att-1", }, - "attachment_get_attachments": {"package_id": "package-1", "document_id": "doc-1"}, + "list_attachment_get_attachments": { + "package_id": "package-1", + "document_id": "doc-1", + }, "attachment_upload_attachment": { "input": b"raw-attachment-bytes", "package_id": "package-1", @@ -423,7 +433,7 @@ async def test_server_error_raises_connector_exception(self, mock_credential): "package_id": "package-1", "document_id": "doc-1", }, - "contacts_get": {"record_per_page": "10", "page_no": "1"}, + "list_contacts_get": {"record_per_page": "10", "page_no": "1"}, "documents_delete_document": {"package_id": "package-1", "document_id": "doc-1"}, "documents_download_document_bytes": { "package_id": "package-1", @@ -507,7 +517,7 @@ async def test_server_error_raises_connector_exception(self, mock_credential): "package_finish": {"package_id": "package-1"}, "package_gatekeeper_approve": {"input": {}, "package_id": "package-1"}, "package_gatekeeper_decline": {"input": {}, "package_id": "package-1"}, - "package_get_all_packages": { + "list_package_get_all_packages": { "document_status": "PENDING", "page_no": "1", "record_per_page": "10", @@ -535,7 +545,7 @@ async def test_server_error_raises_connector_exception(self, mock_credential): "package_id": "package-1", "document_id": "doc-1", }, - "settings_get_templates": {"record_per_page": "10", "page_no": "1"}, + "list_settings_get_templates": {"record_per_page": "10", "page_no": "1"}, "signature_add_signature": { "input": {}, "package_id": "package-1", @@ -556,7 +566,10 @@ async def test_server_error_raises_connector_exception(self, mock_credential): "package_id": "package-1", "document_id": "doc-1", }, - "template_get_enterprise_templates": {"record_per_page": "10", "page_no": "1"}, + "list_template_get_enterprise_templates": { + "record_per_page": "10", + "page_no": "1", + }, "text_box_add_text_box": { "input": {}, "package_id": "package-1", @@ -580,7 +593,7 @@ async def test_server_error_raises_connector_exception(self, mock_credential): "records_per_page": "10", }, "workflow_get_workflow_reminder": {"package_id": "package-1", "order": "1"}, - "workflow_get_workflow_users": {"package_id": "package-1"}, + "list_workflow_get_workflow_users": {"package_id": "package-1"}, "workflow_mark_workflow_completed": {"package_id": "package-1"}, "workflow_permission_get_workflow_permissions": { "package_id": "package-1", @@ -601,7 +614,10 @@ async def test_server_error_raises_connector_exception(self, mock_credential): "order": "1", }, "workflow_workflow_add_group": {"input": {}, "package_id": "package-1"}, - "workflow_workflow_add_placeholder": {"input": {}, "package_id": "package-1"}, + "workflow_workflow_add_placeholder": { + "input": {}, + "package_id": "package-1", + }, "workflow_workflow_add_user": {"input": {}, "package_id": "package-1"}, "workflow_workflow_delete_user": {"package_id": "package-1", "order": "1"}, "workflow_workflow_update_placeholder": { @@ -629,8 +645,8 @@ async def test_server_error_raises_connector_exception(self, mock_credential): async def _invoke_operation(client: SigninghubClient, operation: str): """Invoke a SigningHub operation by name for shared method tests.""" - method = getattr(client, f"{operation}_async") - return await method(**OPERATION_ARGS[operation]) + method = getattr(client, f"{operation}") + return await resolve_generated_result(method(**OPERATION_ARGS[operation])) class TestSigninghubClientAllOperations: @@ -645,7 +661,7 @@ async def test_all_operations_success(self, mock_credential, operation): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: @@ -671,7 +687,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): diff --git a/tests/test_slack.py b/tests/test_slack.py index 42cbd2b..b0491dc 100644 --- a/tests/test_slack.py +++ b/tests/test_slack.py @@ -11,7 +11,8 @@ from azure.connectors.sdk import ( ConnectorException, ) -from azure.connectors.slack import PostMessageRequest, SlackClient, TRIGGER_OPERATIONS +from azure.connectors.aio.slack import SlackClient +from azure.connectors.slack import PostMessageRequest, TRIGGER_OPERATIONS from tests.conftest import MockResponse from tests.generated_connector_test_utils import resolve_generated_result @@ -49,7 +50,7 @@ def test_init_with_custom_settings(self, mock_credential): client = SlackClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -116,11 +117,11 @@ async def test_success_uses_acronym_aware_name(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.set_dnd_async(num_minutes="30") + result = await client.set_dnd(num_minutes="30") mock_send.assert_called_once_with( "GET", @@ -145,12 +146,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.set_dnd_async(num_minutes="invalid") + await client.set_dnd(num_minutes="invalid") class TestSlackContractSurface: @@ -171,7 +172,7 @@ def test_trigger_is_metadata_only(self): def test_deprecated_group_operation_is_not_generated(self): """Test the deprecated group operation is absent.""" - assert not hasattr(SlackClient, "create_group_async") + assert not hasattr(SlackClient, "create_group") class TestListChannelsAsync: @@ -191,11 +192,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await resolve_generated_result(client.list_channels_async()) + result = await resolve_generated_result(client.list_channels()) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -218,12 +219,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await resolve_generated_result(client.list_channels_async()) + await resolve_generated_result(client.list_channels()) class TestCreateChannelAsync: @@ -243,11 +244,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_channel_async(name="dev-chat", is_private="false") + result = await client.create_channel(name="dev-chat", is_private="false") mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -272,12 +273,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.create_channel_async(name="") + await client.create_channel(name="") class TestPostMessageAsync: @@ -298,11 +299,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.post_message_async(input=payload) + result = await client.post_message(input=payload) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -328,12 +329,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.post_message_async(input=payload) + await client.post_message(input=payload) @pytest.mark.asyncio @@ -353,7 +354,7 @@ async def test_channels_continuation_yields_later_channels( ) as client: with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, side_effect=[ MockResponse(status=200, text=json.dumps({ @@ -367,7 +368,7 @@ async def test_channels_continuation_yields_later_channels( ], ) as transport: channels = [ - channel async for channel in client.list_channels_async() + channel async for channel in client.list_channels() ] assert channels == first_items + later_items diff --git a/tests/test_smtp.py b/tests/test_smtp.py index e407239..c646348 100644 --- a/tests/test_smtp.py +++ b/tests/test_smtp.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.smtp import SmtpClient from azure.connectors.smtp import ( - SmtpClient, Email, Attachment, ) @@ -15,6 +15,7 @@ ) from azure.connectors.sdk.serialization import to_wire from tests.conftest import MockResponse +from tests.generated_connector_test_utils import model_instance class TestSmtpClientInitialization: @@ -50,7 +51,7 @@ def test_init_with_custom_settings(self, mock_credential): client = SmtpClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -124,11 +125,11 @@ async def test_success_basic_email(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.send_email_async(input=email_input) + await client.send_email(input=email_input) mock_send.assert_called_once() call_args = mock_send.call_args @@ -155,11 +156,11 @@ async def test_success_with_multiple_recipients(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.send_email_async(input=email_input) + await client.send_email(input=email_input) mock_send.assert_called_once() call_args = mock_send.call_args @@ -197,11 +198,11 @@ async def test_success_with_all_fields(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.send_email_async(input=email_input) + await client.send_email(input=email_input) mock_send.assert_called_once() @@ -234,11 +235,11 @@ async def test_success_with_multiple_attachments(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.send_email_async(input=email_input) + await client.send_email(input=email_input) mock_send.assert_called_once() @@ -261,11 +262,11 @@ async def test_with_high_importance(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - await client.send_email_async(input=email_input) + await client.send_email(input=email_input) @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -285,12 +286,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.send_email_async(input=email_input) + await client.send_email(input=email_input) assert exc_info.value.status_code == 400 @@ -343,14 +344,14 @@ def test_current_email_model_uses_swagger_wire_names(self): from_="sender@contoso.com", to="recipient@contoso.com", c_c="copy@contoso.com", - attachments=[Attachment(content_data="filedata")], + attachments=[model_instance(Attachment, content_data="filedata")], ) assert to_wire(email) == { "From": "sender@contoso.com", "To": "recipient@contoso.com", "CC": "copy@contoso.com", - "Attachments": [{"ContentData": "filedata"}], + "Attachments": [{"ContentData": "filedata", "ContentType": "value"}], } def test_email_with_defaults(self): @@ -397,11 +398,11 @@ async def test_empty_body_email(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - await client.send_email_async(input=email_input) + await client.send_email(input=email_input) @pytest.mark.asyncio async def test_html_body_email(self, mock_credential): @@ -421,11 +422,11 @@ async def test_html_body_email(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - await client.send_email_async(input=email_input) + await client.send_email(input=email_input) @pytest.mark.asyncio async def test_multiple_consecutive_sends(self, mock_credential): @@ -439,7 +440,7 @@ async def test_multiple_consecutive_sends(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: @@ -449,7 +450,7 @@ async def test_multiple_consecutive_sends(self, mock_credential): subject="First Email", body="First message" ) - await client.send_email_async(input=email1) + await client.send_email(input=email1) email2 = Email( from_="sender@contoso.com", @@ -457,7 +458,7 @@ async def test_multiple_consecutive_sends(self, mock_credential): subject="Second Email", body="Second message" ) - await client.send_email_async(input=email2) + await client.send_email(input=email2) assert mock_send.call_count == 2 @@ -479,11 +480,11 @@ async def test_special_characters_in_subject(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - await client.send_email_async(input=email_input) + await client.send_email(input=email_input) @pytest.mark.asyncio async def test_long_recipient_list(self, mock_credential): @@ -504,8 +505,8 @@ async def test_long_recipient_list(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - await client.send_email_async(input=email_input) + await client.send_email(input=email_input) diff --git a/tests/test_sql.py b/tests/test_sql.py index ab7e449..f3bd5a5 100644 --- a/tests/test_sql.py +++ b/tests/test_sql.py @@ -8,8 +8,8 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.sql import SqlClient from azure.connectors.sql import ( - SqlClient, DatabasesList, ExecuteProcedureInput, GetItemsResponse, @@ -30,40 +30,45 @@ ConnectorException, ) from tests.conftest import MockResponse -from tests.generated_connector_test_utils import resolve_generated_result +from tests.generated_connector_test_utils import ( + get_generated_operations, + resolve_generated_result, +) async def _invoke_operation(client: SqlClient, operation: str): """Invoke a SQL operation by name for shared method tests.""" if operation == "delete_item": - return await client.delete_item_async( + return await client.delete_item( server="srv", database="db", table="tbl", id="1" ) if operation == "execute_pass_through_native_query": - return await client.execute_pass_through_native_query_async( + return await client.execute_pass_through_native_query( input=SqlPassThroughNativeQueryBody(query="SELECT 1"), server="srv", database="db", ) if operation == "execute_procedure": - return await client.execute_procedure_async( + return await client.execute_procedure( input=ExecuteProcedureInput(), server="srv", database="db", procedure="proc", ) if operation == "get_item": - return await client.get_item_async( + return await client.get_item( server="srv", database="db", table="tbl", id="1" ) - if operation == "get_items": + if operation == "list_items": + return await resolve_generated_result( + client.list_items(server="srv", database="db", table="tbl") + ) + if operation == "list_tables": return await resolve_generated_result( - client.get_items_async(server="srv", database="db", table="tbl") + client.list_tables(server="srv", database="db") ) - if operation == "get_tables": - return await client.get_tables_async(server="srv", database="db") if operation == "patch_item": - return await client.patch_item_async( + return await client.patch_item( input=PatchItemInput(), server="srv", database="db", @@ -71,59 +76,61 @@ async def _invoke_operation(client: SqlClient, operation: str): id="1", ) if operation == "post_item": - return await client.post_item_async( + return await client.post_item( input=PostItemInput(), server="srv", database="db", table="tbl" ) - if operation == "get_servers": - return await client.get_servers_async() - if operation == "get_databases": - return await client.get_databases_async(server="srv") - if operation == "get_tables_for_delete_item": + if operation == "list_servers": + return await resolve_generated_result(client.list_servers()) + if operation == "list_databases": + return await resolve_generated_result(client.list_databases(server="srv")) + if operation == "list_tables_for_delete_item": return await resolve_generated_result( - client.get_tables_for_delete_item_async(server="srv", database="db") + client.list_tables_for_delete_item(server="srv", database="db") + ) + if operation == "list_procedures_v2": + return await resolve_generated_result( + client.list_procedures_v2(server="srv", database="db") ) - if operation == "get_procedures_v2": - return await client.get_procedures_v2_async(server="srv", database="db") if operation == "get_procedure_v2": - return await client.get_procedure_v2_async( + return await client.get_procedure_v2( server="srv", database="db", procedure="proc" ) - if operation == "get_tables_for_get_item": + if operation == "list_tables_for_get_item": return await resolve_generated_result( - client.get_tables_for_get_item_async(server="srv", database="db") + client.list_tables_for_get_item(server="srv", database="db") ) - if operation == "get_tables_for_get_on_new_items": - return await resolve_generated_result(client.get_tables_for_get_on_new_items_async( + if operation == "list_tables_for_get_on_new_items": + return await resolve_generated_result(client.list_tables_for_get_on_new_items( server="srv", database="db" )) - if operation == "get_tables_for_get_on_updated_items": - return await resolve_generated_result(client.get_tables_for_get_on_updated_items_async( + if operation == "list_tables_for_get_on_updated_items": + return await resolve_generated_result(client.list_tables_for_get_on_updated_items( server="srv", database="db" )) - if operation == "get_tables_for_patch_item": + if operation == "list_tables_for_patch_item": return await resolve_generated_result( - client.get_tables_for_patch_item_async(server="srv", database="db") + client.list_tables_for_patch_item(server="srv", database="db") ) if operation == "get_table_for_patch": - return await client.get_table_for_patch_async( + return await client.get_table_for_patch( server="srv", database="db", table="tbl" ) - if operation == "get_tables_for_post_item": + if operation == "list_tables_for_post_item": return await resolve_generated_result( - client.get_tables_for_post_item_async(server="srv", database="db") + client.list_tables_for_post_item(server="srv", database="db") ) if operation == "get_table": - return await client.get_table_async(server="srv", database="db", table="tbl") + return await client.get_table(server="srv", database="db", table="tbl") if operation == "get_pass_through_native_query_metadata": - return await client.get_pass_through_native_query_metadata_async( + return await client.get_pass_through_native_query_metadata( input=SqlPassThroughNativeQueryBody(query="SELECT 1"), server="srv", database="db", ) if operation == "get_procedure": - return await client.get_procedure_async(procedure="proc") - if operation == "get_procedures": - return await client.get_procedures_async() + return await client.get_procedure(procedure="proc") + if operation == "list_procedures": + return await resolve_generated_result(client.list_procedures()) raise ValueError(f"Unsupported operation '{operation}'.") @@ -133,25 +140,25 @@ async def _invoke_operation(client: SqlClient, operation: str): "execute_pass_through_native_query", "execute_procedure", "get_item", - "get_items", - "get_tables", + "list_items", + "list_tables", "patch_item", "post_item", - "get_servers", - "get_databases", - "get_tables_for_delete_item", - "get_procedures_v2", + "list_servers", + "list_databases", + "list_tables_for_delete_item", + "list_procedures_v2", "get_procedure_v2", - "get_tables_for_get_item", - "get_tables_for_get_on_new_items", - "get_tables_for_get_on_updated_items", - "get_tables_for_patch_item", + "list_tables_for_get_item", + "list_tables_for_get_on_new_items", + "list_tables_for_get_on_updated_items", + "list_tables_for_patch_item", "get_table_for_patch", - "get_tables_for_post_item", + "list_tables_for_post_item", "get_table", "get_pass_through_native_query_metadata", "get_procedure", - "get_procedures", + "list_procedures", ] @@ -188,7 +195,7 @@ def test_init_with_custom_settings(self, mock_credential): client = SqlClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -245,8 +252,8 @@ class TestSqlClientMethods: """Success path tests for representative SQL methods.""" @pytest.mark.asyncio - async def test_get_servers_success(self, mock_credential): - """Test get_servers_async returns parsed JSON and targets /servers.""" + async def test_list_servers_success(self, mock_credential): + """Test list_servers returns parsed items and targets /servers.""" client = SqlClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -255,18 +262,18 @@ async def test_get_servers_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_servers_async() + result = await resolve_generated_result(client.list_servers()) - assert result["value"][0]["name"] == "srv1" + assert result[0]["name"] == "srv1" assert mock_send.call_args[0][1].endswith("/servers") @pytest.mark.asyncio - async def test_get_databases_sends_server_query(self, mock_credential): - """Test get_databases_async appends the server query parameter.""" + async def test_list_databases_sends_server_query(self, mock_credential): + """Test list_databases appends the server query parameter.""" client = SqlClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -275,11 +282,11 @@ async def test_get_databases_sends_server_query(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.get_databases_async(server="srv1") + await resolve_generated_result(client.list_databases(server="srv1")) request_url = mock_send.call_args[0][1] assert "/databases" in request_url @@ -296,11 +303,11 @@ async def test_get_items_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await resolve_generated_result(client.get_items_async( + result = await resolve_generated_result(client.list_items( server="srv", database="db", table="tbl" )) @@ -318,11 +325,11 @@ async def test_get_items_appends_odata_query_params(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await resolve_generated_result(client.get_items_async( + await resolve_generated_result(client.list_items( server="srv", database="db", table="tbl", @@ -345,11 +352,11 @@ async def test_post_item_sends_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.post_item_async( + await client.post_item( input=PostItemInput(additional_properties={"Name": "Contoso"}), server="srv", database="db", @@ -372,11 +379,11 @@ async def test_patch_item_uses_patch_verb(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.patch_item_async( + await client.patch_item( input=body, server="srv", database="db", @@ -399,11 +406,11 @@ async def test_delete_item_uses_delete_verb(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.delete_item_async( + result = await client.delete_item( server="srv", database="db", table="tbl", id="1" ) @@ -422,11 +429,11 @@ async def test_execute_procedure_sends_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.execute_procedure_async( + await client.execute_procedure( input=ExecuteProcedureInput(), server="srv", database="db", @@ -447,11 +454,11 @@ async def test_execute_pass_through_native_query_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.execute_pass_through_native_query_async( + await client.execute_pass_through_native_query( input=SqlPassThroughNativeQueryBody(query="SELECT 1"), server="srv", database="db", @@ -461,8 +468,8 @@ async def test_execute_pass_through_native_query_success(self, mock_credential): assert "/v2/datasets/srv,db/query/sql" in mock_send.call_args[0][1] @pytest.mark.asyncio - async def test_get_procedures_v2_success(self, mock_credential): - """Test get_procedures_v2_async targets the v2 procedures endpoint.""" + async def test_list_procedures_v2_success(self, mock_credential): + """Test list_procedures_v2 targets the v2 procedures endpoint.""" client = SqlClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -471,11 +478,13 @@ async def test_get_procedures_v2_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.get_procedures_v2_async(server="srv", database="db") + await resolve_generated_result( + client.list_procedures_v2(server="srv", database="db") + ) assert "/v2/datasets/srv,db/procedures" in mock_send.call_args[0][1] @@ -490,11 +499,11 @@ async def test_get_table_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.get_table_async(server="srv", database="db", table="tbl") + await client.get_table(server="srv", database="db", table="tbl") assert "/v2/$metadata.json/datasets/srv,db/tables/tbl" in mock_send.call_args[0][1] @@ -508,7 +517,7 @@ async def test_all_operations_success(self, mock_credential, operation): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: @@ -537,7 +546,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -615,53 +624,53 @@ def test_trigger_routes_not_client_methods(self): def test_callable_method_signatures(self): """Test the client exposes exactly the generated callable methods.""" expected_signatures = { - "delete_item_async": ("self", "server", "database", "table", "id"), - "execute_pass_through_native_query_async": ( + "delete_item": ("self", "server", "database", "table", "id"), + "execute_pass_through_native_query": ( "self", "input", "server", "database" ), - "execute_procedure_async": ( + "execute_procedure": ( "self", "input", "server", "database", "procedure" ), - "get_databases_async": ("self", "server"), - "get_item_async": ("self", "server", "database", "table", "id"), - "get_items_async": ( + "list_databases": ("self", "server"), + "get_item": ("self", "server", "database", "table", "id"), + "list_items": ( "self", "server", "database", "table", "apply", "filter", "orderby", "skip", "top", "select", "count", "extract_sensitivity_label", "purview_account_name" ), - "get_pass_through_native_query_metadata_async": ( + "get_pass_through_native_query_metadata": ( "self", "input", "server", "database" ), - "get_procedure_async": ("self", "procedure"), - "get_procedure_v2_async": ( + "get_procedure": ("self", "procedure"), + "get_procedure_v2": ( "self", "server", "database", "procedure" ), - "get_procedures_async": ("self",), - "get_procedures_v2_async": ("self", "server", "database"), - "get_servers_async": ("self",), - "get_table_async": ( + "list_procedures": ("self",), + "list_procedures_v2": ("self", "server", "database"), + "list_servers": ("self",), + "get_table": ( "self", "server", "database", "table", "extract_sensitivity_label", "purview_account_name" ), - "get_table_for_patch_async": ("self", "server", "database", "table"), - "get_tables_async": ( + "get_table_for_patch": ("self", "server", "database", "table"), + "list_tables": ( "self", "server", "database", "extract_sensitivity_label", "purview_account_name" ), - "get_tables_for_delete_item_async": ("self", "server", "database"), - "get_tables_for_get_item_async": ("self", "server", "database"), - "get_tables_for_get_on_new_items_async": ( + "list_tables_for_delete_item": ("self", "server", "database"), + "list_tables_for_get_item": ("self", "server", "database"), + "list_tables_for_get_on_new_items": ( "self", "server", "database" ), - "get_tables_for_get_on_updated_items_async": ( + "list_tables_for_get_on_updated_items": ( "self", "server", "database" ), - "get_tables_for_patch_item_async": ("self", "server", "database"), - "get_tables_for_post_item_async": ("self", "server", "database"), - "patch_item_async": ( + "list_tables_for_patch_item": ("self", "server", "database"), + "list_tables_for_post_item": ("self", "server", "database"), + "patch_item": ( "self", "input", "server", "database", "table", "id" ), - "post_item_async": ("self", "input", "server", "database", "table"), + "post_item": ("self", "input", "server", "database", "table"), } request_control_parameters = ( "timeout", @@ -673,13 +682,10 @@ def test_callable_method_signatures(self): name: parameters + request_control_parameters for name, parameters in expected_signatures.items() } + assert get_generated_operations(SqlClient) == set(expected_signatures) actual_signatures = { - name: tuple(inspect.signature(method).parameters) - for name, method in vars(SqlClient).items() - if ( - inspect.iscoroutinefunction(method) - or inspect.isasyncgenfunction(method) - ) + name: tuple(inspect.signature(getattr(SqlClient, name)).parameters) + for name in expected_signatures } assert actual_signatures == expected_signatures diff --git a/tests/test_starmind.py b/tests/test_starmind.py index 9c8a9c2..c6403b0 100644 --- a/tests/test_starmind.py +++ b/tests/test_starmind.py @@ -9,10 +9,10 @@ from azure.core.credentials import AzureKeyCredential import azure.connectors.starmind as starmind_module from azure.connectors.sdk import ConnectorException +from azure.connectors.aio.starmind import StarmindClient from azure.connectors.starmind import ( FindExpertsInput, PostQuestionDraftInput, - StarmindClient, ) from tests.conftest import MockResponse from tests.generated_connector_test_utils import ( @@ -93,7 +93,7 @@ async def test_generated_operation_success_contract( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"ok": true}'), ) as mock_send: @@ -115,11 +115,11 @@ async def test_find_experts_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"experts": []}'), ) as mock_send: - result = await client.find_experts_async( + result = await client.find_experts( input=FindExpertsInput(text_query="distributed systems"), ) @@ -138,11 +138,11 @@ async def test_post_question_draft_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=201, text='{"id": 42}'), ) as mock_send: - await client.post_question_draft_async( + await client.post_question_draft( input=PostQuestionDraftInput( title="How does this work?", description="Looking for an expert explanation.", @@ -167,7 +167,7 @@ async def test_non_success_response_raises_exception( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=400, text="bad request"), ): diff --git a/tests/test_starrezrestv1.py b/tests/test_starrezrestv1.py index 81407e9..5281004 100644 --- a/tests/test_starrezrestv1.py +++ b/tests/test_starrezrestv1.py @@ -8,39 +8,44 @@ import azure.connectors.starrezrestv1 as starrezrestv1_module from azure.connectors.sdk.serialization import to_wire -from azure.connectors.starrezrestv1 import SelectBookingInput, Starrezrestv1Client +from azure.connectors.aio.starrezrestv1 import Starrezrestv1Client +from azure.connectors.starrezrestv1 import SelectBookingInput from tests.conftest import MockResponse -from tests.generated_connector_test_utils import GeneratedConnectorContractTests +from tests.generated_connector_test_utils import ( + GeneratedConnectorContractTests, + model_instance, + resolve_generated_result, +) OPERATION_CONTRACTS = { - "select_entry": ("POST", True), + "list_select_entry": ("POST", True), "create_entry": ("POST", True), "update_entry": ("POST", True), "delete": ("POST", False), - "select_entry_custom_field": ("POST", True), + "list_select_entry_custom_field": ("POST", True), "update_entry_custom_field": ("POST", True), - "select_term": ("POST", True), - "select_entry_address": ("POST", True), + "list_select_term": ("POST", True), + "list_select_entry_address": ("POST", True), "update_entry_address": ("POST", True), - "select_entry_application": ("POST", True), + "list_select_entry_application": ("POST", True), "create_entry_application": ("POST", True), "update_entry_application": ("POST", True), - "select_term_session": ("POST", True), - "select_entry_detail": ("POST", True), + "list_select_term_session": ("POST", True), + "list_select_entry_detail": ("POST", True), "update_entry_detail": ("POST", True), - "select_entry_enrollment": ("POST", True), + "list_select_entry_enrollment": ("POST", True), "create_entry_enrollment": ("POST", True), "update_entry_enrollment": ("POST", True), - "select_booking": ("POST", True), + "list_select_booking": ("POST", True), "create_booking": ("POST", True), "update_booking": ("POST", True), - "select_room_space": ("POST", True), + "list_select_room_space": ("POST", True), "create_room_space": ("POST", True), - "select_room_location": ("POST", True), - "select_transaction": ("POST", True), + "list_select_room_location": ("POST", True), + "list_select_transaction": ("POST", True), "create_transaction": ("POST", True), - "select_room_space_maintenance": ("POST", True), + "list_select_room_space_maintenance": ("POST", True), "create_room_space_maintenance": ("POST", True), "update_room_space_maintenance": ("POST", True), } @@ -64,18 +69,21 @@ async def test_select_booking_sends_filter_and_deserializes_response( "https://example.azure.com/connections/test", credential=mock_credential, ) - request = SelectBookingInput( + request = model_instance( + SelectBookingInput, return_empty_array_on_no_result=True, page_size=10, ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, - return_value=MockResponse(status=200, text='{"bookings": []}'), + return_value=MockResponse(status=200, text='[{"BookingID": 123}]'), ) as mock_send: - result = await client.select_booking_async(input=request) + result = await resolve_generated_result( + client.list_select_booking(input=request) + ) mock_send.assert_awaited_once_with( "POST", @@ -89,5 +97,6 @@ async def test_select_booking_sends_filter_and_deserializes_response( assert to_wire(request) == { "_returnEmptyArrayOnNoResult": True, "_pageSize": 10, + "_pageIndex": 1, } - assert result == {"bookings": []} + assert result == [{"BookingID": 123}] diff --git a/tests/test_tallyfy.py b/tests/test_tallyfy.py index aa6215c..bb2d8bb 100644 --- a/tests/test_tallyfy.py +++ b/tests/test_tallyfy.py @@ -9,11 +9,13 @@ from azure.core.credentials import AzureKeyCredential import azure.connectors.tallyfy as tallyfy_module from azure.connectors.sdk import ConnectorException -from azure.connectors.tallyfy import CreateRunInput, CreateTaskInput, TallyfyClient +from azure.connectors.aio.tallyfy import TallyfyClient +from azure.connectors.tallyfy import CreateRunInput, CreateTaskInput from tests.conftest import MockResponse from tests.generated_connector_test_utils import ( get_generated_operations, invoke_generated_operation, + model_instance, ) @@ -46,7 +48,7 @@ "/processes/micro-functions/organizations/value/tasks/value/edit-deadline", True, ), - "get_organization_users": ("GET", "/organizations/value/users", False), + "list_organization_users": ("GET", "/organizations/value/users", False), "get_user_organizations": ("GET", "/me/organizations", False), "get_user_tasks": ( "GET", @@ -140,9 +142,16 @@ async def test_generated_operation_success_contract( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, - return_value=MockResponse(status=200, text='{"ok": true}'), + return_value=MockResponse( + status=200, + text=( + '{"data": [{"ok": true}]}' + if operation == "list_organization_users" + else '{"ok": true}' + ), + ), ) as mock_send: result = await invoke_generated_operation(client, operation, tallyfy_module) @@ -150,7 +159,12 @@ async def test_generated_operation_success_contract( assert method == expected_method assert url.endswith(expected_url_suffix) assert (mock_send.call_args.kwargs["body"] is not None) is expects_body - assert result == {"ok": True} + expected_result = ( + [{"ok": True}] + if operation == "list_organization_users" + else {"ok": True} + ) + assert result == expected_result @pytest.mark.asyncio async def test_create_run_success(self, mock_credential): @@ -162,11 +176,11 @@ async def test_create_run_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=201, text='{"id": "run-1"}'), ) as mock_send: - result = await client.create_run_async( + result = await client.create_run( input=CreateRunInput(name="Quarterly review", checklist_id="checklist-1"), org="organization/one", ) @@ -187,12 +201,16 @@ async def test_create_task_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=201, text='{"id": "task-1"}'), ) as mock_send: - await client.create_task_async( - input=CreateTaskInput(name="Review document", description="Check details"), + await client.create_task( + input=model_instance( + CreateTaskInput, + name="Review document", + description="Check details", + ), org="organization", ) @@ -216,7 +234,7 @@ async def test_non_success_response_raises_exception( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=400, text="bad request"), ): diff --git a/tests/test_teams.py b/tests/test_teams.py index cbb742d..df48a8f 100644 --- a/tests/test_teams.py +++ b/tests/test_teams.py @@ -3,9 +3,9 @@ import pytest from unittest.mock import AsyncMock, patch +from azure.connectors.aio.teams import TeamsClient from azure.connectors.teams import ( CallEventWebhookResponseSchema, - TeamsClient, NewMeeting, CreateChannelInput, CreateTagInput, @@ -24,6 +24,7 @@ from azure.connectors.sdk import ConnectorException from azure.connectors.sdk.serialization import to_wire from tests.conftest import MockResponse +from tests.generated_connector_test_utils import model_instance, resolve_generated_result class TestTeamsClientInitialization: @@ -61,7 +62,7 @@ def test_init_with_custom_settings(self, mock_credential): client = TeamsClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) @@ -154,12 +155,12 @@ async def test_create_teams_meeting_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - input_data = NewMeeting() - result = await client.create_teams_meeting_async(input_data, "calendar123") + input_data = model_instance(NewMeeting) + result = await client.create_teams_meeting(input_data, "calendar123") call_args = mock_send.call_args assert call_args[0][0] == "POST" @@ -178,13 +179,13 @@ async def test_create_teams_meeting_error(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - input_data = NewMeeting() + input_data = model_instance(NewMeeting) with pytest.raises(ConnectorException) as exc_info: - await client.create_teams_meeting_async(input_data, "calendar123") + await client.create_teams_meeting(input_data, "calendar123") assert exc_info.value.status_code == 400 @@ -207,14 +208,13 @@ async def test_get_all_teams_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_all_teams_async() + result = await resolve_generated_result(client.list_all_teams()) - assert "value" in result - assert len(result["value"]) == 1 + assert len(result) == 1 @pytest.mark.asyncio async def test_get_all_teams_empty_response(self, mock_credential): @@ -228,13 +228,13 @@ async def test_get_all_teams_empty_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_all_teams_async() + result = await resolve_generated_result(client.list_all_teams()) - assert result is None + assert result == [] @pytest.mark.asyncio async def test_get_all_associated_teams_success(self, mock_credential): @@ -251,13 +251,15 @@ async def test_get_all_associated_teams_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_all_associated_teams_async() + result = await resolve_generated_result( + client.list_all_associated_teams() + ) - assert "value" in result + assert result[0]["teamId"] == "team1" @pytest.mark.asyncio async def test_get_all_teams_error_response(self, mock_credential): @@ -274,12 +276,14 @@ async def test_get_all_teams_error_response(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_all_associated_teams_async() + await resolve_generated_result( + client.list_all_associated_teams() + ) assert exc_info.value.status_code == 401 @@ -302,11 +306,11 @@ async def test_at_mention_user_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.at_mention_user_async("user123") + result = await client.at_mention_user("user123") call_args = mock_send.call_args assert call_args[0][0] == "GET" @@ -325,12 +329,12 @@ async def test_at_mention_user_error(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.at_mention_user_async("nonexistent") + await client.at_mention_user("nonexistent") assert exc_info.value.status_code == 404 @@ -353,12 +357,12 @@ async def test_create_chat_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - input_data = NewChat() - result = await client.create_chat_async(input_data) + input_data = model_instance(NewChat) + result = await client.create_chat(input_data) call_args = mock_send.call_args assert call_args[0][0] == "POST" @@ -377,12 +381,12 @@ async def test_create_chat_error(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_chat_async(NewChat()) + await client.create_chat(model_instance(NewChat)) assert exc_info.value.status_code == 400 @@ -405,7 +409,7 @@ async def test_create_a_team_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: @@ -414,7 +418,7 @@ async def test_create_a_team_success(self, mock_credential): description="A new team", visibility="Private" ) - result = await client.create_a_team_async(input_data) + result = await client.create_a_team(input_data) call_args = mock_send.call_args assert call_args[0][0] == "POST" @@ -433,12 +437,12 @@ async def test_create_a_team_error(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.create_a_team_async(CreateATeamInput()) + await client.create_a_team(model_instance(CreateATeamInput)) assert exc_info.value.status_code == 403 @@ -461,8 +465,8 @@ class TestGeneratedContractSurface: def test_channel_and_chat_operations_are_generated(self): """Test current channel and chat operations are callable.""" - assert hasattr(TeamsClient, "update_channel_properties_async") - assert hasattr(TeamsClient, "remove_member_from_chat_async") + assert hasattr(TeamsClient, "update_channel_properties") + assert hasattr(TeamsClient, "remove_member_from_chat") class TestHttpRequestOperations: @@ -483,12 +487,12 @@ async def test_http_request_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = b'{"method":"GET","uri":"/teams"}' - result = await client.http_request_async(input_data) + result = await client.http_request(input_data) call_args = mock_send.call_args assert call_args[0][0] == "POST" @@ -509,12 +513,12 @@ async def test_http_request_error(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.http_request_async(b'{"method":"GET","uri":"/teams"}') + await client.http_request(b'{"method":"GET","uri":"/teams"}') assert exc_info.value.status_code == 500 @@ -534,12 +538,12 @@ async def test_subscribe_user_message_with_options_success(self, mock_credential with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = DynamicUserMessageWithOptionsSubscriptionRequest() - await client.subscribe_user_message_with_options_async(input_data) + await client.subscribe_user_message_with_options(input_data) call_args = mock_send.call_args assert call_args[0][0] == "POST" @@ -557,12 +561,12 @@ async def test_subscribe_user_message_with_options_error(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await client.subscribe_user_message_with_options_async( + await client.subscribe_user_message_with_options( DynamicUserMessageWithOptionsSubscriptionRequest() ) @@ -572,7 +576,7 @@ class TestDataClasses: def test_new_meeting_creation(self): """Test NewMeeting data class creation.""" - meeting = NewMeeting() + meeting = model_instance(NewMeeting) assert meeting is not None def test_create_channel_input_creation(self): @@ -586,7 +590,7 @@ def test_create_channel_input_creation(self): def test_create_tag_input_creation(self): """Test CreateTagInput data class creation.""" - tag = CreateTagInput(display_name="Test Tag") + tag = model_instance(CreateTagInput, display_name="Test Tag") assert tag.display_name == "Test Tag" def test_add_member_to_tag_input_creation(self): @@ -667,12 +671,12 @@ async def test_multiple_consecutive_calls(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result1 = await client.get_all_teams_async() - result2 = await client.get_all_teams_async() + result1 = await resolve_generated_result(client.list_all_teams()) + result2 = await resolve_generated_result(client.list_all_teams()) assert result1 is not None assert result2 is not None @@ -689,12 +693,12 @@ async def test_json_parse_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(Exception): - await client.get_all_teams_async() + await resolve_generated_result(client.list_all_teams()) @pytest.mark.asyncio async def test_url_construction_with_multiple_trailing_slashes(self, mock_credential): @@ -729,12 +733,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_all_teams_async() + await resolve_generated_result(client.list_all_teams()) assert exc_info.value.status_code == 500 @@ -750,11 +754,11 @@ async def test_404_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_all_teams_async() + await resolve_generated_result(client.list_all_teams()) assert exc_info.value.status_code == 404 diff --git a/tests/test_textrequest.py b/tests/test_textrequest.py index 1d60ad6..0f43da5 100644 --- a/tests/test_textrequest.py +++ b/tests/test_textrequest.py @@ -8,6 +8,7 @@ from azure.core.credentials import AzureKeyCredential import azure.connectors.textrequest as textrequest_module +from azure.connectors.aio.textrequest import TextrequestClient from azure.connectors.textrequest import ( CreateContactInput, CreateDashboardInput, @@ -16,7 +17,6 @@ GetContactByPhoneNumberResponse, SendMessageByPhoneNumberInput, SendMessageByPhoneNumberResponse, - TextrequestClient, UpdateDashboardsNameInput, UpdateGroupInput, TRIGGER_OPERATIONS, @@ -28,6 +28,7 @@ from tests.generated_connector_test_utils import ( get_generated_operations, invoke_generated_operation, + resolve_generated_result, ) @@ -55,33 +56,33 @@ "/dashboards/1/contacts/value", False, ), - "get_contacts": ( + "list_contacts": ( "GET", "/dashboards/1/contacts?page=1&page_size=1", False, ), - "get_conversations": ("GET", "/dashboards/1/conversations", False), - "get_custom_fields": ("GET", "/dashboards/1/fields", False), + "list_conversations": ("GET", "/dashboards/1/conversations", False), + "list_custom_fields": ("GET", "/dashboards/1/fields", False), "get_dashboard": ("GET", "/dashboards/1", False), - "get_dashboards": ("GET", "/dashboards", False), + "list_dashboards": ("GET", "/dashboards", False), "get_group_by_id": ("GET", "/dashboards/1/groups/1", False), - "get_groups": ( + "list_groups": ( "GET", "/dashboards/1/groups?page=1&page_size=1", False, ), - "get_messages_by_contact_phone": ( + "list_messages_by_contact_phone": ( "GET", "/dashboards/1/contacts/value/messages?page=1&page_size=1", False, ), "get_payment": ("GET", "/dashboards/1/payments/1", False), - "get_payments": ( + "list_payments": ( "GET", "/dashboards/1/payments?page=1&page_size=1", False, ), - "get_tags": ( + "list_tags": ( "GET", "/dashboards/1/tags?page=1&page_size=1", False, @@ -110,6 +111,15 @@ "update_group": ("PUT", "/dashboards/1/groups/1", True), } ALL_OPERATIONS = list(SUCCESS_CONTRACTS) +PAGED_OPERATIONS = { + "list_contacts", + "list_conversations", + "list_dashboards", + "list_groups", + "list_messages_by_contact_phone", + "list_payments", + "list_tags", +} class TestTextrequestClientInitialization: @@ -145,7 +155,7 @@ def test_init_with_custom_settings(self, mock_credential): client = TextrequestClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -232,9 +242,21 @@ async def test_generated_operation_success_contract( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, - return_value=MockResponse(status=200, text='{"ok": true}'), + return_value=MockResponse( + status=200, + text=( + '[{"ok": true}]' + if operation in { + "bulk_update_contacts", + "list_custom_fields", + } + else '{"items": [{"ok": true}]}' + if operation in PAGED_OPERATIONS + else '{"ok": true}' + ), + ), ) as mock_send: result = await invoke_generated_operation( client, @@ -246,7 +268,15 @@ async def test_generated_operation_success_contract( assert method == expected_method assert url.endswith(expected_url_suffix) assert (mock_send.call_args.kwargs["body"] is not None) is expects_body - assert result == {"ok": True} + expected_result = ( + [{"ok": True}] + if operation in { + "bulk_update_contacts", + "list_custom_fields", + } | PAGED_OPERATIONS + else {"ok": True} + ) + assert result == expected_result @pytest.mark.asyncio async def test_get_messages_by_contact_phone_success(self, mock_credential): @@ -255,11 +285,16 @@ async def test_get_messages_by_contact_phone_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"items": []}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_messages_by_contact_phone_async( - dashboard_id="7", phone_number="+15551112222", page="1", page_size="20" + result = await resolve_generated_result( + client.list_messages_by_contact_phone( + dashboard_id="7", + phone_number="+15551112222", + page="1", + page_size="20", + ) ) url = mock_send.call_args[0][1] @@ -267,7 +302,7 @@ async def test_get_messages_by_contact_phone_success(self, mock_credential): assert "/dashboards/7/contacts/%2B15551112222/messages" in url assert "page=1" in url assert "page_size=20" in url - assert result == {"items": []} + assert result == [] @pytest.mark.asyncio async def test_send_message_by_phone_number_success(self, mock_credential): @@ -277,10 +312,10 @@ async def test_send_message_by_phone_number_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"message_id": "m1"}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.send_message_by_phone_number_async( + result = await client.send_message_by_phone_number( input=payload, dashboard_id="7", phone_number="+15551112222" ) @@ -296,10 +331,10 @@ async def test_archive_conversation_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"ok": true}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.archive_conversation_async( + result = await client.archive_conversation( dashboard_id="7", phone_number="+15551112222" ) @@ -314,10 +349,10 @@ async def test_unarchive_conversation_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"ok": true}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.unarchive_conversation_async( + result = await client.unarchive_conversation( dashboard_id="7", phone_number="+15551112222" ) @@ -332,10 +367,10 @@ async def test_get_contact_by_phone_number_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"phone_number": "+15551112222"}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_contact_by_phone_number_async( + result = await client.get_contact_by_phone_number( dashboard_id="7", phone_number="+15551112222" ) @@ -350,10 +385,10 @@ async def test_delete_contact_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"ok": true}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.delete_contact_async( + result = await client.delete_contact( dashboard_id="7", phone_number="+15551112222" ) @@ -369,10 +404,10 @@ async def test_create_contact_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"phone_number": "+15551112222"}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_contact_async( + result = await client.create_contact( input=payload, dashboard_id="7", phone_number="+15551112222" ) @@ -388,11 +423,16 @@ async def test_get_contacts_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"items": []}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_contacts_async( - dashboard_id="7", page="1", page_size="20", is_resolved="true" + result = await resolve_generated_result( + client.list_contacts( + dashboard_id="7", + page="1", + page_size="20", + is_resolved="true", + ) ) url = mock_send.call_args[0][1] @@ -400,7 +440,7 @@ async def test_get_contacts_success(self, mock_credential): assert "/dashboards/7/contacts" in url assert "is_resolved=true" in url assert "page=1" in url - assert result == {"items": []} + assert result == [] @pytest.mark.asyncio async def test_get_group_by_id_success(self, mock_credential): @@ -409,10 +449,10 @@ async def test_get_group_by_id_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"id": 3}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_group_by_id_async(dashboard_id="7", group_id="3") + result = await client.get_group_by_id(dashboard_id="7", group_id="3") assert mock_send.call_args[0][0] == "GET" assert "/dashboards/7/groups/3" in mock_send.call_args[0][1] @@ -426,10 +466,10 @@ async def test_update_group_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"id": 3}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.update_group_async( + result = await client.update_group( input=payload, dashboard_id="7", group_id="3" ) @@ -446,10 +486,10 @@ async def test_create_group_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"id": 3}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_group_async(input=payload, dashboard_id="7") + result = await client.create_group(input=payload, dashboard_id="7") assert mock_send.call_args[0][0] == "POST" assert "/dashboards/7/groups" in mock_send.call_args[0][1] @@ -457,20 +497,25 @@ async def test_create_group_success(self, mock_credential): assert result == {"id": 3} @pytest.mark.asyncio - async def test_get_custom_fields_success(self, mock_credential): - """Test get_custom_fields issues a GET to the fields route.""" + async def test_list_custom_fields_success(self, mock_credential): + """Test list_custom_fields issues a GET to the fields route.""" client = self._make_client(mock_credential) - mock_response = MockResponse(status=200, text='[]') + mock_response = MockResponse(status=200, text='[{"id": "field-1"}]') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_custom_fields_async(dashboard_id="7") + result = await invoke_generated_operation( + client, + "list_custom_fields", + textrequest_module, + request_controls={"dashboard_id": "7"}, + ) assert mock_send.call_args[0][0] == "GET" assert "/dashboards/7/fields" in mock_send.call_args[0][1] - assert result == [] + assert result == [{"id": "field-1"}] @pytest.mark.asyncio async def test_mark_payment_paid_success(self, mock_credential): @@ -479,10 +524,10 @@ async def test_mark_payment_paid_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"ok": true}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.mark_payment_paid_async(dashboard_id="7", payment_id="9") + result = await client.mark_payment_paid(dashboard_id="7", payment_id="9") assert mock_send.call_args[0][0] == "POST" assert "/dashboards/7/payments/9/mark_as_paid" in mock_send.call_args[0][1] @@ -496,10 +541,10 @@ async def test_create_payment_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"id": 9}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_payment_async(input=payload, dashboard_id="7") + result = await client.create_payment(input=payload, dashboard_id="7") assert mock_send.call_args[0][0] == "POST" assert "/dashboards/7/payments" in mock_send.call_args[0][1] @@ -513,16 +558,18 @@ async def test_get_dashboards_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"items": []}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_dashboards_async(page="1", page_size="20") + result = await resolve_generated_result( + client.list_dashboards(page="1", page_size="20") + ) url = mock_send.call_args[0][1] assert mock_send.call_args[0][0] == "GET" assert "/dashboards" in url assert "page=1" in url - assert result == {"items": []} + assert result == [] @pytest.mark.asyncio async def test_create_dashboard_success(self, mock_credential): @@ -532,10 +579,10 @@ async def test_create_dashboard_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"id": 1}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_dashboard_async(input=payload) + result = await client.create_dashboard(input=payload) assert mock_send.call_args[0][0] == "POST" assert mock_send.call_args[0][1].endswith("/dashboards") @@ -550,10 +597,10 @@ async def test_update_dashboards_name_success(self, mock_credential): mock_response = MockResponse(status=200, text='{"id": 7}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.update_dashboards_name_async(input=payload, dashboard_id="7") + result = await client.update_dashboards_name(input=payload, dashboard_id="7") assert mock_send.call_args[0][0] == "PUT" assert mock_send.call_args[0][1].endswith("/dashboards/7") @@ -567,12 +614,12 @@ async def test_empty_response_body_returns_none(self, mock_credential): mock_response = MockResponse(status=200, text="") with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.get_dashboards_async() + result = await resolve_generated_result(client.list_dashboards()) - assert result is None + assert result == [] class TestTextrequestClientErrorHandling: @@ -582,33 +629,33 @@ class TestTextrequestClientErrorHandling: @pytest.mark.parametrize( "operation", [ - "get_messages_by_contact_phone", + "list_messages_by_contact_phone", "send_message_by_phone_number", "archive_conversation", "unarchive_conversation", "get_contact_by_phone_number", "delete_contact", "create_contact", - "get_contacts", + "list_contacts", "bulk_update_contacts", "get_group_by_id", "delete_group", "update_group", - "get_groups", + "list_groups", "create_group", - "get_tags", - "get_custom_fields", + "list_tags", + "list_custom_fields", "get_payment", "mark_payment_paid", "send_payment_reminder", "cancel_payment", - "get_payments", + "list_payments", "create_payment", "get_dashboard", "delete_dashboard", "update_dashboards_name", - "get_conversations", - "get_dashboards", + "list_conversations", + "list_dashboards", "create_dashboard", ], ) @@ -621,80 +668,15 @@ async def test_error_response_raises_exception(self, mock_credential, operation) mock_response = MockResponse(status=500, text='{"error":"server failure"}') with patch.object( - client._http_client, "send_async", new_callable=AsyncMock, + client._http_client, "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - if operation == "get_messages_by_contact_phone": - await client.get_messages_by_contact_phone_async( - dashboard_id="7", phone_number="p", page="1", page_size="20" - ) - elif operation == "send_message_by_phone_number": - await client.send_message_by_phone_number_async( - input=SendMessageByPhoneNumberInput(), dashboard_id="7", phone_number="p" - ) - elif operation == "archive_conversation": - await client.archive_conversation_async(dashboard_id="7", phone_number="p") - elif operation == "unarchive_conversation": - await client.unarchive_conversation_async(dashboard_id="7", phone_number="p") - elif operation == "get_contact_by_phone_number": - await client.get_contact_by_phone_number_async( - dashboard_id="7", phone_number="p" - ) - elif operation == "delete_contact": - await client.delete_contact_async(dashboard_id="7", phone_number="p") - elif operation == "create_contact": - await client.create_contact_async( - input=CreateContactInput(), dashboard_id="7", phone_number="p" - ) - elif operation == "get_contacts": - await client.get_contacts_async( - dashboard_id="7", page="1", page_size="20" - ) - elif operation == "bulk_update_contacts": - await client.bulk_update_contacts_async(input=[], dashboard_id="7") - elif operation == "get_group_by_id": - await client.get_group_by_id_async(dashboard_id="7", group_id="3") - elif operation == "delete_group": - await client.delete_group_async(dashboard_id="7", group_id="3") - elif operation == "update_group": - await client.update_group_async( - input=UpdateGroupInput(), dashboard_id="7", group_id="3" - ) - elif operation == "get_groups": - await client.get_groups_async(dashboard_id="7", page="1", page_size="20") - elif operation == "create_group": - await client.create_group_async(input=CreateGroupInput(), dashboard_id="7") - elif operation == "get_tags": - await client.get_tags_async(dashboard_id="7", page="1", page_size="20") - elif operation == "get_custom_fields": - await client.get_custom_fields_async(dashboard_id="7") - elif operation == "get_payment": - await client.get_payment_async(dashboard_id="7", payment_id="9") - elif operation == "mark_payment_paid": - await client.mark_payment_paid_async(dashboard_id="7", payment_id="9") - elif operation == "send_payment_reminder": - await client.send_payment_reminder_async(dashboard_id="7", payment_id="9") - elif operation == "cancel_payment": - await client.cancel_payment_async(dashboard_id="7", payment_id="9") - elif operation == "get_payments": - await client.get_payments_async(dashboard_id="7", page="1", page_size="20") - elif operation == "create_payment": - await client.create_payment_async(input=CreatePaymentInput(), dashboard_id="7") - elif operation == "get_dashboard": - await client.get_dashboard_async(dashboard_id="7") - elif operation == "delete_dashboard": - await client.delete_dashboard_async(dashboard_id="7") - elif operation == "update_dashboards_name": - await client.update_dashboards_name_async( - input=UpdateDashboardsNameInput(), dashboard_id="7" - ) - elif operation == "get_conversations": - await client.get_conversations_async(dashboard_id="7") - elif operation == "get_dashboards": - await client.get_dashboards_async() - else: - await client.create_dashboard_async(input=CreateDashboardInput()) + await invoke_generated_operation( + client, + operation, + textrequest_module, + ) assert exc_info.value.status_code == 500 diff --git a/tests/test_ticketmaster.py b/tests/test_ticketmaster.py index 86acf6a..5d293ff 100644 --- a/tests/test_ticketmaster.py +++ b/tests/test_ticketmaster.py @@ -7,7 +7,7 @@ import pytest import azure.connectors.ticketmaster as ticketmaster_module -from azure.connectors.ticketmaster import TicketmasterClient +from azure.connectors.aio.ticketmaster import TicketmasterClient from tests.conftest import MockResponse from tests.generated_connector_test_utils import GeneratedConnectorContractTests @@ -50,11 +50,11 @@ async def test_attractions_get_serializes_query_and_response( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"items": []}'), ) as mock_send: - result = await client.attractions_get_async( + result = await client.attractions_get( keyword="rock & roll", classification_name=["music", "comedy"], ) diff --git a/tests/test_todo.py b/tests/test_todo.py index 2b18705..1859cc3 100644 --- a/tests/test_todo.py +++ b/tests/test_todo.py @@ -7,11 +7,11 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.todo import TodoClient from azure.connectors.todo import ( CreateToDo, CreateToDoList, TRIGGER_OPERATIONS, - TodoClient, ToDoHtml, UpdateToDo, ) @@ -20,6 +20,7 @@ ) from azure.connectors.sdk.serialization import to_wire from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result class TestTodoClientInitialization: @@ -55,7 +56,7 @@ def test_init_with_custom_settings(self, mock_credential): client = TodoClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -121,8 +122,8 @@ def test_todo_html_preserves_colliding_ids(self): assert payload["@odata.id"] == "odata-id" -class TestGetAllTodoListsAsync: - """Tests for get_all_todo_lists_async method.""" +class TestListAllTodoListsAsync: + """Tests for list_all_todo_lists method.""" @pytest.mark.asyncio async def test_success(self, mock_credential): @@ -131,22 +132,21 @@ async def test_success(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"value": [{"id": "list-1"}]}') + mock_response = MockResponse(status=200, text='[{"id": "list-1"}]') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_all_todo_lists_async() + result = await resolve_generated_result(client.list_all_todo_lists()) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert path.endswith("/lists") - assert result is not None - assert "value" in result + assert result == [{"id": "list-1"}] @pytest.mark.asyncio async def test_error_response_raises_exception(self, mock_credential): @@ -159,12 +159,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.get_all_todo_lists_async() + await resolve_generated_result(client.list_all_todo_lists()) class TestGetTodoListAsync: @@ -184,11 +184,11 @@ async def test_success_encodes_folder_id(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_to_do_list_async(folder_id="list 1") + result = await client.get_to_do_list(folder_id="list 1") mock_send.assert_called_once_with( "GET", @@ -208,18 +208,18 @@ async def test_error_response_raises_exception(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=404, text='{"error": "Not found"}') + mock_response = MockResponse(status=500, text='{"error": "Server error"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.get_to_do_list_async(folder_id="missing-list") + await client.get_to_do_list(folder_id="missing-list") - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestCreateTodoListAsync: @@ -237,11 +237,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_to_do_list_async(input=payload) + result = await client.create_to_do_list(input=payload) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -263,12 +263,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException): - await client.create_to_do_list_async(input=payload) + await client.create_to_do_list(input=payload) class TestUpdateTodoListAsync: @@ -289,11 +289,11 @@ async def test_success_encodes_folder_id_and_sends_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.update_to_do_list_async( + result = await client.update_to_do_list( input=payload, folder_id="list 1", ) @@ -321,12 +321,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.update_to_do_list_async( + await client.update_to_do_list( input=payload, folder_id="missing-list", ) @@ -348,11 +348,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.delete_to_do_list_async(folder_id="list 1") + result = await client.delete_to_do_list(folder_id="list 1") mock_send.assert_called_once_with( "DELETE", @@ -372,18 +372,18 @@ async def test_error_response_raises_exception(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=404, text='{"error": "Not found"}') + mock_response = MockResponse(status=500, text='{"error": "Server error"}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.delete_to_do_list_async(folder_id="missing-list") + await client.delete_to_do_list(folder_id="missing-list") - assert exc_info.value.status_code == 404 + assert exc_info.value.status_code == 500 class TestGetTodoAsync: @@ -403,11 +403,11 @@ async def test_success_encodes_folder_and_todo_ids(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_to_do_async( + result = await client.get_to_do( folder_id="list 1", id="task 1", ) @@ -434,12 +434,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.get_to_do_async( + await client.get_to_do( folder_id="list-1", id="missing-task", ) @@ -462,11 +462,11 @@ async def test_create_to_do_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_to_do_async(input=payload, folder_id="list-1") + result = await client.create_to_do(input=payload, folder_id="list-1") mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -489,11 +489,11 @@ async def test_update_to_do_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.update_to_do_async(input=payload, folder_id="list-1", id="task-1") + result = await client.update_to_do(input=payload, folder_id="list-1", id="task-1") mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -518,11 +518,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.delete_to_do_async( + result = await client.delete_to_do( folder_id="list 1", id="task 1", ) @@ -549,12 +549,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: - await client.delete_to_do_async( + await client.delete_to_do( folder_id="list-1", id="task-1", ) @@ -572,22 +572,24 @@ async def test_success_with_top_query(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"value": [{"id": "task-1"}]}') + mock_response = MockResponse(status=200, text='[{"id": "task-1"}]') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_to_dos_by_folder_async(folder_id="list-1", top="10") + result = await resolve_generated_result( + client.list_to_dos_by_folder(folder_id="list-1", top=10) + ) mock_send.assert_called_once() method, path = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert "/lists/list-1/tasks" in path assert "$top=10" in path - assert result is not None + assert result == [{"id": "task-1"}] class TestTodoTriggerOperations: diff --git a/tests/test_trello.py b/tests/test_trello.py index 43a28fa..3d7399b 100644 --- a/tests/test_trello.py +++ b/tests/test_trello.py @@ -2,7 +2,6 @@ """Unit tests for TrelloClient.""" -import inspect from unittest.mock import AsyncMock, patch import pytest @@ -11,85 +10,99 @@ from azure.connectors.sdk import ( ConnectorException, ) +from azure.connectors.aio.trello import TrelloClient from azure.connectors.trello import ( Card, CommentPost, CreateBoard, CreateCard, CreateList, - TrelloClient, TRIGGER_OPERATIONS, UpdateBoard, UpdateCard, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import ( + get_generated_operations, + model_instance, + resolve_generated_result, +) async def _invoke_operation(client: TrelloClient, operation: str): """Invoke a Trello operation by name for shared tests.""" if operation == "list_cards": - return await client.list_cards_async(board_id="board") + return await resolve_generated_result(client.list_cards(board_id="board")) if operation == "list_cards_simple": - return await client.list_cards_simple_async(board_id="board") + return await resolve_generated_result(client.list_cards_simple(board_id="board")) if operation == "get_card": - return await client.get_card_async(card_id="card", board_id="board") + return await client.get_card(card_id="card", board_id="board") if operation == "delete_card": - return await client.delete_card_async(card_id="card", board_id="board") + return await client.delete_card(card_id="card", board_id="board") if operation == "list_boards": - return await client.list_boards_async() + return await resolve_generated_result(client.list_boards()) if operation == "list_boards_simple": - return await client.list_boards_simple_async() + return await resolve_generated_result(client.list_boards_simple()) if operation == "get_board": - return await client.get_board_async(board_id="board") + return await client.get_board(board_id="board") if operation == "update_board": - return await client.update_board_async(input=UpdateBoard(), board_id="board") + return await client.update_board(input=UpdateBoard(), board_id="board") if operation == "list_lists": - return await client.list_lists_async(board_id="board") + return await resolve_generated_result(client.list_lists(board_id="board")) if operation == "list_lists_simple": - return await client.list_lists_simple_async(board_id="board") + return await resolve_generated_result(client.list_lists_simple(board_id="board")) if operation == "get_list": - return await client.get_list_async(list_id="list", board_id="board") + return await client.get_list(list_id="list", board_id="board") if operation == "update_list": - return await client.update_list_async(list_id="list", board_id="board") + return await client.update_list(list_id="list", board_id="board") if operation == "get_user_profile": - return await client.get_user_profile_async() + return await client.get_user_profile() if operation == "list_teams": - return await client.list_teams_async() + return await resolve_generated_result(client.list_teams()) if operation == "list_team_members": - return await client.list_team_members_async(team_id="team") + return await resolve_generated_result(client.list_team_members(team_id="team")) if operation == "list_board_members": - return await client.list_board_members_async(board_id="board") + return await resolve_generated_result(client.list_board_members(board_id="board")) if operation == "list_board_labels": - return await client.list_board_labels_async(board_id="board") + return await resolve_generated_result(client.list_board_labels(board_id="board")) if operation == "get_team_for_board": - return await client.get_team_for_board_async(board_id="board") + return await client.get_team_for_board(board_id="board") if operation == "list_card_members": - return await client.list_card_members_async(card_id="card", board_id="board") + return await resolve_generated_result( + client.list_card_members(card_id="card", board_id="board") + ) if operation == "list_card_comments": - return await client.list_card_comments_async(card_id="card", board_id="board") + return await resolve_generated_result( + client.list_card_comments(card_id="card", board_id="board") + ) if operation == "add_comment_to_card": - return await client.add_comment_to_card_async( + return await client.add_comment_to_card( input=CommentPost(), card_id="card", board_id="board", ) if operation == "add_member_to_card": - return await client.add_member_to_card_async( - card_id="card", - board_id="board", - member_id="member", + return await resolve_generated_result( + client.add_member_to_card( + card_id="card", + board_id="board", + member_id="member", + ) ) if operation == "create_board": - return await client.create_board_async(input=CreateBoard()) + return await client.create_board(input=model_instance(CreateBoard)) if operation == "create_list": - return await client.create_list_async(input=CreateList()) + return await client.create_list(input=model_instance(CreateList)) if operation == "close_board": - return await client.close_board_async(board_id="board") + return await client.close_board(board_id="board") if operation == "create_card": - return await client.create_card_async(input=CreateCard(), board_id="board") + return await client.create_card( + input=model_instance(CreateCard), + board_id="board", + ) if operation == "update_card": - return await client.update_card_async( - input=UpdateCard(), + return await client.update_card( + input=model_instance(UpdateCard), card_id="card", board_id="board", ) @@ -161,7 +174,7 @@ def test_init_with_custom_settings(self, mock_credential): client = TrelloClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -219,13 +232,7 @@ class TestTrelloClientOperations: def test_all_generated_operations_are_covered(self): """Test the operation list matches every generated client method.""" - generated_operations = { - name.removesuffix("_async") - for name, method in inspect.getmembers(TrelloClient, inspect.iscoroutinefunction) - if name.endswith("_async") - } - - assert generated_operations == set(ALL_OPERATIONS) + assert get_generated_operations(TrelloClient) == set(ALL_OPERATIONS) @pytest.mark.asyncio async def test_list_cards_serializes_path_and_query(self, mock_credential): @@ -238,14 +245,16 @@ async def test_list_cards_serializes_path_and_query(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_cards_async( - board_id="board/one", - actions="comment card", - limit="10", + result = await resolve_generated_result( + client.list_cards( + board_id="board/one", + actions="comment card", + limit=10, + ) ) assert result == [{"id": "card"}] @@ -266,11 +275,11 @@ async def test_create_card_sends_request_body(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_card_async(input=request, board_id="board") + result = await client.create_card(input=request, board_id="board") assert result == {"id": "card"} assert mock_send.call_args[0][0] == "POST" @@ -288,11 +297,11 @@ async def test_delete_card_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.delete_card_async(card_id="card", board_id="board") + result = await client.delete_card(card_id="card", board_id="board") assert result is None assert mock_send.call_args[0][0] == "DELETE" @@ -314,7 +323,7 @@ async def test_error_response_raises_connector_exception( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -359,7 +368,7 @@ def test_response_dataclasses_initialize_expected_defaults(self): assert Card().checklists is None def test_request_dataclasses_instantiate(self): - """Test representative request dataclasses instantiate without arguments.""" - assert CreateBoard().name is None - assert CreateCard().name is None - assert CreateList().name is None + """Test representative request dataclasses instantiate with required fields.""" + assert model_instance(CreateBoard).name is not None + assert model_instance(CreateCard).name is not None + assert model_instance(CreateList).name is not None diff --git a/tests/test_twitter.py b/tests/test_twitter.py index 7ef7dd5..fcf35cb 100644 --- a/tests/test_twitter.py +++ b/tests/test_twitter.py @@ -11,25 +11,27 @@ from azure.connectors.sdk import ( ConnectorException, ) -from azure.connectors.twitter import TRIGGER_OPERATIONS, TwitterClient +from azure.connectors.aio.twitter import TwitterClient +from azure.connectors.twitter import TRIGGER_OPERATIONS from tests.conftest import MockResponse from tests.generated_connector_test_utils import ( get_generated_operations, invoke_generated_operation, + resolve_generated_result, ) SUCCESS_CONTRACTS = { - "followers": ("GET", "/followers?userName=value", False), - "following": ("GET", "/friends?userName=value", False), - "home_timeline": ("GET", "/hometimeline", False), - "my_followers": ("GET", "/myfollowers", False), - "my_following": ("GET", "/myfriends", False), + "list_followers": ("GET", "/followers?userName=value", False), + "list_following": ("GET", "/friends?userName=value", False), + "list_home_timeline": ("GET", "/hometimeline", False), + "list_my_followers": ("GET", "/myfollowers", False), + "list_my_following": ("GET", "/myfriends", False), "retweet": ("POST", "/retweet?tweetId=value", False), - "search_tweet": ("GET", "/searchtweets?searchQuery=value", False), + "list_search_tweet": ("GET", "/searchtweets?searchQuery=value", False), "tweet": ("POST", "/posttweet", True), "user": ("GET", "/user?userName=value", False), - "user_timeline": ("GET", "/usertimeline?userName=value", False), + "list_user_timeline": ("GET", "/usertimeline?userName=value", False), } ALL_OPERATIONS = list(SUCCESS_CONTRACTS) @@ -67,7 +69,7 @@ def test_init_with_custom_settings(self, mock_credential): client = TwitterClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) @@ -140,9 +142,16 @@ async def test_generated_operation_success_contract( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, - return_value=MockResponse(status=200, text='{"ok": true}'), + return_value=MockResponse( + status=200, + text=( + '[{"ok": true}]' + if operation.startswith("list_") + else '{"ok": true}' + ), + ), ) as mock_send: result = await invoke_generated_operation(client, operation, twitter_module) @@ -150,7 +159,12 @@ async def test_generated_operation_success_contract( assert method == expected_method assert url.endswith(expected_url_suffix) assert (mock_send.call_args.kwargs["body"] is not None) is expects_body - assert result == {"ok": True} + expected_result = ( + [{"ok": True}] + if operation.startswith("list_") + else {"ok": True} + ) + assert result == expected_result @pytest.mark.asyncio async def test_user_timeline_success(self, mock_credential): @@ -159,20 +173,22 @@ async def test_user_timeline_success(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - response = MockResponse(status=200, text='{"value": []}') + response = MockResponse(status=200, text='[{"id": "tweet-1"}]') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=response, ) as mock_send: - result = await client.user_timeline_async(user_name="Ada Lovelace", max_results="5") + result = await resolve_generated_result( + client.list_user_timeline(user_name="Ada Lovelace", max_results=5) + ) method, url = mock_send.call_args.args[:2] assert method == "GET" assert url.endswith("/usertimeline?userName=Ada%20Lovelace&maxResults=5") - assert result == {"value": []} + assert result == [{"id": "tweet-1"}] @pytest.mark.asyncio async def test_tweet_success(self, mock_credential): @@ -185,11 +201,11 @@ async def test_tweet_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=response, ) as mock_send: - result = await client.tweet_async(input=b"payload", tweet_text="Hello") + result = await client.tweet(input=b"payload", tweet_text="Hello") method, url = mock_send.call_args.args[:2] assert method == "POST" @@ -198,8 +214,8 @@ async def test_tweet_success(self, mock_credential): assert result == {"id": "tweet-1"} @pytest.mark.asyncio - async def test_empty_response_returns_none(self, mock_credential): - """Test an empty successful response returns None.""" + async def test_empty_response_returns_empty_page(self, mock_credential): + """Test an empty successful response returns an empty page.""" client = TwitterClient( "https://example.azure.com/connections/test", credential=mock_credential, @@ -207,13 +223,13 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=204, text=""), ): - result = await client.home_timeline_async() + result = await resolve_generated_result(client.list_home_timeline()) - assert result is None + assert result == [] def test_trigger_metadata(self): """Test polling trigger metadata is registered instead of callable.""" @@ -236,7 +252,7 @@ async def test_non_success_response_raises_exception( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=400, text="bad request"), ): diff --git a/tests/test_typeform.py b/tests/test_typeform.py index 7868684..1002ae2 100644 --- a/tests/test_typeform.py +++ b/tests/test_typeform.py @@ -3,7 +3,8 @@ """Contract tests for TypeformClient.""" import azure.connectors.typeform as typeform_module -from azure.connectors.typeform import TRIGGER_OPERATIONS, TypeformClient +from azure.connectors.aio.typeform import TypeformClient +from azure.connectors.typeform import TRIGGER_OPERATIONS from tests.generated_connector_test_utils import GeneratedConnectorContractTests diff --git a/tests/test_universalprint.py b/tests/test_universalprint.py index 5549f7f..8856683 100644 --- a/tests/test_universalprint.py +++ b/tests/test_universalprint.py @@ -8,23 +8,24 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential -from azure.connectors.universalprint import UniversalprintClient +from azure.connectors.aio.universalprint import UniversalprintClient from azure.connectors.sdk import ( ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import resolve_generated_result async def _invoke_operation(client: UniversalprintClient, operation: str): """Invoke a Universal Print operation by name for shared tests.""" if operation == "print_file": - return await client.print_file_async( + return await client.print_file( input=b"%PDF-1.4 test", printer="printer123", file_name="document.pdf", ) if operation == "list_recent_shares": - return await client.list_recent_shares_async() + return await resolve_generated_result(client.list_recent_shares()) raise ValueError(f"Unsupported operation '{operation}'.") @@ -62,7 +63,7 @@ def test_init_with_custom_settings(self, mock_credential): client = UniversalprintClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -130,11 +131,11 @@ async def test_print_file_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.print_file_async( + result = await client.print_file( input=body, printer="printer123", file_name="document.pdf", @@ -160,11 +161,11 @@ async def test_print_file_includes_query_params(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.print_file_async( + await client.print_file( input=b"%PDF-1.4 test", printer="printer123", file_name="document.pdf", @@ -189,13 +190,13 @@ async def test_list_recent_shares_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.list_recent_shares_async() + result = await resolve_generated_result(client.list_recent_shares()) - assert result["value"][0]["id"] == "share123" + assert result == [{"id": "share123"}] assert mock_send.call_args[0][0] == "GET" assert "/beta/me/print/recentPrinterShares" in mock_send.call_args[0][1] @@ -206,17 +207,17 @@ async def test_list_recent_shares_empty_returns_none(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text="") + mock_response = MockResponse(status=200, text='{"value": []}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.list_recent_shares_async() + result = await resolve_generated_result(client.list_recent_shares()) - assert result is None + assert result == [] class TestUniversalprintClientErrorHandling: @@ -244,7 +245,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -257,21 +258,21 @@ class TestUniversalprintClientSignatures: def test_print_file_required_params_have_no_default(self): """Test printer and file_name are required (no default value).""" - signature = inspect.signature(UniversalprintClient.print_file_async) + signature = inspect.signature(UniversalprintClient.print_file) assert signature.parameters["printer"].default is inspect.Parameter.empty assert signature.parameters["file_name"].default is inspect.Parameter.empty def test_print_file_required_params_annotated_as_str(self): """Test printer and file_name are annotated as str, not Optional.""" - signature = inspect.signature(UniversalprintClient.print_file_async) + signature = inspect.signature(UniversalprintClient.print_file) assert signature.parameters["printer"].annotation == "str" assert signature.parameters["file_name"].annotation == "str" def test_print_file_optional_params_default_to_none(self): """Test optional configuration params default to None.""" - signature = inspect.signature(UniversalprintClient.print_file_async) + signature = inspect.signature(UniversalprintClient.print_file) assert signature.parameters["configuration_copies"].default is None assert signature.parameters["configuration_color_mode"].default is None @@ -285,4 +286,4 @@ async def test_print_file_missing_required_param_raises_type_error(self, mock_cr ) with pytest.raises(TypeError): - await client.print_file_async(input=b"%PDF-1.4 test") + await client.print_file(input=b"%PDF-1.4 test") diff --git a/tests/test_waywedo.py b/tests/test_waywedo.py index 66b26b2..1009246 100644 --- a/tests/test_waywedo.py +++ b/tests/test_waywedo.py @@ -3,7 +3,8 @@ """Contract tests for WaywedoClient.""" import azure.connectors.waywedo as waywedo_module -from azure.connectors.waywedo import TRIGGER_OPERATIONS, WaywedoClient +from azure.connectors.aio.waywedo import WaywedoClient +from azure.connectors.waywedo import TRIGGER_OPERATIONS from tests.generated_connector_test_utils import GeneratedConnectorContractTests @@ -11,17 +12,17 @@ "comment_add": ("POST", True), "checklist_instances": ("POST", True), "checklist_instances_get": ("GET", False), - "checklist_instances_activity": ("GET", False), - "find_steps": ("GET", False), + "list_checklist_instances_activity": ("GET", False), + "list_find_steps": ("GET", False), "checklist_steps_get": ("GET", False), "checklist_steps_complete": ("POST", True), "collaborators_add": ("POST", True), - "find_checklist": ("GET", False), + "list_find_checklist": ("GET", False), "procedures_get": ("GET", False), - "find_checklist_instances": ("GET", False), - "find_user": ("GET", False), + "list_find_checklist_instances": ("GET", False), + "list_find_user": ("GET", False), "users": ("POST", True), - "get_all_checklist_instances": ("GET", False), + "list_all_checklist_instances": ("GET", False), } diff --git a/tests/test_wdatp.py b/tests/test_wdatp.py index b71dcf1..b0fed2e 100644 --- a/tests/test_wdatp.py +++ b/tests/test_wdatp.py @@ -6,8 +6,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.wdatp import WdatpClient from azure.connectors.wdatp import ( - WdatpClient, AdvancedHuntingInput, PatchAlertInput, StartInvestigationInput, @@ -22,7 +22,10 @@ ConnectorException, ) from tests.conftest import MockResponse -from tests.generated_connector_test_utils import resolve_generated_result +from tests.generated_connector_test_utils import ( + model_instance, + resolve_generated_result, +) class TestWdatpClientInitialization: @@ -58,7 +61,7 @@ def test_init_with_custom_settings(self, mock_credential): client = WdatpClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -128,10 +131,10 @@ async def test_advanced_hunting_success(self, mock_credential): } mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = AdvancedHuntingInput(query="DeviceInfo | take 10") - result = await client.advanced_hunting_async(input=input_data) + result = await client.advanced_hunting(input=input_data) mock_send.assert_called_once() call_args = mock_send.call_args @@ -149,11 +152,11 @@ async def test_advanced_hunting_error(self, mock_credential): mock_response = MockResponse(400, "Invalid query") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ): input_data = AdvancedHuntingInput(query="invalid") with pytest.raises(ConnectorException): - await client.advanced_hunting_async(input=input_data) + await client.advanced_hunting(input=input_data) class TestGetAlerts: @@ -176,9 +179,9 @@ async def test_get_alerts_success(self, mock_credential): } mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.get_alerts_async()) + result = await resolve_generated_result(client.list_alerts()) call_args = mock_send.call_args assert call_args[0][0] == "GET" @@ -195,9 +198,9 @@ async def test_get_alerts_with_filter(self, mock_credential): mock_response = MockResponse(200, '{"count": 0, "value": []}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.get_alerts_async(filter="severity eq 'High'")) + await resolve_generated_result(client.list_alerts(filter="severity eq 'High'")) call_args = mock_send.call_args assert "$filter=" in call_args[0][1] @@ -212,9 +215,9 @@ async def test_get_alerts_with_pagination(self, mock_credential): mock_response = MockResponse(200, '{"count": 0, "value": []}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.get_alerts_async(top="10", skip="5")) + await resolve_generated_result(client.list_alerts(top="10", skip="5")) call_args = mock_send.call_args assert "$top=10" in call_args[0][1] @@ -235,9 +238,9 @@ async def test_get_single_alert_success(self, mock_credential): response_data = {"id": "alert-123", "title": "Test Alert", "severity": "High"} mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_single_alert_async(alert_id="alert-123") + result = await client.get_single_alert(alert_id="alert-123") call_args = mock_send.call_args assert "api/alerts/alert-123" in call_args[0][1] @@ -253,10 +256,10 @@ async def test_get_single_alert_not_found(self, mock_credential): mock_response = MockResponse(404, "Alert not found") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException): - await client.get_single_alert_async(alert_id="nonexistent") + await client.get_single_alert(alert_id="nonexistent") class TestPatchAlert: @@ -273,10 +276,10 @@ async def test_patch_alert_success(self, mock_credential): response_data = {"id": "alert-123", "status": "Resolved"} mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = PatchAlertInput(status="Resolved") - result = await client.patch_alert_async(input=input_data, alert_id="alert-123") + result = await client.patch_alert(input=input_data, alert_id="alert-123") call_args = mock_send.call_args assert call_args[0][0] == "PATCH" @@ -304,9 +307,9 @@ async def test_get_machines_success(self, mock_credential): } mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.get_machines_async()) + result = await resolve_generated_result(client.list_machines()) call_args = mock_send.call_args assert "api/machines" in call_args[0][1] @@ -327,9 +330,9 @@ async def test_get_single_machine_success(self, mock_credential): response_data = {"id": "machine-123", "computerDnsName": "TestPC"} mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_single_machine_async(machine_id="machine-123") + result = await client.get_single_machine(machine_id="machine-123") call_args = mock_send.call_args assert "api/machines/machine-123" in call_args[0][1] @@ -350,10 +353,13 @@ async def test_isolate_machine_success(self, mock_credential): response_data = {"id": "action-123", "type": "Isolate", "status": "InProgress"} mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - input_data = IsolateMachineInput(comment="Security investigation") - result = await client.isolate_machine_async( + input_data = model_instance( + IsolateMachineInput, + comment="Security investigation", + ) + result = await client.isolate_machine( input=input_data, machine_id="machine-123" ) @@ -378,10 +384,10 @@ async def test_unisolate_machine_success(self, mock_credential): response_data = {"id": "action-124", "type": "Unisolate", "status": "InProgress"} mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = UnisolateMachineInput(comment="Investigation complete") - await client.unisolate_machine_async( + await client.unisolate_machine( input=input_data, machine_id="machine-123" ) @@ -404,10 +410,10 @@ async def test_run_antivirus_scan_success(self, mock_credential): response_data = {"id": "action-125", "type": "RunAntiVirusScan", "status": "InProgress"} mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = RunAntivirusScanInput(comment="Routine scan", scan_type="Quick") - await client.run_antivirus_scan_async( + await client.run_antivirus_scan( input=input_data, machine_id="machine-123" ) @@ -430,10 +436,10 @@ async def test_collect_investigation_package_success(self, mock_credential): response_data = {"id": "action-126", "type": "CollectInvestigationPackage"} mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = CollectInvestigationPackageInput(comment="Forensic analysis") - await client.collect_investigation_package_async( + await client.collect_investigation_package( input=input_data, machine_id="machine-123" ) @@ -459,9 +465,9 @@ async def test_get_machine_actions_success(self, mock_credential): } mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.get_machine_actions_async()) + result = await resolve_generated_result(client.list_machine_actions()) call_args = mock_send.call_args assert "api/machineactions" in call_args[0][1] @@ -485,9 +491,9 @@ async def test_get_investigations_success(self, mock_credential): } mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.get_investigations_async()) + result = await resolve_generated_result(client.list_investigations()) call_args = mock_send.call_args assert "api/investigations" in call_args[0][1] @@ -508,10 +514,10 @@ async def test_start_investigation_success(self, mock_credential): response_data = {"id": "inv-123", "state": "Running"} mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = StartInvestigationInput(comment="Suspicious activity") - await client.start_investigation_async( + await client.start_investigation( input=input_data, machine_id="machine-123" ) @@ -534,10 +540,10 @@ async def test_add_machine_tag_success(self, mock_credential): response_data = {"id": "machine-123", "machineTags": ["HighValue"]} mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = MachineTagInput(value="HighValue", action="Add") - result = await client.machine_tag_async( + result = await client.machine_tag( input=input_data, machine_id="machine-123" ) @@ -561,9 +567,9 @@ async def test_get_file_stats_success(self, mock_credential): response_data = {"sha1": "abc123", "globallyPrevalence": 100} mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_file_stats_async(file_id="abc123") + result = await client.get_file_stats(file_id="abc123") call_args = mock_send.call_args assert "api/files/abc123/stats" in call_args[0][1] @@ -584,9 +590,9 @@ async def test_get_domain_stats_success(self, mock_credential): response_data = {"host": "example.com", "organizationPrevalence": 50} mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_domain_stats_async(domain_name="example.com") + result = await client.get_domain_stats(domain_name="example.com") call_args = mock_send.call_args assert "api/domains/example.com/stats" in call_args[0][1] @@ -607,9 +613,9 @@ async def test_get_ip_stats_success(self, mock_credential): response_data = {"ipAddress": "192.168.1.1", "organizationPrevalence": 25} mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_ip_stats_async(ip_address="192.168.1.1") + result = await client.get_ip_stats(ip_address="192.168.1.1") call_args = mock_send.call_args assert "api/ips/192.168.1.1/stats" in call_args[0][1] @@ -630,10 +636,10 @@ async def test_restrict_app_execution_success(self, mock_credential): response_data = {"id": "action-127", "type": "RestrictCodeExecution"} mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: input_data = RestrictAppExecutionInput(comment="Containment") - await client.restrict_app_execution_async( + await client.restrict_app_execution( input=input_data, machine_id="machine-123" ) @@ -659,9 +665,9 @@ async def test_get_remediation_activities_success(self, mock_credential): } mock_response = MockResponse(200, json.dumps(response_data)) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock, return_value=mock_response + client._http_client, 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await resolve_generated_result(client.get_remediation_activities_async()) + result = await resolve_generated_result(client.list_remediation_activities()) call_args = mock_send.call_args assert "api/remediationtasks" in call_args[0][1] diff --git a/tests/test_webex.py b/tests/test_webex.py index ef675d1..b1b14ca 100644 --- a/tests/test_webex.py +++ b/tests/test_webex.py @@ -7,18 +7,22 @@ import pytest from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.webex import WebexClient from azure.connectors.webex import ( CreateSpaceInput, CreateSpaceMemberInput, CreateTeamMemberInput, SendMessageInput, TRIGGER_OPERATIONS, - WebexClient, ) from azure.connectors.sdk import ( ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import ( + model_instance, + resolve_generated_result, +) class TestWebexClientInitialization: @@ -54,7 +58,7 @@ def test_init_with_custom_settings(self, mock_credential): client = WebexClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -121,12 +125,16 @@ async def test_create_space_member_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_space_member_async( - input=CreateSpaceMemberInput(room_id="R1", person_email="a@b.com"), + result = await client.create_space_member( + input=model_instance( + CreateSpaceMemberInput, + room_id="R1", + person_email="a@b.com", + ), ) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -142,21 +150,23 @@ async def test_get_messages_success(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"items": []}') + mock_response = MockResponse(status=200, text='{"items": [{"id": "msg1"}]}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_messages_async(room_id="R1") + result = await resolve_generated_result( + client.list_messages(room_id="R1") + ) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert "/v1/messages" in url assert "roomId=R1" in url - assert result == {"items": []} + assert result == [{"id": "msg1"}] @pytest.mark.asyncio async def test_send_message_success(self, mock_credential): @@ -169,11 +179,11 @@ async def test_send_message_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.send_message_async( + result = await client.send_message( input=SendMessageInput(room_id="R1", text="hello"), ) @@ -194,11 +204,11 @@ async def test_get_message_details_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_message_details_async(message_id="msg1") + result = await client.get_message_details(message_id="msg1") method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" @@ -216,17 +226,17 @@ async def test_get_people_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_people_async(email="a@b.com") + result = await resolve_generated_result(client.list_people(email="a@b.com")) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert "/v1/people" in url assert "email=a%40b.com" in url - assert result == {"items": []} + assert result == [] @pytest.mark.asyncio async def test_get_my_own_details_success(self, mock_credential): @@ -239,11 +249,11 @@ async def test_get_my_own_details_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_my_own_details_async() + result = await client.get_my_own_details() method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" @@ -257,20 +267,20 @@ async def test_get_spaces_success(self, mock_credential): "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text='{"items": []}') + mock_response = MockResponse(status=200, text='{"items": [{"id": "R1"}]}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_spaces_async() + result = await resolve_generated_result(client.list_spaces()) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" assert url.endswith("/v1/rooms") - assert result == {"items": []} + assert result == [{"id": "R1"}] @pytest.mark.asyncio async def test_create_space_success(self, mock_credential): @@ -283,11 +293,11 @@ async def test_create_space_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_space_async( + result = await client.create_space( input=CreateSpaceInput(title="My Space"), ) @@ -308,11 +318,11 @@ async def test_get_space_detail_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_space_detail_async(room_id="R1") + result = await client.get_space_detail(room_id="R1") method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] assert method == "GET" @@ -330,12 +340,16 @@ async def test_create_team_member_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.create_team_member_async( - input=CreateTeamMemberInput(team_id="T1", person_email="a@b.com"), + result = await client.create_team_member( + input=model_instance( + CreateTeamMemberInput, + team_id="T1", + person_email="a@b.com", + ), ) method, url = mock_send.call_args[0][0], mock_send.call_args[0][1] @@ -345,23 +359,23 @@ async def test_create_team_member_success(self, mock_credential): assert result == {"id": "tm1"} @pytest.mark.asyncio - async def test_empty_response_body_returns_none(self, mock_credential): - """Test a 2xx response with no body returns None.""" + async def test_empty_page_returns_empty_list(self, mock_credential): + """Test an empty items envelope returns an empty list.""" client = WebexClient( "https://example.azure.com/connections/test", credential=mock_credential, ) - mock_response = MockResponse(status=200, text="") + mock_response = MockResponse(status=200, text='{"items": []}') with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.get_spaces_async() + result = await resolve_generated_result(client.list_spaces()) - assert result is None + assert result == [] class TestWebexClientErrorHandling: @@ -372,12 +386,12 @@ class TestWebexClientErrorHandling: "operation", [ "create_space_member", - "get_messages", + "list_messages", "send_message", "get_message_details", - "get_people", + "list_people", "get_my_own_details", - "get_spaces", + "list_spaces", "create_space", "get_space_detail", "create_team_member", @@ -393,31 +407,37 @@ async def test_error_response_raises_exception(self, mock_credential, operation) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): with pytest.raises(ConnectorException) as exc_info: if operation == "create_space_member": - await client.create_space_member_async(input=CreateSpaceMemberInput()) - elif operation == "get_messages": - await client.get_messages_async(room_id="R1") + await client.create_space_member( + input=model_instance(CreateSpaceMemberInput) + ) + elif operation == "list_messages": + await resolve_generated_result( + client.list_messages(room_id="R1") + ) elif operation == "send_message": - await client.send_message_async(input=SendMessageInput()) + await client.send_message(input=SendMessageInput()) elif operation == "get_message_details": - await client.get_message_details_async(message_id="msg1") - elif operation == "get_people": - await client.get_people_async(email="a@b.com") + await client.get_message_details(message_id="msg1") + elif operation == "list_people": + await resolve_generated_result(client.list_people(email="a@b.com")) elif operation == "get_my_own_details": - await client.get_my_own_details_async() - elif operation == "get_spaces": - await client.get_spaces_async() + await client.get_my_own_details() + elif operation == "list_spaces": + await resolve_generated_result(client.list_spaces()) elif operation == "create_space": - await client.create_space_async(input=CreateSpaceInput()) + await client.create_space(input=model_instance(CreateSpaceInput)) elif operation == "get_space_detail": - await client.get_space_detail_async(room_id="R1") + await client.get_space_detail(room_id="R1") else: - await client.create_team_member_async(input=CreateTeamMemberInput()) + await client.create_team_member( + input=model_instance(CreateTeamMemberInput) + ) assert exc_info.value.status_code == 500 @@ -459,7 +479,6 @@ class TestWebexTypeSerialization: def test_dataclass_defaults(self): """Test dataclasses default to None and reserved names are renamed.""" - assert CreateSpaceInput().title is None - assert CreateSpaceInput().team_id is None + assert model_instance(CreateSpaceInput).team_id is None assert SendMessageInput().room_id is None - assert CreateTeamMemberInput().team_id is None + assert model_instance(CreateTeamMemberInput).person_id is None diff --git a/tests/test_wordonlinebusiness.py b/tests/test_wordonlinebusiness.py index bd3720d..15af148 100644 --- a/tests/test_wordonlinebusiness.py +++ b/tests/test_wordonlinebusiness.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.wordonlinebusiness import WordonlinebusinessClient from azure.connectors.wordonlinebusiness import ( - WordonlinebusinessClient, CreateFileItemInput, ContentBody, BlobMetadata, @@ -17,6 +17,10 @@ ConnectorException, ) from tests.conftest import MockResponse +from tests.generated_connector_test_utils import ( + model_instance, + resolve_generated_result, +) class TestWordonlinebusinessClientInitialization: @@ -52,7 +56,7 @@ def test_init_with_custom_settings(self, mock_credential): client = WordonlinebusinessClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -124,14 +128,14 @@ async def test_create_file_item_success(self, mock_credential): ) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response input_data = CreateFileItemInput( additional_properties={"field1": "value1", "field2": "value2"} ) - result = await client.create_file_item_async( + result = await client.create_file_item( input=input_data, source="me", drive="drive-1", @@ -158,12 +162,12 @@ async def test_create_file_item_empty_response(self, mock_credential): mock_response = MockResponse(status=200, text="") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response input_data = CreateFileItemInput() - result = await client.create_file_item_async( + result = await client.create_file_item( input=input_data, source="me", drive="drive-1", @@ -183,13 +187,13 @@ async def test_create_file_item_error_response(self, mock_credential): mock_response = MockResponse(status=400, text="Bad Request") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response input_data = CreateFileItemInput() with pytest.raises(ConnectorException) as exc_info: - await client.create_file_item_async( + await client.create_file_item( input=input_data, source="me", drive="drive-1", @@ -216,12 +220,12 @@ async def test_create_word_file_success(self, mock_credential): ) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response input_data = ContentBody(content="Hello World document content") - result = await client.create_word_file_with_content_async( + result = await client.create_word_file_with_content( input=input_data, file_name="test.docx" ) @@ -247,12 +251,12 @@ async def test_create_word_file_without_filename(self, mock_credential): ) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response input_data = ContentBody(content="Document content") - result = await client.create_word_file_with_content_async(input=input_data) + result = await client.create_word_file_with_content(input=input_data) call_args = mock_send.call_args assert "fileName=" not in call_args[0][1] @@ -269,12 +273,12 @@ async def test_create_word_file_empty_response(self, mock_credential): mock_response = MockResponse(status=200, text="") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response input_data = ContentBody(content="Content") - result = await client.create_word_file_with_content_async(input=input_data) + result = await client.create_word_file_with_content(input=input_data) assert result is None @@ -289,13 +293,13 @@ async def test_create_word_file_error_response(self, mock_credential): mock_response = MockResponse(status=500, text="Internal Server Error") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response input_data = ContentBody(content="Content") with pytest.raises(ConnectorException) as exc_info: - await client.create_word_file_with_content_async(input=input_data) + await client.create_word_file_with_content(input=input_data) assert exc_info.value.status_code == 500 @@ -313,12 +317,12 @@ async def test_create_word_file_with_special_characters_in_name(self, mock_crede ) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response input_data = ContentBody(content="Content") - await client.create_word_file_with_content_async( + await client.create_word_file_with_content( input=input_data, file_name="my document.docx" ) @@ -345,11 +349,11 @@ async def test_convert_to_pdf_success(self, mock_credential): ) with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - result = await client.get_file_pdf_async( + result = await client.get_file_pdf( source="me", drive="drive-1", file="file-1" @@ -373,11 +377,11 @@ async def test_convert_to_pdf_with_sensitivity_label(self, mock_credential): mock_response = MockResponse(status=200, text="PDF_CONTENT") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.get_file_pdf_async( + await client.get_file_pdf( source="me", drive="drive-1", file="file-1", @@ -400,11 +404,11 @@ async def test_convert_to_pdf_empty_response(self, mock_credential): mock_response = MockResponse(status=200, text="") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - result = await client.get_file_pdf_async( + result = await client.get_file_pdf( source="me", drive="drive-1", file="file-1" @@ -423,12 +427,12 @@ async def test_convert_to_pdf_error_response(self, mock_credential): mock_response = MockResponse(status=404, text="File not found") with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response with pytest.raises(ConnectorException) as exc_info: - await client.get_file_pdf_async( + await client.get_file_pdf( source="me", drive="drive-1", file="file-1" @@ -447,11 +451,11 @@ async def test_get_drives_injects_personal_source(self, mock_credential): mock_response = MockResponse(status=200, text='{"value": []}') with patch.object( - client._http_client, 'send_async', new_callable=AsyncMock + client._http_client, 'send', new_callable=AsyncMock ) as mock_send: mock_send.return_value = mock_response - await client.get_drives_async() + await resolve_generated_result(client.list_drives()) call_args = mock_send.call_args assert "source=me" in call_args[0][1] @@ -473,10 +477,10 @@ def test_create_file_item_input_with_values(self): assert input_data.additional_properties["field1"] == "value1" assert input_data.additional_properties["templateId"] == "abc123" - def test_content_body_defaults(self): - """Test ContentBody default values.""" - body = ContentBody() - assert body.content is None + def test_content_body_required_content(self): + """Test ContentBody requires document content.""" + body = model_instance(ContentBody) + assert body.content == "value" def test_content_body_with_content(self): """Test ContentBody with content.""" diff --git a/tests/test_wordpress.py b/tests/test_wordpress.py index 7fca278..5516bb9 100644 --- a/tests/test_wordpress.py +++ b/tests/test_wordpress.py @@ -9,15 +9,16 @@ from azure.core.credentials import AzureKeyCredential import azure.connectors.wordpress as wordpress_module from azure.connectors.sdk import ConnectorException +from azure.connectors.aio.wordpress import WordpressClient from azure.connectors.wordpress import ( CreatePostModel, TRIGGER_OPERATIONS, - WordpressClient, ) from tests.conftest import MockResponse from tests.generated_connector_test_utils import ( get_generated_operations, invoke_generated_operation, + resolve_generated_result, ) @@ -91,12 +92,17 @@ async def test_generated_operation_success_contract( "https://example.azure.com/connections/test", credential=mock_credential, ) + response_text = ( + '{"sites": [{"ok": true}]}' + if operation == "list_sites" + else '{"ok": true}' + ) with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, - return_value=MockResponse(status=200, text='{"ok": true}'), + return_value=MockResponse(status=200, text=response_text), ) as mock_send: result = await invoke_generated_operation(client, operation, wordpress_module) @@ -104,7 +110,8 @@ async def test_generated_operation_success_contract( assert method == expected_method assert url.endswith(expected_url_suffix) assert (mock_send.call_args.kwargs["body"] is not None) is expects_body - assert result == {"ok": True} + expected_result = [{"ok": True}] if operation == "list_sites" else {"ok": True} + assert result == expected_result @pytest.mark.asyncio async def test_create_post_success(self, mock_credential): @@ -117,11 +124,11 @@ async def test_create_post_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=response, ) as mock_send: - result = await client.create_async( + result = await client.create( input=CreatePostModel(title="Generated SDK", content="Hello"), site_id="site/one", ) @@ -142,16 +149,16 @@ async def test_list_sites_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"sites": []}'), ) as mock_send: - result = await client.list_sites_async() + result = await resolve_generated_result(client.list_sites()) method, url = mock_send.call_args.args[:2] assert method == "GET" assert "/me/sites?fields=" in url - assert result == {"sites": []} + assert result == [] def test_trigger_metadata(self): """Test polling trigger metadata is registered instead of callable.""" @@ -176,7 +183,7 @@ async def test_non_success_response_raises_exception( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=400, text="bad request"), ): diff --git a/tests/test_yammer.py b/tests/test_yammer.py index 8340775..ea86724 100644 --- a/tests/test_yammer.py +++ b/tests/test_yammer.py @@ -5,8 +5,8 @@ import pytest from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.yammer import YammerClient from azure.connectors.yammer import ( - YammerClient, Network, YammerEntity, User, @@ -22,7 +22,10 @@ ) from azure.connectors.sdk.serialization import to_wire from tests.conftest import MockResponse -from tests.generated_connector_test_utils import resolve_generated_result +from tests.generated_connector_test_utils import ( + model_instance, + resolve_generated_result, +) class TestYammerClientInitialization: @@ -64,7 +67,7 @@ def test_init_with_custom_settings(self, mock_credential): client = YammerClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -143,11 +146,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_networks_async() + result = await resolve_generated_result(client.list_networks()) mock_send.assert_called_once() call_args = mock_send.call_args @@ -168,12 +171,12 @@ async def test_error_response_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.get_networks_async() + await resolve_generated_result(client.list_networks()) assert exc_info.value.status_code == 401 @@ -196,11 +199,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_groups_async() + result = await resolve_generated_result(client.list_groups()) mock_send.assert_called_once() call_args = mock_send.call_args @@ -220,21 +223,21 @@ async def test_with_query_parameters(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_groups_async( + await resolve_generated_result(client.list_groups( network_id="net123", - mine="1", - show_all_company_group="true" - ) + mine=1, + show_all_company_group=1, + )) call_args = mock_send.call_args url = call_args[0][1] assert "network_id=net123" in url assert "mine=1" in url - assert "showAllCompanyGroup=true" in url + assert "showAllCompanyGroup=1" in url class TestGetUserDetailsById: @@ -255,11 +258,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - result = await client.get_user_details_by_id_async(user_id="12345") + result = await client.get_user_details_by_id(user_id="12345") mock_send.assert_called_once() call_args = mock_send.call_args @@ -283,11 +286,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.like_message_async(message_id="msg123") + await client.like_message(message_id="msg123") mock_send.assert_called_once() call_args = mock_send.call_args @@ -314,11 +317,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - _ = await resolve_generated_result(client.get_all_messages_async()) + _ = await resolve_generated_result(client.list_all_messages()) mock_send.assert_called_once() call_args = mock_send.call_args @@ -337,11 +340,11 @@ async def test_with_pagination_params(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await resolve_generated_result(client.get_all_messages_async( + await resolve_generated_result(client.list_all_messages( network_id="net123", older_than="100", newer_than="50", @@ -376,11 +379,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - _ = await resolve_generated_result(client.get_messages_following_async()) + _ = await resolve_generated_result(client.list_messages_following()) mock_send.assert_called_once() call_args = mock_send.call_args @@ -406,11 +409,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - _ = await resolve_generated_result(client.get_messages_in_group_async(group_id="123")) + _ = await resolve_generated_result(client.list_messages_in_group(group_id="123")) mock_send.assert_called_once() call_args = mock_send.call_args @@ -436,11 +439,11 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - _ = await resolve_generated_result(client.get_messages_in_thread_async(thread_id="456")) + _ = await resolve_generated_result(client.list_messages_in_thread(thread_id="456")) mock_send.assert_called_once() call_args = mock_send.call_args @@ -480,9 +483,13 @@ async def test_success(self, mock_credential): mock_response = MockResponse( status=201, - text='{"id": 789, "content_excerpt": "New message"}' + text=( + '{"messages": [{"id": 789, ' + '"content_excerpt": "New message"}]}' + ), ) - message_input = PostOperationRequest( + message_input = model_instance( + PostOperationRequest, group_id=123, body="Hello Yammer!", title="Test Post" @@ -490,11 +497,13 @@ async def test_success(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - _ = await client.post_message_async(input=message_input) + _ = await resolve_generated_result( + client.post_message(input=message_input) + ) mock_send.assert_called_once() call_args = mock_send.call_args @@ -509,19 +518,22 @@ async def test_with_network_id(self, mock_credential): credential=mock_credential ) - mock_response = MockResponse(status=201, text='{"id": 789}') - message_input = PostOperationRequest(body="Hello!") + mock_response = MockResponse( + status=201, + text='{"messages": [{"id": 789}]}', + ) + message_input = model_instance(PostOperationRequest, body="Hello!") with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.post_message_async( + await resolve_generated_result(client.post_message( input=message_input, - network_id="net123" - ) + network_id="net123", + )) call_args = mock_send.call_args url = call_args[0][1] @@ -538,16 +550,18 @@ async def test_error_response_raises_exception(self, mock_credential): mock_response = MockResponse( status=403, text='{"error": "Not authorized to post"}' ) - message_input = PostOperationRequest(body="Test") + message_input = model_instance(PostOperationRequest, body="Test") with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await client.post_message_async(input=message_input) + await resolve_generated_result( + client.post_message(input=message_input) + ) assert exc_info.value.status_code == 403 @@ -643,7 +657,8 @@ def test_liked_by(self): def test_post_operation_request(self): """Test PostOperationRequest dataclass creation.""" - request = PostOperationRequest( + request = model_instance( + PostOperationRequest, group_id=123, body="Hello Yammer!", title="Announcement", @@ -656,7 +671,8 @@ def test_post_operation_request(self): def test_current_post_request_uses_swagger_wire_names(self): """Test the current post request preserves its Swagger keys.""" - request = PostOperationRequest( + request = model_instance( + PostOperationRequest, group_id=123, body="Hello Yammer!", replied_to_id=456, @@ -695,12 +711,12 @@ async def test_empty_response_returns_none(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): - result = await client.get_networks_async() - assert result is None + result = await resolve_generated_result(client.list_networks()) + assert result == [] @pytest.mark.asyncio async def test_multiple_consecutive_calls(self, mock_credential): @@ -714,12 +730,12 @@ async def test_multiple_consecutive_calls(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ) as mock_send: - await client.get_networks_async() - await client.get_groups_async() + await resolve_generated_result(client.list_networks()) + await resolve_generated_result(client.list_groups()) assert mock_send.call_count == 2 @@ -737,11 +753,11 @@ async def test_server_error_raises_exception(self, mock_credential): with patch.object( client._http_client, - 'send_async', + 'send', new_callable=AsyncMock, return_value=mock_response ): with pytest.raises(ConnectorException) as exc_info: - await resolve_generated_result(client.get_all_messages_async()) + await resolve_generated_result(client.list_all_messages()) assert exc_info.value.status_code == 500 diff --git a/tests/test_zendesk.py b/tests/test_zendesk.py index 20ba736..efe0f8f 100644 --- a/tests/test_zendesk.py +++ b/tests/test_zendesk.py @@ -8,9 +8,9 @@ from unittest.mock import AsyncMock, patch from azure.core.credentials import AzureKeyCredential +from azure.connectors.aio.zendesk import ZendeskClient from azure.connectors.zendesk import ( Item, - ZendeskClient, TRIGGER_OPERATIONS, ) from azure.connectors.sdk import ( @@ -22,22 +22,24 @@ async def _invoke_operation(client: ZendeskClient, operation: str): """Invoke a Zendesk operation by name for shared tests.""" - if operation == "get_tables": - return await client.get_tables_async() - if operation == "get_items": - return await resolve_generated_result(client.get_items_async(table="tickets")) + if operation == "list_tables": + return await resolve_generated_result(client.list_tables()) + if operation == "list_items": + return await resolve_generated_result(client.list_items(table="tickets")) if operation == "post_item": - return await client.post_item_async(input=Item(), table="tickets") + return await client.post_item(input=Item(), table="tickets") if operation == "get_item": - return await client.get_item_async(table="tickets", id="1") + return await client.get_item(table="tickets", id="1") if operation == "delete_item": - return await client.delete_item_async(table="tickets", id="1") + return await client.delete_item(table="tickets", id="1") if operation == "patch_item": - return await client.patch_item_async(input=Item(), table="tickets", id="1") - if operation == "search_articles": - return await client.search_articles_async(query="password") + return await client.patch_item(input=Item(), table="tickets", id="1") + if operation == "list_search_articles": + return await resolve_generated_result( + client.list_search_articles(query="password") + ) if operation == "get_table": - return await client.get_table_async(table="tickets") + return await client.get_table(table="tickets") raise ValueError(f"Unsupported operation '{operation}'.") @@ -75,7 +77,7 @@ def test_init_with_custom_settings(self, mock_credential): client = ZendeskClient( "https://example.azure.com/connections/test", credential=mock_credential, - timeout_seconds=60.0, + timeout=60.0, max_retry_attempts=5, ) assert client._http_client._timeout_seconds == 60.0 @@ -142,13 +144,13 @@ async def test_get_tables_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_tables_async() + result = await resolve_generated_result(client.list_tables()) - assert result["value"][0]["name"] == "tickets" + assert result == [{"name": "tickets"}] assert mock_send.call_args[0][0] == "GET" assert "/datasets/default/tables" in mock_send.call_args[0][1] @@ -163,11 +165,11 @@ async def test_get_items_includes_query_params(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await resolve_generated_result(client.get_items_async( + await resolve_generated_result(client.list_items( table="tickets", filter="status eq 'open'", top="10", @@ -191,11 +193,11 @@ async def test_post_item_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.post_item_async(input=body, table="tickets") + result = await client.post_item(input=body, table="tickets") assert result["dynamic_properties"]["id"] == 1 assert mock_send.call_args[0][0] == "POST" @@ -213,11 +215,11 @@ async def test_get_item_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_item_async(table="tickets", id="42") + result = await client.get_item(table="tickets", id="42") assert result["dynamic_properties"]["id"] == 42 assert mock_send.call_args[0][0] == "GET" @@ -234,11 +236,11 @@ async def test_delete_item_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.delete_item_async(table="tickets", id="42") + result = await client.delete_item(table="tickets", id="42") assert result is None assert mock_send.call_args[0][0] == "DELETE" @@ -256,11 +258,11 @@ async def test_patch_item_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.patch_item_async(input=body, table="tickets", id="42") + result = await client.patch_item(input=body, table="tickets", id="42") assert result["dynamic_properties"]["id"] == 42 assert mock_send.call_args[0][0] == "PATCH" @@ -278,17 +280,21 @@ async def test_search_articles_includes_query_params(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - await client.search_articles_async(query="password reset", locale="en-us") + result = await resolve_generated_result(client.list_search_articles( + query="password reset", + locale="en-us", + )) request_url = mock_send.call_args[0][1] assert mock_send.call_args[0][0] == "GET" assert "/api/v2/help_center/articles/search" in request_url assert "query=password%20reset" in request_url assert "locale=en-us" in request_url + assert result == [] @pytest.mark.asyncio async def test_get_table_success(self, mock_credential): @@ -301,11 +307,11 @@ async def test_get_table_success(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ) as mock_send: - result = await client.get_table_async(table="tickets") + result = await client.get_table(table="tickets") assert result["name"] == "tickets" assert mock_send.call_args[0][0] == "GET" @@ -322,13 +328,13 @@ async def test_get_tables_empty_returns_none(self, mock_credential): with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): - result = await client.get_tables_async() + result = await resolve_generated_result(client.list_tables()) - assert result is None + assert result == [] class TestZendeskClientErrorHandling: @@ -338,13 +344,13 @@ class TestZendeskClientErrorHandling: @pytest.mark.parametrize( "operation", [ - "get_tables", - "get_items", + "list_tables", + "list_items", "post_item", "get_item", "delete_item", "patch_item", - "search_articles", + "list_search_articles", "get_table", ], ) @@ -362,7 +368,7 @@ async def test_error_response_raises_exception_for_all_operations( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=mock_response, ): @@ -375,14 +381,14 @@ class TestZendeskClientSignatures: def test_search_articles_query_required_and_annotated_str(self): """Test the query parameter is required and annotated as str, not Optional.""" - signature = inspect.signature(ZendeskClient.search_articles_async) + signature = inspect.signature(ZendeskClient.list_search_articles) assert signature.parameters["query"].default is inspect.Parameter.empty assert signature.parameters["query"].annotation == "str" def test_search_articles_optional_params_default_to_none(self): """Test optional search params default to None.""" - signature = inspect.signature(ZendeskClient.search_articles_async) + signature = inspect.signature(ZendeskClient.list_search_articles) assert signature.parameters["locale"].default is None @@ -395,19 +401,19 @@ async def test_search_articles_missing_query_raises_type_error(self, mock_creden ) with pytest.raises(TypeError): - await client.search_articles_async() + await resolve_generated_result(client.list_search_articles()) @pytest.mark.parametrize( "method_name", [ - "get_tables_async", - "get_items_async", - "post_item_async", - "get_item_async", - "delete_item_async", - "patch_item_async", - "search_articles_async", - "get_table_async", + "list_tables", + "list_items", + "post_item", + "get_item", + "delete_item", + "patch_item", + "list_search_articles", + "get_table", ], ) def test_public_methods_have_return_annotation(self, method_name): @@ -416,7 +422,7 @@ def test_public_methods_have_return_annotation(self, method_name): assert signature.return_annotation is not inspect.Signature.empty assert signature.return_annotation in ( - "AsyncIterator[dict[str, Any]]", + "AsyncItemPaged[dict[str, Any]]", "dict[str, Any] | None", "None", ) diff --git a/tests/test_zeptomail.py b/tests/test_zeptomail.py index a8227b1..fd6a92d 100644 --- a/tests/test_zeptomail.py +++ b/tests/test_zeptomail.py @@ -2,19 +2,22 @@ """Contract tests for ZeptomailClient.""" -from typing import Any, Dict, List, Optional, get_type_hints +from typing import Any, Dict, List, Mapping, Optional, get_type_hints from unittest.mock import AsyncMock, patch import azure.connectors.zeptomail as zeptomail_module import pytest +from azure.connectors.aio.zeptomail import ZeptomailClient from azure.connectors.zeptomail import ( ReplyToAddress, SendMailInput, SendTemplateMailInput, - ZeptomailClient, ) from azure.connectors.sdk.serialization import to_wire -from tests.generated_connector_test_utils import GeneratedConnectorContractTests +from tests.generated_connector_test_utils import ( + GeneratedConnectorContractTests, + model_instance, +) from tests.conftest import MockResponse @@ -42,7 +45,8 @@ async def test_send_template_mail_preserves_mixed_values( ) -> None: """Test the template-mail request serializes mixed merge values unchanged.""" type_hints = get_type_hints(SendTemplateMailInput) - model = SendTemplateMailInput( + model = model_instance( + SendTemplateMailInput, merge_key_detail=[{"key": "customer", "value": "Ada", "rank": 2}] ) client = ZeptomailClient( @@ -52,11 +56,11 @@ async def test_send_template_mail_preserves_mixed_values( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"ok": true}'), ) as mock_send: - result = await client.send_template_mail_async(model) + result = await client.send_template_mail(model) assert type_hints["merge_key_detail"] == Optional[List[Dict[str, Any]]] mock_send.assert_awaited_once_with( @@ -77,7 +81,7 @@ async def test_send_template_mail_preserves_mixed_values( def test_reply_to_uses_corrected_model_in_both_requests() -> None: """Test the corrected public type preserves both reply-to annotations.""" - expected_type = Optional[List[ReplyToAddress]] + expected_type = Optional[List[ReplyToAddress | Mapping[str, Any]]] assert get_type_hints(SendMailInput)["reply_to"] == expected_type assert get_type_hints(SendTemplateMailInput)["reply_to"] == expected_type @@ -105,11 +109,11 @@ async def test_get_processed_emails_uses_exact_encoded_query( with patch.object( client._http_client, - "send_async", + "send", new_callable=AsyncMock, return_value=MockResponse(status=200, text='{"data": []}'), ) as mock_send: - result = await client.get_processed_emails_async( + result = await client.get_processed_emails( mailagent_key="agent+key", subject="Quarterly report", from_="sender+alias@example.com", diff --git a/tests/test_zohosign.py b/tests/test_zohosign.py index 2374094..374da4d 100644 --- a/tests/test_zohosign.py +++ b/tests/test_zohosign.py @@ -5,7 +5,8 @@ from typing import get_type_hints import azure.connectors.zohosign as zohosign_module -from azure.connectors.zohosign import ZohosignClient, TRIGGER_OPERATIONS +from azure.connectors.aio.zohosign import ZohosignClient +from azure.connectors.zohosign import TRIGGER_OPERATIONS from tests.generated_connector_test_utils import GeneratedConnectorContractTests @@ -17,7 +18,7 @@ "get_document": ("GET", False), "get_form_data": ("GET", False), "get_template_details": ("GET", False), - "get_templates": ("GET", False), + "list_templates": ("GET", False), "invoke_api": ("POST", True), "recall_document": ("POST", False), "remind_document_recipients": ("POST", False), @@ -54,17 +55,17 @@ def test_document_identifiers_use_integer_annotations() -> None: ] for operation in integer_request_id_operations: - type_hints = get_type_hints(getattr(ZohosignClient, f"{operation}_async")) + type_hints = get_type_hints(getattr(ZohosignClient, f"{operation}")) assert type_hints["request_id"] is int, operation - download_file_hints = get_type_hints(ZohosignClient.download_file_async) + download_file_hints = get_type_hints(ZohosignClient.download_file) assert download_file_hints["document_id"] is int for operation in ["send_sign_request", "update_document"]: - type_hints = get_type_hints(getattr(ZohosignClient, f"{operation}_async")) + type_hints = get_type_hints(getattr(ZohosignClient, f"{operation}")) assert type_hints["request_id"] is str, operation def test_multipart_create_document_is_not_generated() -> None: """Test the unsupported multipart operation is excluded.""" - assert not hasattr(ZohosignClient, "create_document_async") + assert not hasattr(ZohosignClient, "create_document")